【问题标题】:Editing Model Attributes using has_many through使用 has_many 编辑模型属性
【发布时间】:2014-10-23 18:07:20
【问题描述】:

我已成功创建了一个has_many through 与我的两个模型的连接。总而言之,每个艺术家可以属于多个组,反之亦然:

# artist.rb
  has_many :memberships
  has_many :groups, through: :memberships

# membership.rb
  belongs_to :artist
  belongs_to :group

# group.rb
  has_many :memberships
  has_many :artists, through: :memberships

我想做的是设置一个 status 属性,该属性将是一个布尔值,并指示艺术家是否不再属于该组。因此,例如,如果艺术家离开了群组,他/她将被识别为 Past Member 布尔值,名为 status(true = current_member,false = Past_member)。

我不确定一些事情。首先是决定将该属性分配给哪个模型。都是三个吗?是 2/3 还是 1/3?

我遇到的第二个问题是创建一种方法,允许我在艺术家的编辑视图或他们所属的组中更改艺术家的成员身份。我希望做的是,如果从任一视图更改了一个,此更改将反映在两个模型上。

艺术家和团体展览的观点可能会相互反映,所以为了简洁起见,我只列出艺术家的展览观点:

艺术家展览视图

我唯一遇到的问题是尝试列出过去的组。我应该为这个特定场景设置范围还是方法?

<h3>Member of:</h3>
<hr>
<% @artist.groups.each do |group| %>
    <%= artist.group.name %>
    <% if artist.group.status == false %>
        <h3>Past Member of: %></h3>
        <hr>
        <!-- <% Scope or Method that filters Past Groups %> -->
    <% end %>
<% end %>

艺术家编辑视图

对于编辑视图,我似乎无法弄清楚的一件事是嵌套艺术家的每一组。我的语法可能有点偏离,但只是为了让您了解我正在尝试做的事情:

<%= form_for @artist do |f| %>
  <h3>Memberships</h3>
  <% @artist.groups.each do |group| %>
    <%= f.group.radio_button :status, true %>
    <%= f.group.label :status, 'Current Member', value: true %>
    <%= f.group.radio_button :status, false %>
    <%= f.group.label :status, 'Past Member', value: false %>
  <% end %>
  <br>
  <%= f.submit %>
<% end %>

组编辑视图

我假设这看起来几乎与艺术家编辑视图完全相同,但在一定程度上颠倒了:

<%= form_for @group do |f| %>
  <h3>Memberships</h3>
  <% @group.artists.each do |artist| %>
    <div>
      <%= f.artist.radio_button :status, true %>
      <%= f.artist.label :status, 'Current Member', value: true %>
      <%= f.artist.radio_button :status, false %>
      <%= f.artist.label :status, 'Past Member', value: false %>
    </div>
  <% end %>
  <br>
  <%= f.submit %>
<% end %>

如果需要任何控制器逻辑,我会全力以赴。

【问题讨论】:

    标签: ruby-on-rails ruby model associations has-many-through


    【解决方案1】:

    首先,我将其添加到Membership,因为这是关系的真实指标

    由于您正在查看单个组或艺术家,它将是一个实例方法而不是一个范围。类似:

    class Group
      has_many :memberships
      has_many :artists, through: :memberships
      def past_artists
        artists.where(memberships:{status: false})
      end
    end
    #might be User not sure based on your code and your question
    class Artist
      has_many :memberships
      has_many :groups, through: :memberships
      def past_groups
        groups.where(memberships:{status: false})
      end
    end
    

    那么你的组视图应该是这样的

    <% @group.memberships.each do |membership| %>
       <%= render '/memberships/membership_edit_form', membership: membership, obj: @group %>
    <% end %>
    

    并创建一个部分/memberships/_membership_edit_form.html.erb

    <%= form_for membership do |f| %>
       <h5><%= obj.is_a?(Group) ? membership.artist : membership.group %></h5>
       <%= f.label :status, "Current Member?" %>
       <%= f.check_box :status %>
       <%= f.submit %>
    <% end %>
    

    请注意,提交按钮一次只会更新 1 个成员关系。

    要一次更新多个,您应该可以这样做

    <%= form_for @group do |f| %>
      <%= f.fields_for :memberships do |builder| %>
         <%= render '/memberships/membership_fields', f: builder, obj: @group %>
      <% end %>
      <%= f.submit %>
    <% end %>
    

    然后在/memberships/_membership_fields.html.erb中创建一个partial

    <h5><%= obj.is_a?(Group) ? f.object.artist : f.object.group %></h5>
    <%= f.label :status, "Current Member?" %>
    <%= f.check_box :status %>
    

    这应该允许您通过参数将它们全部传递为 [:group][:memberships] 之类的东西,但请注意,我相信要正确更新这些您必须迭代集合。

    【讨论】:

    • 在为我的 membership 模型创建迁移后,我添加了您的答案中提到的两种方法,但是当我在 rails 控制台中尝试这两种方法中的任何一种时,我得到了NameError: undefined local variable or method 'artists'
    • @CarlEdwards 我修复了Artist,它应该说groups,但你的关联Group应该有一个artists方法,因为你有has_many :artists, through: :memberships
    • 让我确保我做对了。在我的 Rails 控制台中,我首先执行了a = Artist.first。然后 g = a.groups.first。我终于做到了g.status,我得到了错误NoMethodError: undefined method 'status' for #&lt;Group:0x007f91e9a829d8&gt;
    • 在插入艺术家的视图代码时也遇到了这个错误:wrong number of arguments (1 for 2..3)
    • @CarlEdwards status 应该是Membership 的一部分,因此您可以执行a = Artist.first 然后运行类似a.memberships.each {|m| puts "Group: #{m.group.name} Status: #{m.status} 的内容,它会输出类似“Group: Group Name Status: false”的内容。艺术家和团体单独没有身份,他们只有一个协会的身份。
    猜你喜欢
    • 1970-01-01
    • 2017-07-01
    • 1970-01-01
    • 2010-11-20
    • 2011-01-12
    • 2011-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多