0

Topic模型中:

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

在 POST 创建期间,params提交的是:choices,而不是:choices_attributesRails 预期的,并给出错误:

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

有没有办法配置accepts_nested_attributes_for接受参数传递choices而不是choices_attributesJSON 调用?

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

  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
4

3 回答 3

1

这是一个较老的问题,但我遇到了同样的问题。有没有其他方法可以解决这个问题?看起来“_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 的“唯一”子句中。

于 2013-08-15T21:03:26.603 回答
0

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

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

但是你会打破你的选择关联的二传手。

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

于 2012-06-18T08:42:05.780 回答
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
于 2014-08-20T18:13:51.733 回答