无法在用户模型上设置新属性(使用 Devise & Rails 5)



我在我的用户模型(Devise)中添加了一个新的属性/列(locale)。我将使用它来保存用户选择的语言以显示应用程序。这是由用户在默认的设计注册表单上选择的。

我已将 devise_parameter_sanitizer 方法添加到我的应用程序控制器以允许新参数,但每次添加新用户时,数据库中的locale列始终为空。

如果我按照日志进行操作,我可以看到参数已传递到创建操作,但由于某种原因,它在中间的某个地方丢失了。

希望得到一些关于我在这里做错了什么的指导。

创建新用户时记录

    Started POST "/users" for 127.0.0.1 at 2019-01-19 12:09:25 +0100
    Processing by Devise::RegistrationsController#create as HTML
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"O3FEXmGBOnipEOLXkxNpRCKmpYVa5gc8oM2wauJbNt1iechdMQslDYZRSOgNEWeqsVFxcOQnxR2tbM2zNfAayw==", "user"=>{"email"=>"testytesty@testytesty1.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "locale"=>"sv", "commit"=>"Sign up"}
    (0.1ms)  begin transaction
    ↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
    User Exists (0.5ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "testytesty@testytesty1.com"], ["LIMIT", 1]]
    ↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
    User Create (1.2ms)  INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["email", "testytesty@testytesty1.com"], ["encrypted_password", "$2a$11$EYTMfLLydcUvPjBjKcKxFe67OsTvwJao/SvP8PFrkctC95SkDQJDq"], ["created_at", "2019-01-19 11:09:25.326356"], ["updated_at", "2019-01-19 11:09:25.326356"]]

图式

create_table "users", force: :cascade do |t|
  t.string "email", default: "", null: false
  t.string "encrypted_password", default: "", null: false
  t.string "reset_password_token"
  t.datetime "reset_password_sent_at"
  t.datetime "remember_created_at"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "locale"
  t.index ["email"], name: "index_users_on_email", unique: true
  t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
 end

应用控制器

class ApplicationController < ActionController::Base
    protect_from_forgery with: :exception, unless: -> { request.format.json? }
    before_action :configure_permitted_parameters, if: :devise_controller?
    before_action :authenticate_user!
    before_action :belongs_to_user
    before_action :set_locale
    def after_sign_in_path_for(resource_or_scope)
        # Set a default current company scope for a use after signing in
        session[:current_company] = current_user.companies.first.id unless current_user.companies.empty?
        puts session[:current_company]
        companies_path
    end
    def set_locale
        I18n.locale = current_user.try(:locale) || I18n.default_locale
    end
    def belongs_to_user
        unless params[:controller] == 'devise/sessions' || params[:access_token].present? # TODO this is a potential security gap - patch this up so that it can't just any old token, it must be a valid one (look in the captables controller)
        @current_user_companies = current_user.companies unless !user_signed_in?
        if !params[:company_id].present?
            @company = Company.find(params[:id]) unless !params[:id].present?
        else
            @company = Company.find(params[:company_id]) unless !params[:company_id].present?
        end
        unless !@company
            if !@current_user_companies.include?(Company.find(@company.id))
            redirect_to companies_path, alert: "Access denied: You do not belong to this company"
            end
        end
        end
    end
    protected
    def configure_permitted_parameters
        # Permit some additional params on the user sign up that aren't the default email, password etc
        devise_parameter_sanitizer.permit(:sign_up, keys: [:locale])
    end
end

我的注册表格

    <%= 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, autofocus: true, autocomplete: "email" %>
    </div>
    <div class="field">
        <%= f.label :password %>
        <% if @minimum_password_length %>
        <em>(<%= @minimum_password_length %> characters minimum)</em>
        <% end %><br />
        <%= f.password_field :password, autocomplete: "new-password" %>
    </div>
    <div class="field">
        <%= f.label :password_confirmation %><br />
        <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
    </div>
    <div class="field">
        <%= f.label :locale %><br />
        <%= select_tag(:locale, options_for_select([["English", "en"], ["Swedish", "sv"]])) %>
    </div>
    <div class="actions">
        <%= f.submit "Sign up" %>
    </div>
    <% end %>

更新:全栈跟踪

