【问题标题】:why are my new and create actions not working with accepts_nested_attributes_for with has_many through?为什么我的 new 和 create 操作不能通过 has_many 与 accept_nested_attributes_for 一起使用?
【发布时间】:2014-01-18 15:54:50
【问题描述】:

我正在使用与 has_many 关联的 3 个模型构建一个 rail 3.2.16 应用程序,但我的保存操作不起作用。这是我的模型:

class Cliente < ActiveRecord::Base
 has_many :prestamos
  accepts_nested_attributes_for :prestamos, reject_if: :all_blank
end

class User < ActiveRecord::Base
  has_many :prestamos
  has_many :clientes, :through => :prestamos
end

class Prestamo < ActiveRecord::Base
  validates_numericality_of :monto, only_integer: true
  validates :monto, presence: true
  belongs_to :user
  belongs_to :cliente, inverse_of: :prestamos
end

当我尝试在 clientes_controller#new 中构建我的@cliente 时

@cliente = current_user.clientes.build

这个在#create

@cliente = current_user.clientes.build(params[:cliente])

并使用此视图

<%= simple_form_for(@cliente) do |f| %>
  <%= f.input :nombre %>
  <%= f.input :cedula %>
  <%= f.input :direccion %>
  <%= f.simple_fields_for :prestamos do |builder| %>
    <%= builder.input :monto %>
  <% end %>
  <%= f.button :submit %>
<% end %>

渲染 HTML 是预期的,但在保存时,我得到了与 prestamo 模型中的 monto 相关的验证错误。顺便说一下,monto字段显示了两次。

我的错误:

Prestamos monto 不是一个数字 Prestamos monto 不能为空

我真的希望有人可以帮助我。

提前致谢。

【问题讨论】:

  • 您是否将User 模型中的prestamos_attributes 列入白名单(使用attr_accessible)?
  • 不,我只是将它添加到我的客户模型中。顺便说一句,我只是添加它来测试它,但错误仍然存​​在。
  • 能否将错误信息添加到问题中?
  • 我刚刚添加了它。是验证错误、存在和数量
  • 您使用了哪些值导致了这些错误?

标签: ruby-on-rails-3 has-many-through has-many


【解决方案1】:

好吧,我可以解决它,但我不确定这是否是最好的方法,因为我是 Rails 的新手(3 个月)。这就是我所做的:

首先,我将我的加入模型 Prestamo 更改为:

class Prestamo < ActiveRecord::Base
  attr_accessible :monto, :user_id, :cliente_id

  validates_numericality_of :monto, only_integer: true
  validates :monto, presence: true

  belongs_to :user
  belongs_to :cliente, inverse_of: :prestamos

end

验证已经存在,我只是将:user_id 添加到attr_accessible

第二,我将新的和创建的操作更改为:

新:

def new
  @cliente = Cliente.new
  @cliente.prestamos.build(user_id: current_user.id)
end

创建:

@cliente = Cliente.new(params[:cliente])

最后,我在表单中添加了一个隐藏字段,只是为了存储 user_id

<%= form.simple_fields_for :prestamos do |f| %>
<%= f.input :monto %>
<%= f.input :user_id, as: :hidden %>
<% end %>

【讨论】:

  • 目前看起来不错,除了一件事:将user_id 存储在隐藏的输入中。不要这样做,因为恶意用户可能会篡改该值,从而导致安全问题。只需删除隐藏的输入并在 create 方法中使用这一行:@cliente = Cliente.new(params[:cliente].merge({user_id: current_user.id})),就完成了。
  • 不工作。无法批量分配 user_id。这是提交的表格:"cliente"=>{"nombre"=>"Name", "cedula"=>"4568213", "direccion"=>"Arabia", "prestamos_attributes"=>{"0"=> {"monto"=>"00000"}}}, "commit"=>"创建客户"}
  • 哦,对不起。改用这个:@cliente = Cliente.new(params[:cliente]); @cliente.prestamos.each { |p| p.user = current_user }.
  • 现在我考虑了您的方法,我认为您不应该让 ClientesController 处理“prestamos”的创建,而是创建一个 LoansController 并在那里处理创建。使其嵌套在客户端资源中。这将让您编写更简洁的代码,如下所示:@loan = @cliente.loans.create(params[:loan].merge(user: current_user))
  • 我的意思是表单应该提交给 Prestamos 控制器的创建操作,像我提到的那样从那里处理创建。 Prestamo 模型不需要accept_nested_attributes_for,因为您是直接创建它们,而不是通过 Cliente 模型。
猜你喜欢
  • 2015-11-08
  • 2014-06-02
  • 2021-04-08
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 2020-10-08
  • 2023-03-24
相关资源
最近更新 更多