无法获得嵌套模型值

时间:2015-10-04 02:05:40

标签: ruby-on-rails devise

我想创建BuyerSeller模型,可以通过devise进行身份验证。

应用程序/模型/ buyer.rb

class Buyer < ActiveRecord::Base
  has_one :user, as: :authable
  accepts_nested_attributes_for :user
end

应用程序/控制器/ buyers_controller.rb

class BuyersController < ApplicationController
  def new
    @buyer = Buyer.new
    @buyer.build_user
  end
  def create
    @buyer = Buyer.new(buyer_params)
    respond_to do |format|
      if @buyer.save
        format.html { redirect_to @buyer, notice: 'Buyer was successfully created.' }
        format.json { render :show, status: :created, location: @buyer }
      else
        format.html { render :new }
        format.json { render json: @buyer.errors, status: :unprocessable_entity }
      end
    end
  end
   def buyer_params
      params.require(:buyer).permit(user_attributes: [:email, :password, :password_confirmation])
    end
end

应用程序/视图/买家/ new.html.erb

<%= form_for(@buyer) do |f| %>
    <%= f.fields_for @buyer.user do |user| %>
        <%= user.email_field :email %>
    <% end %>
    <div class="actions">
      <%= f.submit %>
    </div>
<% end %>

使用这些代码,我可以创建Buyer,但买家没有用户。

我似乎在permit

中写错了方法
>> params
=> {"utf8"=>"✓", "authenticity_token"=>"xxx", "buyer"=>{"user"=>{"email"=>"bar@example.com"}}, "commit"=>"Create Buyer", "controller"=>"buyers", "action"=>"create"}
>>  buyer_params
=> {}

如果我将user_attributes更改为user,我可以获得email参数,但后来收到错误:User(#70323929049400) expected, got ActionController::Parameters(#70323888554040)

如何解决此错误?

修改

感谢Brian的帮助,我可以通过以下方式删除错误:

def buyer_params
  params[:buyer][:user_attributes] = params[:buyer][:user] if params[:buyer][:user].present?
  params.require(:buyer).permit(user_attributes: [:email, :password, :password_confirmation])
end

但我不认为这是一种正确的写作方式。我为它创建了一个存储库。如果你能查一下,我很高兴。

https://github.com/ironsand/polymorphic-authable-by-devise

我做的是:

  1. 创建App。
  2. 通过设计创建用户模型。
  3. 通过脚手架创建卖方和买方模型。
  4. 两个模型的用户均为authable

3 个答案:

答案 0 :(得分:1)

我可能误解了这个问题,但它似乎已经接受了_ented_attributes_for&#39;要求:user_attributes但表单返回a:user。一个(也许是不优雅的)解决方案是做这样的事情:

def buyer_params
  params[:user_attributes] = params[:user] if params[:user].present?
  params.require(:buyer).permit(user_attributes: [:email, :password, :password_confirmation])
end

假设这有效并且您应用类似的类似代码来创建卖家,则警告相同的用户可能无法同时成为买方和卖方。

答案 1 :(得分:1)

更好的主意......

为什么不在单个roles模型上设置UserSTI

虽然您可以为Devise创建单独的模型,但在您的情况下,似乎有点不必要,尤其是当您关联Buyer belongs_to User时...

如果您通过User填充Devise模型,并通过rolesSTI功能进行推断,效率会更高:

<强> STI

Here's a tutorial with EXACTLY this functionality

您可以相对简单地设置STI:

#app/models/buyer.rb
class Buyer < User
end

#app/models/seller.rb
class Seller < User
end

#app/models/user.rb
class User < ActiveRecord::Base
   #Devise stuff here
end

然后,您就可以像使用自己的表一样使用模型......

@buyer = Buyer.find params[:id]
@buyer.email 

这将允许您设置必要的表格和控制器,以方便买家或卖家的注册过程......

#config/routes.rb
devise_for :users,   skip: :registrations
devise_for :sellers, skip: :sessions
devise_for :buyers,  skip: :sessions

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
   def configure_permitted_parameters
      devise_parameter_sanitizer.for(:sign_up) << :type
   end
end

<强>角色

另一种方法是use roles

我们经常使用它 - 在role_id表中设置users以赋予它们某些特权:

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
   def configure_permitted_parameters
      devise_parameter_sanitizer.for(:sign_up) << :role_id
   end
end

#app/models/user.rb
class User < ActiveRecord::Base
   ## Devise Stuff ##
   before_create :set_role
   belongs_to :role

   private

   def set_role
      self.role = Role.find_by(name: "buyer") unless role?
   end
end

-

我认为您当前的设置非常低效,以至于妨碍了未来的可扩展性。

答案 2 :(得分:0)

使用嵌套属性时,您必须将关联名称传递给$.ajax({ url: 'https://en.wikipedia.org/w/api.php', data: { action: 'query', list: 'search', srsearch: searchString, // variable pulled from input format: 'json', //origin: 'https://www.mediawiki.org' }, xhrFields: { withCredentials: true }, dataType: 'jsonp' // will probably use 'json' now that I'm server-side }).done( function ( data ) { searchParser(data); }); ... //searchParser() below ,在您的情况下:

fields_for