Rails设计不会将额外的输入字段保存到数据库 [英] Rails devise doesn't save extra input fields to database

查看:140
本文介绍了Rails设计不会将额外的输入字段保存到数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有使用Devise宝石将额外的用户字段值插入数据库时​​遇到问题。我在找什么?



我正在使用

  ruby 2.1.5p273 
Rails 4.1.8

这是我的user.rb模型

  class User< ActiveRecord :: Base 

belongs_to:country

#包含默认设计模块。其他可用的是:
#:confirmable,:lockable,:timeoutable和:omniauthable
devise:database_authenticatable,:可注册,
:可恢复,可记忆,可跟踪,可验证, :authentication_keys => [:login]

attr_accessor:login,:name,:last_name,:address,:post_number,:city,,mobile

validates:username,presence:true,length :{maximum:25},:uniqueness => {:case_sensitive => false}
validates:name,presence:true
validates:last_name,presence:true
validates:address,presence:true
validates:post_number,presence:true
验证:city,presence:true
validates:country,presence:true
validates:mobile,presence:true

def login =(login)
@login =登录
end

def login
@login || self.username || self.email
end

def self.find_for_database_authentication(warden_conditions)
条件= warden_conditions.dup
如果login = conditions.delete(:login)
where(conditions).where(conditions).where([username =:value OR lower(email)= lower(:value),{:value => login}])first
else
where(conditions).first
end
end

end

我的应用程序控制器

  class ApplicationController< ActionController :: Base 
#通过引发异常来防止CSRF攻击。
#对于API,您可能需要使用:null_session。
protect_from_forgery with::exception

before_action:configure_permitted_pa​​rameters,如果::devise_controller?

protected

def configure_permitted_pa​​rameters
devise_parameter_sanitizer.for(:sign_up)<< :username<< :电子邮件<< :password<< :password_confirmation<< :remember_me<< :name<< :last_name<< :地址< :post_number<<< :city<<< :country_id<< :mobile
devise_parameter_sanitizer.for(:sign_in)<<< :login<< :username<< :电子邮件<< :password<< :remember_me
devise_parameter_sanitizer.for(:account_update)<< :username<< :电子邮件<< :password<< :password_confirmation<< :current_password<<< :name<< :last_name<< :地址<< :post_number<<< :city<<< :country_id<< :mobile
end

end

应用程序控制器(V2,我试过船方式)

  class ApplicationController< ActionController :: Base 
#通过引发异常来防止CSRF攻击。
#对于API,您可能需要使用:null_session。
protect_from_forgery with::exception

before_action:configure_permitted_pa​​rameters,如果::devise_controller?

protected

def configure_permitted_pa​​rameters
devise_parameter_sanitizer.for(:sign_up){| u | u.permit(:username,:email,:password,:password_confirmation,:remember_me,:name,:last_name,:address,:post_number,:city,:country_id,,mobile)}
devise_parameter_sanitizer.for sign_in){| u | u.permit(:login,:username,:email,:password,,remember_me)}
devise_parameter_sanitizer.for(:account_update){| u | u.permit(:username,:email,:password,:password_confirmation,:current_password,:name,:last_name,:address,:post_number,:city,:country_id,,mobile)}
end

end

注册/ new.html.erb

 < h2>注册< / h2> 

<%= form_for(资源,as:resource_name,url:registration_path(resource_name))do | f | %GT;
<%= devise_error_messages! %GT;

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

< div class =field>
<%= f.label:username%>< br />
<%= f.text_field:username,autofocus:true%>
< / div>

< div class =field>
<%= f.label:password%>
<%if @validatable%>
< em>(<%= @minimum_password_length%>字符最小)< / em>
<%end%>< br />
<%= f.password_field:password,autocomplete:off%>
< / div>

< div class =field>
<%= f.label:password_confirmation%>< br />
<%= f.password_field:password_confirmation,autocomplete:off%>
< / div>

< hr>

< div>
<%= f.label:name%>< br />
<%= f.text_field:name%>
< / div>

