ruby-on-rails – 无法使用Devise批量分配受保护的属性以创建has_many嵌套模型

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 无法使用Devise批量分配受保护的属性以创建has_many嵌套模型前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经看过RailsCast,另一个嵌套属性视频,很多SO帖子,并与此争吵了一段时间,但我仍然无法弄明白.我希望它有点小.

我有两个模型,User(由Devise创建)和Locker(又名产品愿望清单),我正在尝试为用户注册时创建一个Locker.我的登录表单有一个新的Locker名称字段(恰当地称为:name),我试图分配给在新用户注册时创建的锁定器.我所遇到的只有:

警告:无法批量分配受保护的属性:locker

我已经在我的两个模型中尝试了accepts_nested_attributes和attr_accesible的每个组合,但仍然无效.我可以从日志中看到它正在由Devise #create方法处理,我知道Devise不够聪明,无法创建我想要的模型:)

这是我的两个模型的相关部分:

  1. # user.rb
  2. class User < ActiveRecord::Base
  3. attr_accessible :username,:email,:password,:password_confirmation,:remember_me,:locker_attributes
  4.  
  5. # Associations
  6. has_many :lockers
  7. has_many :lockups,:through => :lockers
  8.  
  9. # Model nesting access
  10. accepts_nested_attributes_for :lockers
  11. end

  1. # locker.rb
  2. class Locker < ActiveRecord::Base
  3. belongs_to :user
  4. has_many :lockups
  5. has_many :products,:through => :lockups
  6.  
  7. attr_accessible :name,:description
  8. end
  9.  
  10. # lockers_controller.rb (create)
  11. @locker = current_user.lockers.build(params[:locker])
  12. @locker.save

我假设我需要覆盖Devise的创建方法以某种方式让它工作,但我对rails非常新,并且我已经习惯了黑盒子“神奇”的本质.

如果有人能帮助我,我会非常感激.已经花了太多时间在这上面,因为它是:)

编辑:我意识到我在我的问题中省略了一些东西.我的Locker模型有三个属性名称,描述(非强制)和user_id将其链接用户.我的注册表单只需要名称,所以我没有循环遍历嵌套表单中的所有属性.这可能与我的问题有关吗?

编辑2:我也想出了如何覆盖Devise的RegistrationsController #create方法,我只是不知道该放什么. Devise的整个资源对我来说没有意义,浏览他们的RegistrationsController的源代码也没有帮助我.

并且对于奖励积分:当用户使用无效数据提交登录表单时,Locker字段总是空白,而常规的Devise字段,用户名和&电子邮件,已填写.这也可以轻松修复吗?如果是这样,怎么样?

解决方法@H_301_28@
首先,你有一个错字:
  1. attr_accessible :locker_attributes

应该是复数:

  1. attr_accessible :lockers_attributes

那么,使用nested_attributes的标准方法是:

  1. <%= form_for @user do |f| %>
  2. <%# fields_for will iterate over all user.lockers and
  3. build fields for each one of them using the block below,with html name attributes like user[lockers_attributes][0][name].
  4. it will also generate a hidden field user[lockers_attributes][0][id]
  5. if the locker is already persisted,which allows nested_attributes
  6. to know if the locker already exists of if it must create a new one
  7. %>
  8. <% f.fields_for :lockers do |locker_fields| %>
  9. <%= locker_fields.label :name %>
  10. <%= locker_fields.text_field :name %>
  11. <% end %>
  12. <% end %>

在你的控制器:

  1. def new
  2. @user = User.new
  3. @user.lockers.build
  4. end
  5.  
  6. def create
  7. # no need to use build here : params[:user] contains a
  8. # :lockers_attributes key,which has an array of lockers attributes as value ;
  9. # it gets assigned to the user using user.lockers_attributes=,# a method created by nested_attributes
  10. @user = User.new( params[:user] )
  11. end

作为旁注,您可以避免以不同方式为控制器中的新用户构建新的锁定器:

>在User上创建工厂方法,或覆盖new,或使用after_initialize回调以确保每个实例化的新用户自动构建一个锁定器
>将特定对象传递给fields_for:

  1. <% f.fields_for :lockers,f.object.lockers.new do |new_locker_fields| %>

猜你在找的Ruby相关文章