Started POST "/users" for 127.0.0.1 at 2019-01-19 12:37:40 +0100
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"pAL2lKhnw4VEFx+umYkGDp+d87hrCRZ/xR0JaYof5X4J8Y4Acj8SOzB85mm6heRtNMXHpIPaI9l8+oDCeuLH5A==", "user"=>{"email"=>"jameselliotpember@gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "locale"=>"sv", "commit"=>"Sign up"}
(0.1ms)  begin transaction
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "jameselliotpember@gmail.com"], ["LIMIT", 1]]
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
User Create (0.4ms)  INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["email", "jameselliotpember@gmail.com"], ["encrypted_password", "$2a$11$N5A/.cfWXnAa/3upKDYlwOxLCt4zc8WPe2Jce.A60A3.SFR4jgoxe"], ["created_at", "2019-01-19 11:37:40.625528"], ["updated_at", "2019-01-19 11:37:40.625528"]]
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
(1.8ms)  commit transaction
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
(0.1ms)  begin transaction
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
LoginActivity Create (0.6ms)  INSERT INTO "login_activities" ("scope", "strategy", "identity", "success", "user_type", "user_id", "context", "ip", "user_agent", "referrer", "created_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["scope", "user"], ["strategy", "database_authenticatable"], ["identity", "jameselliotpember@gmail.com"], ["success", 1], ["user_type", "User"], ["user_id", 1], ["context", "devise/registrations#create"], ["ip", "127.0.0.1"], ["user_agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"], ["referrer", "http://localhost:3000/users/sign_up"], ["created_at", "2019-01-19 11:37:40.630791"]]
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
(1.0ms)  commit transaction
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
[ActiveJob] Enqueued AuthTrail::GeocodeJob (Job ID: 3c096920-93b2-45aa-ba0d-3c9ff5a1466f) to Async(default) with arguments: #<GlobalID:0x00007f9698b7c510 @uri=#<URI::GID gid://calmcap/LoginActivity/2>>
LoginActivity Load (0.4ms)  SELECT  "login_activities".* FROM "login_activities" WHERE "login_activities"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
[ActiveJob] [AuthTrail::GeocodeJob] [3c096920-93b2-45aa-ba0d-3c9ff5a1466f] Performing AuthTrail::GeocodeJob (Job ID: 3c096920-93b2-45aa-ba0d-3c9ff5a1466f) from Async(default) with arguments: #<GlobalID:0x00007f9698b4bbe0 @uri=#<URI::GID gid://calmcap/LoginActivity/2>>
[ActiveJob] [AuthTrail::GeocodeJob] [3c096920-93b2-45aa-ba0d-3c9ff5a1466f]    (0.1ms)  begin transaction
[ActiveJob] [AuthTrail::GeocodeJob] [3c096920-93b2-45aa-ba0d-3c9ff5a1466f]   ↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
[ActiveJob] [AuthTrail::GeocodeJob] [3c096920-93b2-45aa-ba0d-3c9ff5a1466f]    (0.0ms)  commit transaction
[ActiveJob] [AuthTrail::GeocodeJob] [3c096920-93b2-45aa-ba0d-3c9ff5a1466f]   ↳ /usr/local/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
[ActiveJob] [AuthTrail::GeocodeJob] [3c096920-93b2-45aa-ba0d-3c9ff5a1466f] Performed AuthTrail::GeocodeJob (Job ID: 3c096920-93b2-45aa-ba0d-3c9ff5a1466f) from Async(default) in 2.8ms
Company Exists (0.1ms)  SELECT  1 AS one FROM "companies" WHERE "companies"."user_id" = ? LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
↳ app/controllers/application_controller.rb:10
Redirected to http://localhost:3000/companies
Completed 302 Found in 175ms (ActiveRecord: 4.5ms)

试试这个!

改变

 <%= select_tag(:locale, options_for_select([["English", "en"], ["Swedish", "sv"]])) %>

 <%= f.select :locale, options_for_select([["English","en"],["Swedish","sv"]]), {include_blank: "locale"} %>

如果您检查日志,您会发现您的locale参数不在user范围内。我重新格式化了这一行:

    Parameters: {
      "utf8"=>"✓",
      "authenticity_token"=>"...", 
      "user"=>{
         "email"=>"testytesty@testytesty1.com", 
         "password"=>"[FILTERED]", 
         "password_confirmation"=>"[FILTERED]"
      }, 
      "locale"=>"sv", 
      "commit"=>"Sign up"
}

因此,您应该将其添加到user参数组中。

据我了解,发生这种情况是因为您没有将其绑定到表单上。您应该在表单中使用f.select而不是select_tag

最新更新