< div>
<%= f.label:last_name%>< br />
<%= f.text_field:last_name%>
< / div>
< div>
<%= f.label:address%>< br />
<%= f.text_field:address%>
< / div>
< div>
<%= f.label:post_number%>< br />
<%= f.text_field:post_number%>
< / div>
< div>
<%= f.label:city%>< br />
<%= f.text_field:city%>
< / div>
< div>
<%= f.label:country_id%>< br />
<%= f.select(:country_id,options_from_collection_for_select(Country.all,:id,:name))%>
< / div>
< div>
<%= f.label:mobile%>< br />
<%= f.text_field:mobile%>
< / div>

< br>< br>

< div class =actions>
<%= f.submit注册%>
< / div>
<%end%>

<%= renderdevise / shared / links%>

这是一个日志,当我提交表单时会发生什么

 开始POST/ users为127.0.0.1在2015-01-12 21:29:36 +0100 
处理注册控制器#创建为HTML
参数:{utf8=>✓,authenticity_token=>YXPl + X5Xpib9yG4ywUY2BAOmiGdNUtkQZtIgxqBXbak =,user=> {email=>test@gmail.com username=>testUser,password=>[FILTERED],password_confirmation=>[FILTERED],name=>Test,last_name=> Test,address=>Test,post_number=>21332,city=>TestCity,country_id=>81831761,mobile=> 333666333666},commit=>注册}
(0.1ms)begin transaction
用户存在(0.2ms)SELECT 1 AS FROM FROMusersWHEREusers电子邮件='test@gmail.com'LIMIT 1
用户存在(0.1ms)SELECT 1 AS FROM FROMusersWHERE LOWER(users。username)= LOWER('testUser')LIMIT 1
国家负载(0.0ms)SELECTcountr 来自国家哪里国家。id=? LIMIT 1 [[id,81831761]]
用户负载(0.2ms)SELECTusers。* FROMusersWHEREusers。confirmation_token='0ddbdfeadb0c6758be3dda41b068fd319e0fd63cefcb16c5b985f90ab16e6784'ORDER BYusers idASC LIMIT 1
在列```````````````````````````````` users(confirm_sent_at,confirmation_token,country_id,created_at,email,encrypted_pa​​ssword,updated_at,username)VALUES(?,?,?,? ?[confirm_sent_at,2015-01-12 20:29:36.962365],[confirmation_token,0ddbdfeadb0c6758be3dda41b068fd319e0fd63cefcb16c5b985f90ab16e6784],[country_id,81831761],[created_at 01-12 20:29:36.742990],[email,test@gmail.com],[encrypted_pa​​ssword,$ 2a $ 10 $ bL6dOOVGzfJ5eOGA8mU / ces7w1CCjJk8Z8rlj6BvSQyqbLgazqrVW],[updated_at,2015-01 -12 20:29:36.742990],[username,testUser]]
渲染设计/邮件/ confirm_instructions.html.erb(0.8ms)

我有两个任务: p>


  1. 我必须做什么,所以设计会扩展他的INSERT sql查询以插入额外的数据库字段值?

  2. 哪种写应用程序控制器devise_parameter_sanitizer的方式是正确的?

Thx for help

解决方案

我找到了一个解决方案!
在rails 4中,您必须在控制器中指定user_params



这是我的users_controller(添加的user_params)

  class UsersController< ApplicationController 

def index
@users = User.all
end

def new
@user = User.new
end

private

def user_params
params.require(:user).permit(:username,:email,:password,:password_confirmation,:remember_me, name,:last_name,:address,:post_number,:city,:country_id,,mobile)
end


end
/ pre>

这是我的用户模型(删除attr_accessor)

 类User< ActiveRecord :: Base 

belongs_to:country

#包含默认设计模块。其他可用的是:
#:confirmable,:lockable,:timeoutable和:omniauthable
devise:database_authenticatable,:可注册,
:可恢复,可记忆,可跟踪,可验证, :authentication_keys => [:login]

validates:username,presence:true,length:{maximum:25},:uniqueness => {:case_sensitive => false}
validates:name,presence:true,length:{maximum:30}
validates:last_name,presence:true
validates:address,presence:true
validates:post_number ,存在:true
validates:city,presence:true
validates:country,presence:true
validates:mobile,presence:true

def login =(login )
@login = login
end

def login
@login || self.username || self.email
end

