【问题标题】:Setting An Attribute On a has_many_through Join Model在 has_many_through 连接模型上设置属性
【发布时间】:2013-09-27 11:21:17
【问题描述】:

我在ContributorResource 之间通过Contributorship 建立了has_many_through 关系。不同寻常的是,当我建立关联时,我需要为 :

设置contribution_type
model Contributor

  has_many contributorships
  has_many contributors, through: contributorships

end

model Resource

  has_many contributorships
  has_many resources, through: contributorships

end

model Contributorships

  attr_accessible :contribution_type, :contributor, :archive_resource

  belongs_to resources
  belongs_to contributors

end

建立关联涉及:

c = Contributor.create!()
r = Resource.create!()
c.contributorships.create!(resource:r,  contribution_type: :author)

或者(如果我不想提前保存):

c = Contributor.new()
r = Resource.new()
cs = Contributorship.new(contributor:c, resource:r,  contribution_type: :author)
c.save!
r.save!
cs.save!

如果我不需要在 Contributorship 加入模型上设置 contribution_type 属性,我可以这样做:

c.resources << r

那么有没有更优雅的方式来做到这一点同时设置属性?

【问题讨论】:

  • 是什么类型的?随机字符串还是数组中的一组预定义值?

标签: ruby-on-rails ruby-on-rails-3 join model has-many-through


【解决方案1】:

您可以使用build 自动设置实例化对象之间的关联。

contributor = Contributor.new
contributor.contributorships.build(:contribution_type => :author)
contributor.resources.build
contributor.save!

【讨论】:

    【解决方案2】:

    如果contributor_type 的值依赖于来自其他模型之一的值,我倾向于只编写一个 before_validation 回调来在每次创建 Contributorships 时设置正确的对应值。即

    model Contributorships
    
      attr_accessible :contribution_type, :contributor, :archive_resource
    
      belongs_to resources
      belongs_to contributors
    
      before_validation :set_contributor_type
    
      def set_contributor_type
         if self.new_record?
            # Whatever code you need to determine the type value
            self.contributor_type = value
         end
      end
    
    end
    

    如果这是用户定义的值,那么您需要使用 accepts_nested_attributes_forin 模型定义您的 contributor_type,然后在表单中使用 fields_for 以允许用户在创建时设置值记录。以下 railscast 非常全面和详细地介绍了这一点:http://railscasts.com/episodes/197-nested-model-form-part-2?view=asciicast

    即:

    <%= form_for(contributor) do |f| %>
       # Whatever fields you want to save for the contributor
       <% contributorship = f.object.contributorships.build %>
       <%= f.fields_for(:contributorships, contributorship) do |new_contributorship| %>
             # Whatever fields you want to save for the contributorship
             <% resource = new_contributorship.object.resources.build %>
             <%= f.fields_for(:resources, resource) do |new_resource| %>
                    # Whatever fields you want to save for the resource
             <% end %>
       <% end %>
    <% end %>
    

    【讨论】:

    • 不错的想法,但不幸的是它不依赖于模型值。
    • 那么,它是由用户设置的吗(即通过表单上的下拉菜单或其他方式?)
    • 是的。每个贡献者都可以拥有contributor_typeauthoreditor
    • 不幸的是,它似乎比这复杂得多。我熟悉使用accepts_nested_attributes_for,但这无助于需要在连接模型上创建或更新属性的问题。如果我想在关联的另一端为模型设置一个属性,这将很有用。这里还有 Railscast 的更新版本:railscasts.com/episodes/…
    • 对不起,我没有正确解释。我遇到了使用accepts_nested_attribues_for 为您的加入模型和孩子。请参阅我的更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 2015-02-17
    • 1970-01-01
    • 2016-05-04
    • 2011-08-24
    • 1970-01-01
    相关资源
    最近更新 更多