【问题标题】:In Rails, what is the inverse of update_attributes?在 Rails 中,update_attributes 的倒数是什么?
【发布时间】:2014-02-20 01:04:49
【问题描述】:

在 Rails 中,update_attributes! 的倒数是什么?

换句话说,什么将记录映射到属性散列,从而重新创建该记录及其所有子记录?

答案不是ActiveRecord.attributes,因为它不会递归到子对象中。

澄清您是否有以下情况:

class Foo < ActiveRecord::Base
  has_many :bars
  accepts_nested_attributes_for :bars
end

然后你可以传递一个像这样的哈希

{"name" =&gt; "a foo", "bars_attributes" =&gt; [{"name" =&gt; "a bar} ...]}

update_attributes。但目前尚不清楚如何为此目的以编程方式轻松生成这样的哈希。

编辑:
正如我在评论中提到的,我可以这样做:
foo.as_json(:include =&gt; :bars)

但我想要一个使用accepts_nested_attributes_for :bars 声明的解决方案,以避免必须明确包含关联。

【问题讨论】:

  • “将重新创建该记录及其所有子记录”是什么意思?
  • 生成散列相当容易,使用与响应 JSON 关系相同的方法,然后将其解析为散列。 (不过,并不是说这是最有效的方法。)
  • 试试obj.association_cache,它会给你更多的哈希
  • @DaveNewton,我可以根据需要使用as_jsonto_json,但是我必须传入一个哈希值,例如{:include =&gt; {:bars =&gt; {:include =&gt; :bazs}}} ...。我希望避免这种情况,因为模型已经知道 accept_nested_attributes 的用途。
  • @z5h 是的,没错。可能有一个嵌套的哈希 AR/对象转储器,但肯定有。

标签: ruby-on-rails ruby activerecord


【解决方案1】:

不确定这会是怎样的“逆向”,但尽管 Rails 可能无法“获得答案”,但没有什么能阻止您遍历对象并非常有效地创建它。

让你开始的东西:

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for

您会注意到在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 也不会)

【讨论】:

    【解决方案2】:

    您可以使用以下方法在哈希中包含嵌套选项

    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_jsonto_jsonto_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
    

    【讨论】:

      猜你喜欢
      • 2018-09-18
      • 1970-01-01
      • 1970-01-01
      • 2019-02-21
      • 2016-09-16
      • 1970-01-01
      • 2011-05-06
      • 2011-02-16
      • 1970-01-01
      相关资源
      最近更新 更多