accepted_nested_attributes_for别名?

时间:2012-06-18 07:05:10

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

Topic模型中:

class Topic < ActiveRecord::Base
  has_many :choices, :dependent => :destroy
  accepts_nested_attributes_for :choices
  attr_accessible :title, :choices
end

在POST广告期间,提交的params:choices,而不是Rails预期的:choices_attributes,并提供错误:

ActiveRecord::AssociationTypeMismatch (Choice(#70365943501680) expected,
got ActiveSupport::HashWithIndifferentAccess(#70365951899600)):

有没有办法让accepts_nested_attributes_for接受在JSON调用中以choices而不是choices_attributes传递的参数?

目前,我在控制器中进行了属性创建(这似乎不是一个优雅的解决方案):

  def create
    choices = params[:topic].delete(:choices)
    @topic = Topic.new(params[:topic])
    if choices
      choices.each do |choice|
        @topic.choices.build(choice)
      end
    end
    if @topic.save
      render json: @topic, status: :created, location: @topic
    else
      render json: @topic.errors, status: :unprocessable_entity
    end
  end

3 个答案:

答案 0 :(得分:0)

您可以在模型中创建方法choices=

def choices=(params)
  self.choices_attributes = params
end

但是你会打破选择关联的制定者。

最好的方法是修改表单以返回choices_attributes而不是choices

答案 1 :(得分:0)

这是一个较旧的问题,但我遇到了同样的问题。还有其他方法吗?看起来“_attributes”字符串在nested_attributes.rb代码(https://github.com/rails/rails/blob/master/activerecord/lib/active_record/nested_attributes.rb#L337)中是硬编码的。

在提交表单时为属性分配“choices_attributes”很好,但是如果它被用于API则会怎样。在那种情况下它只是没有意义。

在为API传递JSON时,有没有人可以绕过这个或替代方案?

感谢。

更新:

好吧,既然我没有听到任何关于此的更新,我将展示我现在如何解决这个问题。作为Rails的新手,我愿意接受建议,但这是我现在能够解决的唯一方法。

我在API base_controller.rb中创建了一个adjust_for_nested_attributes方法

def adjust_for_nested_attributes(attrs)     
  Array(attrs).each do |param|
    if params[param].present? 
      params["#{param}_attributes"] = params[param]
      params.delete(param)
    end
  end
end

此方法基本上将传入的任何属性转换为#{attr} _attributes,以便它与accepts_nested_attributes_for一起使用。

然后在每个需要此功能的控制器中,我添加了一个像这样的before_action

before_action only: [:create] do 
  adjust_for_nested_attributes(:choices) 
end

现在我只担心创建,但如果你需要更新,你可以将它添加到before_action的'only'子句中。

答案 2 :(得分:0)

  # Adds support for creating choices associations via `choices=value`
  # This is in addition to `choices_attributes=value` method provided by
  # `accepts_nested_attributes_for :choices`
  def choices=(value)
    value.is_a?(Array) && value.first.is_a?(Hash) ? (self.choices_attributes = value) : super
  end