通过has_many:through with:conditions保存连接属性

Mar*_*tto 5 activerecord ruby-on-rails data-modeling relationship has-many-through

我有一个看起来像这样的Artist模型:

# app/models/artist.rb
class Artist < ActiveRecord::Base
  # Relationships
  has_many  :releases
  has_many  :songs, :through => :releases
  has_many  :featured_songs,  :through => :releases,
                              :class_name => "Song",
                              :source => :song,
                              :conditions => { 'releases.featured', true }                         

end
Run Code Online (Sandbox Code Playgroud)

检索featured_songs非常有效.这里的问题是我无法向艺术家添加新的feature_song,因为出于某种原因,'featured'属性被设置为'nil'.

这就是我正在尝试的:

ruby-1.9.2-p180 :004 > a = Artist.first
ruby-1.9.2-p180 :005 > a.featured_songs.create(:title => "Title", :user => User.first)
Run Code Online (Sandbox Code Playgroud)

实际结果是:

ruby-1.9.2-p180 :004 > a = Artist.first
ruby-1.9.2-p180 :005 > a.featured_songs.create(:title => "Title", :user => User.first)
  User Load (0.9ms)  SELECT `users`.* FROM `users` LIMIT 1
  SQL (1.0ms)  BEGIN
  SQL (5.5ms)  INSERT INTO `songs` (`created_at`, `title`, `updated_at`, `user_id`) VALUES (?, ?, ?, ?)  [["created_at", Thu, 11 Aug 2011 18:30:34 UTC +00:00], ["title", "Title"], ["updated_at", Thu, 11 Aug 2011 18:30:34 UTC +00:00], ["user_id", 1]]
  SQL (1.2ms)  INSERT INTO `releases` (`album_id`, `artist_id`, `created_at`, `featured`, `song_id`, `updated_at`) VALUES (?, ?, ?, ?, ?, ?)  [["album_id", nil], ["artist_id", 1], ["created_at", Thu, 11 Aug 2011 18:30:34 UTC +00:00], ["featured", nil], ["song_id", 6], ["updated_at", Thu, 11 Aug 2011 18:30:34 UTC +00:00]]
   (0.1ms)  COMMIT
Run Code Online (Sandbox Code Playgroud)

注意: ["featured", nil]

知道我做错了什么吗?如何在不直接访问连接的情况下正确设置连接的属性?

谢谢!

编辑:使我的问题更清楚:

  • 从艺术家的例子来看,我无法通过这种featured_songs关系创作新的特色歌曲

  • 保存似乎是将所有歌曲属性设置为EXCEPT(最重要的一个) featured

  • featured属性nil由于某种原因被设置为,这是真正的问题.

ada*_*mar 0

编辑:更新:releases_attributes 以反映 has_many 关系。

杰德尔的回答是正确的。这是一个解决的问题accepts_nested_attributes_forhas_many仅描述查询记录的机制,而不是更新或创建记录的机制。

您列出的属性被更新的原因是因为它们是歌曲对象的一部分。您尝试更新的字段是特色字段,它是releases连接表的一部分。

accepts_nested_attributes_for是解决更新嵌套关系问题的工具。如果您想在创建歌曲对象期间添加特色属性(如您在示例中所做的那样),那么您需要将其添加为 Song 类的嵌套属性的一部分。

class Song < ActiveRecord::Base
  has_many :releases
  has_many :artists, :through => :releases
  accepts_nested_attributes_for :releases
end
Run Code Online (Sandbox Code Playgroud)

然后你create会看起来像这样:

a.songs.create(:title => 'Title', :user => User.first, :releases_attributes => [{ :id => 123, :featured => true}])
Run Code Online (Sandbox Code Playgroud)

请注意添加_attributes。如果您使用嵌套表单,这正是 Rails 在视图中执行的操作。请参阅 ActiveRecord 源文件nested_attributes.rb以获取证明。

如果您确实想要一种更简洁的方法来完成此操作,您可以添加一个Song#create_featured方法,将:releases_attributes哈希值合并到#create.