在Rails中,update_attributes!
的反转是什么?
换句话说,是什么将记录映射到将重新创建该记录及其所有子记录的属性哈希?
答案不是ActiveRecord.attributes
,因为它不会递归到子对象中。
澄清您是否有以下内容:
class Foo < ActiveRecord::Base
has_many :bars
accepts_nested_attributes_for :bars
end
然后你可以传递像
这样的哈希值 {"name" => "a foo", "bars_attributes" => [{"name" => "a bar} ...]}
到update_attributes
。但目前尚不清楚如何以编程方式为此目的轻松生成此类哈希。
编辑:
正如我在评论中提到的,我可以做类似的事情:
foo.as_json(:include => :bars)
但我想要一个使用accepts_nested_attributes_for :bars
声明的解决方案,以避免必须明确包含关联。
答案 0 :(得分:1)
不确定那是怎样的“反向”,但是当Rails可能没有“看到答案”时,没有什么可以阻止你遍历一个对象并有效地创建它。
让你入门的东西:
您会注意到accepts_nested_attributes_for
方法中,rails会在nested_attributes_options
中为嵌套的所有模型设置哈希值。因此,我们可以使用它来获取这些嵌套关联,以填充此新哈希。
def to_nested_hash
nested_hash = self.attributes.delete_if {|key, value| [:id, :created_at, :deleted_at].include? key.to_sym } # And any other attributes you don't want
associations = self.nested_attributes_options.keys
associations.each do |association|
key = "#{association}_attributes"
nested_hash[key] = []
self.send(association).find_each do |child|
nested_hash[key] << child.attributes.delete_if {|key, value| [:id, :created_at, :deleted_at].include? key.to_sym }
end
end
return nested_hash
end
使用上面的示例:
foo.as_json(:include => foo.nested_attributes_options.keys)
有一点需要注意,这不会给我bars_attributes
我的第一个建议。 (serializable_hash
)
答案 1 :(得分:0)
您可以使用以下方法在哈希
中包含嵌套选项class Foo < ActiveRecord::Base
has_many :bars
accepts_nested_attributes_for :bars
def to_nested_hash(options = nil)
options ||= {}
if options[:except]
incl = self.nested_attributes_options.keys.map(&:to_s) - Array(options[:except]).map(&:to_s)
else
incl = self.nested_attributes_options.keys
end
options = { :include => incl }.merge(options)
self.serializable_hash(options)
end
end
如果在某些情况下你不想要酒吧,你可以传递选项
foo.to_nested_hash(:except => :bars)
修改:如果您在as_json
,to_json
和to_xml
class Foo < ActiveRecord::Base
has_many :bars
accepts_nested_attributes_for :bars
def serializable_hash(options = nil)
options ||= {}
if options[:except]
incl = self.nested_attributes_options.keys.map(&:to_s) - Array(options[:except]).map(&:to_s)
else
incl = self.nested_attributes_options.keys
end
options = { :include => incl }.merge(options)
super(options)
end
def to_nested_hash(options = nil)
self.serializable_hash(options)
end
end