Eu tenho um Bill
objeto, que tem muitos Due
objetos. O Due
objeto também pertence a um Person
. Eu quero um formulário que pode criar o Bill
e seus filhosDues
em uma página. Estou tentando criar um formulário usando atributos aninhados, semelhantes aos deste Railscast .
O código relevante está listado abaixo:
due.rb
class Due < ActiveRecord::Base
belongs_to :person
belongs_to :bill
end
bill.rb
class Bill < ActiveRecord::Base
has_many :dues, :dependent => :destroy
accepts_nested_attributes_for :dues, :allow_destroy => true
end
bills_controller.rb
# GET /bills/new
def new
@bill = Bill.new
3.times { @bill.dues.build }
end
bills / _form.html.erb
<%= form_for(@bill) do |f| %>
<div class="field">
<%= f.label :company %><br />
<%= f.text_field :company %>
</div>
<div class="field">
<%= f.label :month %><br />
<%= f.text_field :month %>
</div>
<div class="field">
<%= f.label :year %><br />
<%= f.number_field :year %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<%= f.fields_for :dues do |builder| %>
<%= render 'due_fields', :f => builder %>
<% end %>
<% end %>
bills / _due_fields.html.erb
<div>
<%= f.label :amount, "Amount" %>
<%= f.text_field :amount %>
<br>
<%= f.label :person_id, "Renter" %>
<%= f.text_field :person_id %>
</div>
ATUALIZAÇÃO para bills_controller.rb Isso funciona!
def bill_params
params
.require(:bill)
.permit(:company, :month, :year, dues_attributes: [:amount, :person_id])
end
Os campos adequados são renderizados na página (embora ainda não haja um menu suspenso Person
) e o envio é bem-sucedido. No entanto, nenhuma das taxas filhas é salva no banco de dados e um erro é gerado no log do servidor:
Unpermitted parameters: dues_attributes
Pouco antes do erro, o log exibe isso:
Started POST "/bills" for 127.0.0.1 at 2013-04-10 00:16:37 -0700
Processing by BillsController#create as HTML<br>
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"ipxBOLOjx68fwvfmsMG3FecV/q/hPqUHsluBCPN2BeU=",
"bill"=>{"company"=>"Comcast", "month"=>"April ",
"year"=>"2013", "dues_attributes"=>{
"0"=>{"amount"=>"30", "person_id"=>"1"},
"1"=>{"amount"=>"30", "person_id"=>"2"},
"2"=>{"amount"=>"30", "person_id"=>"3"}}}, "commit"=>"Create Bill"}
Houve alguma mudança no Rails 4?
ruby-on-rails
ruby-on-rails-4
jcanipar
fonte
fonte
Respostas:
Parece que houve uma alteração no manuseio da proteção de atributos e agora você deve colocar os parâmetros da lista de permissões no controlador (em vez de attr_accessible no modelo) porque a antiga gema opcional strong_parameters se tornou parte do Rails Core.
Isso deve ser algo como isto:
Então
params.require(:model).permit(:fields)
seria usadoe para atributos aninhados algo como
Mais detalhes podem ser encontrados nos documentos da API do Ruby edge e em strong_parameters no github ou aqui
fonte
def bill_params params.require(:bill).permit(:company, :month, :year, :dues_attributes[:amount, :person_id]) end
Agora estou recebendo este erro: nenhuma conversão implícita de símbolo para Integerpets_attributes: [:id, :name, :category]
Caso contrário, quando você editar, cada animal será criado novamente.Person.create(person_params)
ou não chamará o método Em vez disso, você receberáActiveModel::ForbiddenAttributesError
.:_destroy
parâmetro oculto . ou sejapets_attributes: [:id, :name, :category, :_destroy]
Dos documentos
Atributos aninhados estão na forma de um hash. No meu aplicativo, tenho um modelo Question.rb que aceita atributos aninhados para um modelo Answer.rb (onde o usuário cria opções de resposta para uma pergunta que ele cria). No questions_controller, faço isso
Tudo no hash da pergunta é permitido, incluindo os atributos de resposta aninhada. Isso também funciona se os atributos aninhados estiverem na forma de uma matriz.
Dito isso, pergunto-me se há uma preocupação de segurança com essa abordagem, porque ela basicamente permite qualquer coisa que esteja dentro do hash sem especificar exatamente o que é, o que parece contrário ao objetivo de parâmetros fortes.
fonte
.permit!
a única opção? Não consigo fazê-lo funcionar mesmo com todos os atributos do modelo permitidos porque ele engasga com a matriz.ou você pode simplesmente usar
fonte
Na verdade, existe uma maneira de apenas listar todos os parâmetros aninhados.
Este método tem vantagem sobre outras soluções. Permite permitir parâmetros profundamente aninhados.
Enquanto outras soluções, como:
Não.
Fonte:
https://github.com/rails/rails/issues/9454#issuecomment-14167664
fonte
Hoje me deparei com esse mesmo problema, enquanto trabalhava no trilhos 4, consegui fazê-lo estruturando meus campos_para:
Então, no meu controlador, tenho meus parâmetros fortes como:
Tudo funciona!
fonte
Se você usar um campo JSONB, deverá convertê-lo em JSON com .to_json (ROR)
fonte