【问题标题】:Rails devise doesn't save extra input fields to databaseRails 设计不会将额外的输入字段保存到数据库
【发布时间】:2015-01-12 20:39:06
【问题描述】:

我在使用 Devise gem 将额外的用户字段值插入数据库时​​遇到问题。我错过了什么?

我正在使用

ruby 2.1.5p273
Rails 4.1.8

这是我的 user.rb 模型

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

我的应用控制器

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

应用控制器(V2,我尝试过船的方式)

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

注册/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" %>

这是我提交表单时发生的日志

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)

我有两个问题:

  1. 我必须做什么,所以设计将扩展他的 INSERT sql 查询以插入额外的数据库字段值?
  2. 应用控制器devise_parameter_sanitizer的哪种写法是正确的?

谢谢帮助

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 devise


    【解决方案1】:

    我找到了解决办法! 在 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
    

    这是我的用户模型(删除 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
    

    这是我的应用程序控制器

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-08
      • 1970-01-01
      • 1970-01-01
      • 2014-08-20
      • 1970-01-01
      • 2014-01-11
      • 2016-03-23
      相关资源
      最近更新 更多