为什么这个rails嵌套属性赋值不起作用

时间:2015-12-18 06:38:17

标签: ruby-on-rails ruby

我有一个名为传记的Rails模型,传记有一种生活方式。

class Lifestyle < ActiveRecord::Base
    belongs_to :biography
end

class Biography < ActiveRecord::Base
  has_one :lifestyle, dependent: :destroy
  accepts_nested_attributes_for :lifestyle
end

在我的传记控制器中,我有这个:

def update_biography
  biography = current_user.biography
  logger.debug("params are: #{params}")
  logger.debug("biography_params are: #{biography_params}")
  if biography.update(biography_params)
    render :json => biography
  else
    render :json => { :errors => biography.errors.full_messages }, :status => 400
  end
end

def biography_params
            params.require(:biography).permit(
                                      :disability, :hiv_positive, :blood_type,
                                      lifestyle_attributes: [:id, :diet, :smoke, :drink])
end

这是我从上面的两个logger.debug语句中得到的结果:

params are: {"lifestyle_attributes"=>{"diet"=>"2", "smoke"=>"false", "drink"=>"2"}, "disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3", "controller"=>"biographies", "action"=>"update_biography", "id"=>"4", "biography"=>{"disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3"}}

biography_params are: {"disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3"}

为什么我的传记_params不包含lifestyle_attributes,即使我在传记模型中接受了_nested_attributes_for法则,并且还在模型中定义了传记与生活方式之间的关联?我还在强参数许可列表中添加了lifestyle_attributes。

但是,如果我在rails控制台中运行它,则分配确实有效:

b = Biography.first
b.update("lifestyle_attributes"=>{"diet"=>"2", "smoke"=>"false", "drink"=>"2"})

3 个答案:

答案 0 :(得分:2)

requirepermit实际上是ActionController::Parameters的方法。在这种情况下require :biography需要出现在您从主干视图发送的哈希中。

require方法确保存在特定参数,如果未提供,则require方法会引发错误。它为传递给require ActionController::Parameters的密钥返回:biography的实例。

答案 1 :(得分:1)

你可以尝试

drill.exec: {
  cluster-id: "drillbits1",
  zk.connect: "localhost:2181",
  sys.store.provider.local.path = "/home/dev/abc"
}

如果你不希望params = {biography: {first_name: "new", last_name: "user", disability: false, hiv_positive: false, blood_type: 3, "lifestyle_attributes: {diet: "2", smoke: "false", drink: "2"}} 加上你的参数,你可以忽略biography:上的require(:biography)只是params.require(:biography)

希望现在可行了

您可以获得有关Nested Attributes

的更多信息

答案 2 :(得分:1)

问题是lifestyle_attributes不是biography参数哈希的一部分。你应该

params: {
   biography: {
      lifestyle_attributes: {
         ...
      }
   }
}

这将允许params方法正确访问数据。

要解释它是如何工作的,您需要查看ActionController::Parameters类的工作原理:

  

返回一个新的ActionController::Parameters实例,该实例仅包含给定的过滤器,并将该对象的允许属性设置为true。

每次使用params.require(:x).permit(:y)时,它都会返回一个新的哈希值,允许的参数。这些允许的参数必须嵌套在 required 参数中。

正如您所展示的,这很有效......

  

传记_params是:{"disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3"}

问题在于,因为lifestyle_attributes 嵌套在biography下,因此在调用params方法后不会返回其参数。

此修复程序将采用格式

#app/views/biographies/new.html.erb
<%= form_for @biography do |f| %>
   <%= ... biography attributes %>
   <%= f.fields_for :lifestyle do |l| %>
      <%= lifestyle fields %>
   <% end %>
   <%= f.submit %>
<% end %>

我目前还不知道你是如何做到的,但不知何故,你已经在lifestyle哈希之外附加了biography个属性。