Rails 4嵌套强参数抛出未经编译的参数错误

时间:2014-12-12 00:02:20

标签: ruby-on-rails strong-parameters

我已经在这几个小时了,但无法理解:

尝试在新的组织表单中创建新地址。可以为组织,公司或员工创建地址。我希望与Orgainsation / Company / Employee相关的Address_id存储在他们的数据库记录中,但无法使strong_parameters正常工作。

  

模型/ organisation.rb

class Organisation < ActiveRecord::Base
  belongs_to :address
  has_many :users
  accepts_nested_attributes_for :address
end
  

模型/ address.rb

class Address < ActiveRecord::Base
    has_many :organisations
    has_many :companies
    has_many :employees
end
  

视图/组织/ _form.html.erb

<%= form_for(@organisation) do |f| %>
  <% if @organisation.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@organisation.errors.count, "error") %> prohibited this organisation from being saved:</h2>

  <ul>
  <% @organisation.errors.full_messages.each do |message| %>
    <li><%= message %></li>
  <% end %>
  </ul>
 </div>
<% end %>

<div class="field">
  <%= f.label :name %><br>
  <%= f.text_field :name %>
</div>

<%= f.fields_for @address do |t| %> 
  <div>
    <%= t.label :Line_1 %><br />
    <%= t.text_field :line1 %>
  </div>
  <div>
    <%= t.label :Line_2 %><br />
    <%= t.text_field :line2 %>
  </div>
  <div>
    <%= t.label :Line_3 %><br />
    <%= t.text_field :line3 %>
  </div>
  <div>
    <%= t.label :Line_4 %><br />
    <%= t.text_field :line4 %>
  </div>
  <div>
    <%= t.label :Postcode %><br />
    <%= t.text_field :postcode %>
  </div>     
  <div>
    <%= t.label :Country %><br />
    <%= t.text_field :country %>
  </div>                            
<% end %>

 <div class="field">
 <%= f.label :phone %><br>
 <%= f.text_field :phone %>
 </div>

 <div class="actions">
  <%= f.submit %>
</div>
   
  

控制器/ organisations_controller.rb

class OrganisationsController < ApplicationController
 espond_to :html, :json
 before_action :set_organisation, only: [:show, :edit, :update, :destroy]

 def new
  @organisation = Organisation.new
  @address = Address.new
  respond_with(@organisation)
 end


 def create
  puts "Start of debug"
  puts organisation_params[:address_attributes]
  puts "End of debug"
  @organisation = Organisation.new(organisation_params)
  @address = Address.new(organisation_params[:address_attributes])
  @address.save
  @organisation.address = @address.id
  @organisation.save
  respond_with(@organisation)
 end

 private
 def set_organisation
  @organisation = Organisation.find(params[:id])
 end

 def organisation_params
   params.require(:organisation).permit(:name, :phone, :creator, :contact, :renewal, :approved, :balance, address_attributes:[:line1, :line2, :line3, :line4, :postcode, :country, :organisation_id])
 end
end

但我不断收到以下错误

Started POST "/organisations" for 127.0.0.1 at 2014-12-11 23:40:54 +0000
Processing by OrganisationsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"T2344536dhfjkhkj3eb5g43glwy547fy5p2nbydddfr=", "organisation"=>{"name"=>"The company", "address"=>{"line1"=>"1 The Road", "line2"=>"", "line3"=>"", "line4"=>"", "postcode"=>"", "country"=>"Ireland"}, "phone"=>"01111111"}, "commit"=>"Create Organisation"}
Start of debug
Unpermitted parameters: address

End of debug
Unpermitted parameters: address
Unpermitted parameters: address
   (0.4ms)  BEGIN
  SQL (1.0ms)  INSERT INTO "addresses" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", "2014-12-11 23:40:54.404236"], ["updated_at", "2014-12-11 23:40:54.404236"]]
PG::NotNullViolation: ERROR:  null value in column "line1" violates not-null constraint
DETAIL:  Failing row contains (21, null, null, null, null, null, null, 2014-12-11 23:40:54.404236, 2014-12-11 23:40:54.404236).
: INSERT INTO "addresses" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"
   (0.4ms)  ROLLBACK
Completed 500 Internal Server Error in 7ms