def self.find_for_database_authentication(warden_conditions)
条件= warden_conditions.dup
如果login = conditions.delete(:login)
where(conditions).where(conditions).where([username =:value OR lower(email)= lower(:value),{:value => login}])first
else
其中(条件).first
end
end

end

这是我的应用程序控制器

  class ApplicationController< ActionController :: Base 
#通过引发异常来防止CSRF攻击。
#对于API,您可能需要使用:null_session。
protect_from_forgery with::exception

before_action:configure_permitted_pa​​rameters,如果::devise_controller?

protected

def configure_permitted_pa​​rameters
devise_parameter_sanitizer.for(:sign_up)do | u | u.permit(:username,:email,:password,:password_confirmation,:remember_me,:name,:last_name,:address,:post_number,:city,:country_id,,mobile)end
devise_parameter_sanitizer.for sign_in)do | u | u.permit(:login,:username,:email,:password,,remember_me)end
devise_parameter_sanitizer.for(:account_update)do | u | u.permit(:username,:email,:password,:password_confirmation,:current_password,:name,:last_name,:address,:post_number,:city,:country_id,,mobile)end
end

end


I'm having problem with inserting extra user fields values to database with Devise gem. What i'm missing?

I'm using

ruby 2.1.5p273
Rails 4.1.8

This is my user.rb model

class User < ActiveRecord::Base

  belongs_to :country

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable, :authentication_keys => [:login]

  attr_accessor :login, :name, :last_name, :address, :post_number, :city, :mobile

  validates :username, presence: true, length: {maximum: 25}, :uniqueness => { :case_sensitive => false }
  validates :name, presence:true
  validates :last_name, presence:true
  validates :address, presence:true
  validates :post_number, presence:true
  validates :city, presence:true
  validates :country, presence:true
  validates :mobile, presence:true

  def login=(login)
    @login = login
  end

  def login
    @login || self.username || self.email
  end

  def self.find_for_database_authentication(warden_conditions)
    conditions = warden_conditions.dup
    if login = conditions.delete(:login)
      where(conditions).where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
    else
      where(conditions).first
    end
  end

end

My aplication controller

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) << :username << :email << :password << :password_confirmation << :remember_me << :name << :last_name << :address << :post_number << :city << :country_id << :mobile
    devise_parameter_sanitizer.for(:sign_in) << :login << :username << :email << :password << :remember_me
    devise_parameter_sanitizer.for(:account_update) << :username << :email << :password << :password_confirmation << :current_password << :name << :last_name << :address << :post_number << :city << :country_id << :mobile
  end

end

Application controller (V2, i tried boat ways)

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(:username, :email, :password, :password_confirmation, :remember_me, :name, :last_name, :address, :post_number, :city, :country_id, :mobile) }
    devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:login, :username, :email, :password, :remember_me) }
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:username, :email, :password, :password_confirmation, :current_password, :name, :last_name, :address, :post_number, :city, :country_id, :mobile) }
  end

end

Registratiions/new.html.erb

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

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

    <div class="field">
      <%= f.label :username %><br />
      <%= f.text_field :username, autofocus: true %>
    </div>

    <div class="field">
        <%= f.label :password %>
        <% if @validatable %>
        <em>(<%= @minimum_password_length %> characters minimum)</em>
        <% end %><br />
        <%= f.password_field :password, autocomplete: "off" %>
    </div>

    <div class="field">
        <%= f.label :password_confirmation %><br />
        <%= f.password_field :password_confirmation, autocomplete: "off" %>
    </div>

    <hr>

    <div>
        <%= f.label :name %><br />
        <%= f.text_field :name %>
    </div>

    <div>
        <%= f.label :last_name %><br />
        <%= f.text_field :last_name %>
    </div>
    <div>
        <%= f.label :address %><br />
        <%= f.text_field :address %>
    </div>
    <div>
        <%= f.label :post_number %><br />
        <%= f.text_field :post_number %>
    </div>
    <div>
        <%= f.label :city %><br />
        <%= f.text_field :city %>
    </div>
    <div>
        <%= f.label :country_id %><br />
        <%= f.select(:country_id, options_from_collection_for_select(Country.all, :id, :name)) %>
    </div>
    <div>
        <%= f.label :mobile %><br />
        <%= f.text_field :mobile %>
    </div>

    <br><br>

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

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

And this is a log what happens when i submit my form

