Reputation: 357
I've added a new attribute/column (locale
) to my User model (Devise). I will use this to save the User's chosen language to show the app in. This is selected by the user on the default Devise sign up form.
I have added the devise_parameter_sanitizer
method to my application controller to permit the new parameter but everytime I add a new user, the locale
column is always blank in the database.
If I follow the logs, I can see that the parameter is passed through to the create action, but for some reason it's lost somewhere in the middle.
Would love some guidance on what I'm doing wrong here.
Log when creating a new user
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"]]
Schema
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
Application controller
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
My sign up form
<%= 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 %>
Update: Full stack trace
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)
Upvotes: 1
Views: 335
Reputation: 568
change
<%= select_tag(:locale, options_for_select([["English", "en"], ["Swedish", "sv"]])) %>
TO
<%= f.select :locale, options_for_select([["English","en"],["Swedish","sv"]]), {include_blank: "locale"} %>
Upvotes: 2
Reputation: 8050
If you check your logs you will see that your locale
param does not come inside user
scope. I've reformatted this line:
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"...",
"user"=>{
"email"=>"testytesty@testytesty1.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"
},
"locale"=>"sv",
"commit"=>"Sign up"
}
So, you should add it inside user
group of params.
As I understand this had happened because you didn't bind it to the form. You should use f.select
instead of select_tag
in your form.
Upvotes: 2