Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails 4.1使用Desive ForbiddenAttributes错误为多个角色注册多态关联_Ruby On Rails_Ruby_Ruby On Rails 4_Devise_Polymorphic Associations - Fatal编程技术网

Ruby on rails Rails 4.1使用Desive ForbiddenAttributes错误为多个角色注册多态关联

Ruby on rails Rails 4.1使用Desive ForbiddenAttributes错误为多个角色注册多态关联,ruby-on-rails,ruby,ruby-on-rails-4,devise,polymorphic-associations,Ruby On Rails,Ruby,Ruby On Rails 4,Devise,Polymorphic Associations,我是Rails新手,所以我从Rails4开始学习它。我必须创建两种类型的用户——客户和公司,所以我决定使用多态关联。现在,我正在尝试使用Desive(3.4.0版)对这些型号进行注册和验证。我在这里寻找解决方案,发现了一些问题,但据我所知,它只适用于Rails3。在Rails 4上,我无法解决许可属性的问题,并且不断出现错误ActiveModel::ForbiddenAttributesError 用户模型 模式 模型 模型 模型 注册视图 #views/registration/new.htm

我是Rails新手,所以我从Rails4开始学习它。我必须创建两种类型的用户——客户和公司,所以我决定使用多态关联。现在,我正在尝试使用Desive
(3.4.0版)
对这些型号进行注册和验证。我在这里寻找解决方案,发现了一些问题,但据我所知,它只适用于Rails3。在Rails 4上,我无法解决许可属性的问题,并且不断出现错误
ActiveModel::ForbiddenAttributesError

用户模型 模式 模型 模型 模型 注册视图

#views/registration/new.html.erb
<h2>Sign up</h2>

<%
  # customized code begin

  params[:user][:user_type] ||= 'client'

  if ["client", "company"].include? params[:user][:user_type].downcase
    child_class_name = params[:user][:user_type].downcase.camelize
    user_type = params[:user][:user_type].downcase
  else
    child_class_name = "Client"
    user_type = "client"
  end

  resource.role = child_class_name.constantize.new if resource.role.nil?

  # customized code end
%>

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
  <% my_devise_error_messages!    # customized code %>

  <div><%= f.label :email %><br />
  <%= f.email_field :email %></div>

  <div><%= f.label :password %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation %></div>

  <% # customized code begin %>
  <%= fields_for resource.role do |rf| %>
    <% render :partial => "#{child_class_name.underscore}_fields", :locals => { :f => rf } %>
  <% end %>

  <%= hidden_field :user, :user_type, :value => user_type %>
  <% # customized code end %>

  <div><%= f.submit "Sign up" %></div>
<% end %>

<%= render :partial => "devise/shared/links" %>

调试信息:

sign_up_params: {"email"=>"example@expample.com", "password"=>"12345678", "password_confirmation"=>"12345678", "user_type"=>"company", "company"=>{"company_name"=>"expample company name", "company_tel"=>"223-2323-2"}}
user_params: {"email"=>"example@expample.com", "password"=>"12345678", "password_confirmation"=>"12345678"}
user_type: company
child_class_params: {"company_name"=>"expample company name", "company_tel"=>"223-2323-2"}
您可以看到,所有必要的参数都通过
sign\u-up\u-params

那么为什么会出现错误
禁止属性

问题解决后,可能对某些人有用 我仍然不明白问题是什么,但我做到了:

resource.role = child_class.new(child_class_params.symbolize_keys)
它开始工作时没有出错

class Client < ActiveRecord::Base
  has_one :user, :as => :role
end
t.string   "company_name"
t.datetime "created_at"
t.datetime "updated_at"
t.string   "company_tel"
class Company < ActiveRecord::Base
  has_one :user, :as => :role
end
devise_for :users, :controllers => { :registrations => 'registrations' }
  resources :users

  devise_scope :user do 
    get 'client/sign_up' => 'registrations#new', :user => { :user_type => 'client' }
    get 'company/sign_up' => 'registrations#new', :user => { :user_type => 'company' }
  end