Started POST "/users" for 127.0.0.1 at 2015-01-12 21:29:36 +0100
Processing by RegistrationsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"YXPl+X5Xpib9yG4ywUY2BAOmiGdNUtkQZtIgxqBXbak=", "user"=>{"email"=>"test@gmail.com", "username"=>"testUser", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "name"=>"Test", "last_name"=>"Test", "address"=>"Test", "post_number"=>"21332", "city"=>"TestCity", "country_id"=>"81831761", "mobile"=>"333666333666"}, "commit"=>"Sign up"}
   (0.1ms)  begin transaction
  User Exists (0.2ms)  SELECT  1 AS one FROM "users"  WHERE "users"."email" = 'test@gmail.com' LIMIT 1
  User Exists (0.1ms)  SELECT  1 AS one FROM "users"  WHERE LOWER("users"."username") = LOWER('testUser') LIMIT 1
  Country Load (0.0ms)  SELECT  "countries".* FROM "countries"  WHERE "countries"."id" = ? LIMIT 1  [["id", 81831761]]
  User Load (0.2ms)  SELECT  "users".* FROM "users"  WHERE "users"."confirmation_token" = '0ddbdfeadb0c6758be3dda41b068fd319e0fd63cefcb16c5b985f90ab16e6784'  ORDER BY "users"."id" ASC LIMIT 1
Binary data inserted for `string` type on column `confirmation_token`
Binary data inserted for `string` type on column `encrypted_password`
  SQL (0.3ms)  INSERT INTO "users" ("confirmation_sent_at", "confirmation_token", "country_id", "created_at", "email", "encrypted_password", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["confirmation_sent_at", "2015-01-12 20:29:36.962365"], ["confirmation_token", "0ddbdfeadb0c6758be3dda41b068fd319e0fd63cefcb16c5b985f90ab16e6784"], ["country_id", 81831761], ["created_at", "2015-01-12 20:29:36.742990"], ["email", "test@gmail.com"], ["encrypted_password", "$2a$10$bL6dOOVGzfJ5eOGA8mU/ces7w1CCjJk8Z8rlj6BvSQyqbLgazqrVW"], ["updated_at", "2015-01-12 20:29:36.742990"], ["username", "testUser"]]
  Rendered devise/mailer/confirmation_instructions.html.erb (0.8ms)

I have two questons:

  1. What i have to do, so devise will extend his INSERT sql query to insert extra database fields values?
  2. Which way of writing application controller devise_parameter_sanitizer is correct?

Thx for help

解决方案

I found a solution! In rails 4 you have to specifiey user_params in controller

This is my users_controller (added user_params)

class UsersController < ApplicationController

  def index
    @users = User.all
  end

  def new
    @user = User.new
  end

  private

  def user_params
    params.require(:user).permit(:username, :email, :password, :password_confirmation, :remember_me, :name, :last_name, :address, :post_number, :city, :country_id, :mobile)
  end


end

And this is my user model (removed attr_accessor)

    class User < ActiveRecord::Base

      belongs_to :country

      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable, :confirmable, :authentication_keys => [:login]

      validates :username, presence: true, length: {maximum: 25}, :uniqueness => { :case_sensitive => false }
      validates :name, presence:true, length: {maximum: 30}
      validates :last_name, presence:true
      validates :address, presence:true
      validates :post_number, presence:true
      validates :city, presence:true
      validates :country, presence:true
      validates :mobile, presence:true

      def login=(login)
        @login = login
      end

      def login
        @login || self.username || self.email
      end

      def self.find_for_database_authentication(warden_conditions)
        conditions = warden_conditions.dup
        if login = conditions.delete(:login)
          where(conditions).where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
        else
          where(conditions).first
        end
      end

    end

And this is my application controller

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) do |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me, :name, :last_name, :address, :post_number, :city, :country_id, :mobile) end
    devise_parameter_sanitizer.for(:sign_in) do |u| u.permit(:login, :username, :email, :password, :remember_me) end
    devise_parameter_sanitizer.for(:account_update) do |u| u.permit(:username, :email, :password, :password_confirmation, :current_password, :name, :last_name, :address, :post_number, :city, :country_id, :mobile) end
  end

end

这篇关于Rails设计不会将额外的输入字段保存到数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