ActiveRecord::StatementInvalid (PG::NotNullViolation: ERROR:  null value in column "line1" violates not-null constraint
DETAIL:  Failing row contains (21, null, null, null, null, null, null, 2014-12-11 23:40:54.404236, 2014-12-11 23:40:54.404236).
: INSERT INTO "addresses" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"):
  app/controllers/organisations_controller.rb:29:in `create'

在我看来,地址没有被创建,因为它无法访问传递的地址属性,但却是“未经许可的参数”。即使我将它包含在organisation_params.permit语句中????

我在这里做错了吗?

  

修改1

根据hkumar的建议,我已编辑views/organisations/_form.html.erb文件,现在说<%= f.fields_for "#{@address}_attributes" do |t| %>

但错误现在看起来像:

 Parameters: {"utf8"=>"✓", "authenticity_token"=>"T2344536dhfjkhkj3eb5g43glwy547fy5p2nbydddfr=", "organisation"=>{"name"=>"The company", "#<Address:0x00000003aa2690>_attributes"=>{"line1"=>"The Road", "line2"=>"", "line3"=>"", "line4"=>"", "postcode"=>"", "country"=>"Ireland"}, "phone"=>"01111111"}, "commit"=>"Create Organisation"}
Start of debug
Unpermitted parameters: #<Address:0x00000003aa2690>_attributes

End of debug
  

修改2

遵循Paul Richter的建议,现在错误是:

Started POST "/organisations" for 127.0.0.1 at 2014-12-12 01:35:13 +0000
Processing by OrganisationsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"T2344536dhfjkhkj3eb5g43glwy547fy5p2nbydddfr=", "organisation"=>{"name"=>"The company", "address_attributes"=>{"line1"=>"The road", "line2"=>"", "line3"=>"", "line4"=>"", "postcode"=>"", "country"=>"Ireland"}, "phone"=>"01111111"}, "commit"=>"Create Organisation"}
Start of debug
{"name"=>"The company", "phone"=>"01111111", "address_attributes"=>{"line1"=>"The road", "line2"=>"", "line3"=>"", "line4"=>"", "postcode"=>"", "country"=>"Ireland"}}
End of debug
   (0.6ms)  BEGIN
  SQL (0.9ms)  INSERT INTO "addresses" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", "2014-12-12 01:35:14.196724"], ["updated_at", "2014-12-12 01:35:14.196724"]]
PG::NotNullViolation: ERROR:  null value in column "line1" violates not-null constraint
DETAIL:  Failing row contains (46, null, null, null, null, null, null, 2014-12-12 01:35:14.196724, 2014-12-12 01:35:14.196724).
: INSERT INTO "addresses" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"
   (0.3ms)  ROLLBACK
Completed 500 Internal Server Error in 57ms

ActiveRecord::StatementInvalid (PG::NotNullViolation: ERROR:  null value in column "line1" violates not-null constraint
DETAIL:  Failing row contains (46, null, null, null, null, null, null, 2014-12-12 01:35:14.196724, 2014-12-12 01:35:14.196724).
: INSERT INTO "addresses" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"):
  app/controllers/organisations_controller.rb:29:in `create'
  

最终修改

感谢Paul Richter,以下代码现在可以使用(对于任何偶然发现它的人):

  

controllers / organisations_controller.rb

class OrganisationsController < ApplicationController
 espond_to :html, :json
 before_action :set_organisation, only: [:show, :edit, :update, :destroy]

 def new
    @organisation = Organisation.new
    @organisation.build_address
 end


 def create
  @organisation = Organisation.new(organisation_params)
  @organisation.save
  respond_with(@organisation)
 end

 private
 def set_organisation
  @organisation = Organisation.find(params[:id])
 end

 def organisation_params
   params.require(:organisation).permit(:name, :phone, :creator, :contact, :renewal, :approved, :balance, address_attributes:[:line1, :line2, :line3, :line4, :postcode, :country, :organisation_id])
 end
end

1 个答案:

答案 0 :(得分:2)

该问题涉及以下形式的这一行:

f.fields_for @address do |t|

控制器中的这一行(显示完整的方法,所以我们都在同一页面上):

def new
  @organisation = Organisation.new
  @address = Address.new  # This line, specifically
  respond_with(@organisation)
end

问题在于,您创建单独的AddressOrganization对象,就好像它们是独立的独立实体一样,但是从Address belongs_to Organization开始(根据您的模型,Address实际上取决于父Organization,因此应该正确关联。

相反,您可能希望这样做:

def new
  @organisation = Organisation.new
  @organization.build_address
 ...

这将设置一个与其父Address相关联的新Organization对象。

然后在表单中,将fields_for行更改为:

f.fields_for :address do |t|

这将调用address对象的@organization方法,[insert 1 magic}将使用accepts_nested_attributes_for的命名约定。

简而言之,您看到错误的原因是,虽然您确实正确设置了强参数,但是将一个单独的,已断开连接的Address对象传递给f.fields_for阻止表单字段被正确命名。

修改

现在表单已正确设置,请将create方法更改为:

def create
  @organisation = Organisation.new(organisation_params)
  @organisation.save
  respond_with(@organisation)
end

在下面的评论中,您提到如何获取我正在创建的地址的ID并将其存储在组织中。需要说明的是,此时地址没有id,但由于您在accepts_nested_attributes_for :address模型中设置了Organization行,因此Rails会创建一个新{{1}通过使用您传入的Address哈希中的Organization参数,已将对象与address_attributes相关联。

这一行(organization_params)为您创建整个结构,只要这些参数符合预期的命名约定即可。(/ p>