#views/registration/new.html.erb
<h2>Sign up</h2>

<%
  # customized code begin

  params[:user][:user_type] ||= 'client'

  if ["client", "company"].include? params[:user][:user_type].downcase
    child_class_name = params[:user][:user_type].downcase.camelize
    user_type = params[:user][:user_type].downcase
  else
    child_class_name = "Client"
    user_type = "client"
  end

  resource.role = child_class_name.constantize.new if resource.role.nil?

  # customized code end
%>

<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
  <% my_devise_error_messages!    # customized code %>

  <div><%= f.label :email %><br />
  <%= f.email_field :email %></div>

  <div><%= f.label :password %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation %></div>

  <% # customized code begin %>
  <%= fields_for resource.role do |rf| %>
    <% render :partial => "#{child_class_name.underscore}_fields", :locals => { :f => rf } %>
  <% end %>

  <%= hidden_field :user, :user_type, :value => user_type %>
  <% # customized code end %>

  <div><%= f.submit "Sign up" %></div>
<% end %>

<%= render :partial => "devise/shared/links" %>
#views/registration/_client_fields.html.erb
<div><%= f.label :client_name %><br />
<%= f.text_field :client_name %></div>
#views/registration/_company_fields.html.erb
<div><%= f.label :company_name %><br />
<%= f.text_field :company_name %></div>

<div><%= f.label :company_tel %><br />
<%= f.text_field :company_tel %></div>
#controllers/registration_controller.rb
class RegistrationsController < Devise::RegistrationsController
  def create
    user_params        = sign_up_params # is sign_up_params not able to edit?
    user_type          = user_params.delete (:user_type) #take out user_type from user_params
    child_class_params = user_params.delete (user_type.to_s.underscore.to_sym) #obtain a nested hash (:company or :client)

    logger.debug "sign_up_params: #{sign_up_params}"         #DEBUG
    logger.debug "user_params: #{user_params}"               #DEBUG
    logger.debug "user_type: #{user_type}"                   #DEBUG
    logger.debug "child_class_params: #{child_class_params}" #DEBUG

    build_resource(user_params)

    # crate a new child instance depending on the given user type
    child_class = user_type.camelize.constantize

    resource.role = child_class.new(child_class_params)

    # first check if child instance is valid
    # cause if so and the parent instance is valid as well
    # it's all being saved at once
    valid = resource.valid?
    valid = resource.role.valid? && valid

    # customized code end

    if valid && resource.save    # customized code
      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_flashing_format?
        sign_up(resource_name, resource)
        respond_with resource, location: after_sign_up_path_for(resource)
      else
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
        expire_data_after_sign_in!
        respond_with resource, location: after_inactive_sign_up_path_for(resource)
      end
    else
      clean_up_passwords resource
      @validatable = devise_mapping.validatable?
      if @validatable
        @minimum_password_length = resource_class.password_length.min
      end
      respond_with resource
    end
  end
end
#controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

   before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| 
        u.permit(:email, :password, :password_confirmation, :user_type).tap do |wl| 
            if params[:company]
              wl[:company] = params[:company]
            elsif params[:client]
              wl[:client]  = params[:client]
            end
        end 
    }
  end
end
resource.role = child_class.new(child_class_params)
sign_up_params: {"email"=>"example@expample.com", "password"=>"12345678", "password_confirmation"=>"12345678", "user_type"=>"company", "company"=>{"company_name"=>"expample company name", "company_tel"=>"223-2323-2"}}
user_params: {"email"=>"example@expample.com", "password"=>"12345678", "password_confirmation"=>"12345678"}
user_type: company
child_class_params: {"company_name"=>"expample company name", "company_tel"=>"223-2323-2"}
resource.role = child_class.new(child_class_params.symbolize_keys)