params的顺序停止* _attributes =从工作

时间:2011-05-23 21:51:04

标签: ruby-on-rails ruby-on-rails-3

所以我实施了一个hack,我想知道“正确”的方法是什么。

问题是我有一个使用实例变量的*_attributes=()方法。这是一个问题的原因是,在调用该方法时,尚未设置该实例变量。这是有问题的方法:

def proposed_times_attributes=(attributes)
  attributes.each do |key,value|
    value[:timezone] = timezone
  end
  assign_nested_attributes_for_collection_association(:proposed_times, attributes)
end

时区位于 proposed_times_attributes之后的参数哈希中。因此,我的黑客是从params删除它,然后将其添加回来,从而将其移动到行尾。

def create
  p = params[:consultation]
  a = p.delete(:proposed_times_attributes)
  p[:proposed_times_attributes] = a

  @consultation = current_user.advised_consultations.new(p)
  ...
end

我应该这样做的正确方法是什么?

new()调用load(),其中循环遍历每个键/值对。

值得庆幸的是我使用的是Ruby 1.9.2,它保留了顺序,但知道如何做到这一点会很好,所以它不会依赖于这个事实。

1 个答案:

答案 0 :(得分:0)

如果new之后的下一个操作始终是save操作,您可以将属性存储在访问者中,并使用before_validation回调对其进行操作。

class Consultations < ActiveRecord::Base

  attr_accessor :proposed_times_attributes

  before_validation :assign_proposed_times

  def assign_proposed_times
    proposed_times_attributes.each do |key,value|
      value[:timezone] = timezone
    end
    assign_nested_attributes_for_collection_association(:proposed_times, attributes)
  end

end

现在在您的控制器中,您只需:

def create
  @consultation = current_user.advised_consultations.new(params[:consultation])
  ...
end

如果您希望在调用save之前执行其他操作,那么就像在示例中一样拉出参数,然后在调用new后将其传递给适当的方法将是要走的路