Rails设计不会将额外的输入字段保存到数据库 [英] Rails devise doesn't save extra input fields to database
问题描述
我有使用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_parameters,如果::devise_controller?
protected
def configure_permitted_parameters
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_parameters,如果::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
注册/ 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_password,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_password,$ 2a $ 10 $ bL6dOOVGzfJ5eOGA8mU / ces7w1CCjJk8Z8rlj6BvSQyqbLgazqrVW],[updated_at,2015-01 -12 20:29:36.742990],[username,testUser]]
渲染设计/邮件/ confirm_instructions.html.erb(0.8ms)
我有两个任务: p>
- 我必须做什么,所以设计会扩展他的INSERT sql查询以插入额外的数据库字段值?
- 哪种写应用程序控制器devise_parameter_sanitizer的方式是正确的?
Thx for help
我找到了一个解决方案!
在rails 4中,您必须在控制器中指定user_params
这是我的users_controller(添加的user_params)
class UsersController< ApplicationController
/ pre>
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
这是我的用户模型(删除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_parameters,如果::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
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:
- What i have to do, so devise will extend his INSERT sql query to insert extra database fields values?
- 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屋!