0

Currently, StrongParameters is serving up and error due to the fact that :password and :password_confirmation are not permitted and I believe that's correct because I think I'm only supposed to have the values I want to write to the DB get a permitted key so there must be something wrong with this flow despite doing a tutorial that lead me to this point. Bcrypt should be called to encrypt :password, assign that to :password_hash and discard :password so StrongParameters should never even sees :password, right? I'm not sure how to do that as I thought this code would do that...

Here are my files:

User Model:

class User < ActiveRecord::Base
    attr_accessor :password
    before_save :encrypt_password

    validates_presence_of :password, :on => :create
    validates :password_confirmation, :email, presence: true
    validates :password, confirmation: true
    validates :email, uniqueness: true

    def encrypt_password
        if password.present?
            self.password_salt = BCrypt::Engine.generate_salt
            self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
        end
    end
end

User Controller:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
  debugger
    @user = User.new(params[user_params])
    if @user.save
        redirect_to root_url, :notice => "Signup was succsessful!"
    else
        render 'new'
    end
  end


  private

  def user_params
    user_params = params.require(:user).permit(:email, :password_salt, :password_hash)
  end

end

Output via debug server:

Started POST "/users" for 127.0.0.1 at 2013-10-28 21:42:47 -0700
Processing by UsersController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"/Qij3/MBTqhB+Q1mZjD5PoimOa37z/jjCY0FMSnPtZA=", "user"=>{"email"=>"test@email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Create User"}
/home/user/web/gather/app/controllers/users_controller.rb:8
@user = User.new(params[user_params])

[3, 12] in /home/user/web/gather/app/controllers/users_controller.rb
   3            @user = User.new
   4    end
   5  
   6    def create
   7    debugger
=> 8            @user = User.new(params[user_params])
   9            if @user.save
   10                   redirect_to root_url, :notice => "Signup was succsessful!"
   11           else
   12                   render 'new'
(rdb:6) c
/home/user/web/gather/app/controllers/users_controller.rb:21
user_params = params.require(:user).permit(:email, :password_salt, :password_hash)

[16, 25] in /home/user/web/gather/app/controllers/users_controller.rb
   16  
   17    private
   18  
   19    def user_params
   20    debugger
=> 21      user_params = params.require(:user).permit(:email, :password_salt, :password_hash)
   22      debugger
   23    end
   24  
   25  end
(rdb:6) instance_variables
[:@_routes, :@_action_has_layout, :@_headers, :@_status, :@_request, :@_response, :@_env, :@_prefixes, :@_lookup_context, :@_action_name, :@_response_body, :@_config, :@_params]
(rdb:6) @_params.inspect
"{\"utf8\"=>\"✓\", \"authenticity_token\"=>\"/Qij3/MBTqhB+Q1mZjD5PoimOa37z/jjCY0FMSnPtZA=\", \"user\"=>{\"email\"=>\"test@email.com\", \"password\"=>\"goober\", \"password_confirmation\"=>\"goober\"}, \"commit\"=>\"Create User\", \"action\"=>\"create\", \"controller\"=>\"users\"}"
(rdb:6) c
Unpermitted parameters: password, password_confirmation
/home/user/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-4.0.0/lib/action_controller/metal/strong_parameters.rb:271
convert_hashes_to_parameters(key, super)

[266, 275] in /home/user/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-4.0.0/lib/action_controller/metal/strong_parameters.rb
   266      #
   267      #   params = ActionController::Parameters.new(person: { name: 'Francesco' })
   268      #   params[:person] # => {"name"=>"Francesco"}
   269      #   params[:none]   # => nil
   270      def [](key)
=> 271        convert_hashes_to_parameters(key, super)
   272      end
   273  
   274      # Returns a parameter for the given +key+. If the +key+
   275      # can't be found, there are several options: With no other arguments,
(rdb:6) c
   (0.4ms)  begin transaction
  User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" IS NULL LIMIT 1
   (0.1ms)  rollback transaction
  Rendered users/new.html.erb within layouts/application (3.6ms)
Completed 200 OK in 42166ms (Views: 31.7ms | ActiveRecord: 0.6ms)

I'm sure I'm missing something simple, but I can't figure it out as I'm new to Ruby and Rails and everyone seems to be doing this differently as Rails undergoes development.

Thanks in advanced!

UPDATE Changing @user = User.new(params[user_params]) to @user = User.new(user_params) gives me the following error:

NoMethodError in UsersController#create
undefined method `stringify_keys' for 1:Fixnum

Extracted source (around line #8):
6
7
8
9
10
11

  def create
  debugger
    @user = User.new(user_params)
    if @user.save
        redirect_to root_url, :notice => "Signup was succsessful!"
    else

Rails.root: /home/dburke/web/gather

Application Trace | Framework Trace | Full Trace
activerecord (4.0.0) lib/active_record/attribute_assignment.rb:17:in `assign_attributes'
activerecord (4.0.0) lib/active_record/core.rb:192:in `initialize'
activerecord (4.0.0) lib/active_record/inheritance.rb:27:in `new'
activerecord (4.0.0) lib/active_record/inheritance.rb:27:in `new'
app/controllers/users_controller.rb:8:in `create'
actionpack (4.0.0) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
actionpack (4.0.0) lib/abstract_controller/base.rb:189:in `process_action'
actionpack (4.0.0) lib/action_controller/metal/rendering.rb:10:in `process_action'
actionpack (4.0.0) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
activesupport (4.0.0) lib/active_support/callbacks.rb:403:in `_run__535388504__process_action__callbacks'
activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
actionpack (4.0.0) lib/abstract_controller/callbacks.rb:17:in `process_action'
actionpack (4.0.0) lib/action_controller/metal/rescue.rb:29:in `process_action'
actionpack (4.0.0) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
activesupport (4.0.0) lib/active_support/notifications.rb:159:in `block in instrument'
activesupport (4.0.0) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (4.0.0) lib/active_support/notifications.rb:159:in `instrument'
actionpack (4.0.0) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
actionpack (4.0.0) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
activerecord (4.0.0) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (4.0.0) lib/abstract_controller/base.rb:136:in `process'
actionpack (4.0.0) lib/abstract_controller/rendering.rb:44:in `process'
actionpack (4.0.0) lib/action_controller/metal.rb:195:in `dispatch'
actionpack (4.0.0) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
actionpack (4.0.0) lib/action_controller/metal.rb:231:in `block in action'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:80:in `call'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:80:in `dispatch'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:48:in `call'
actionpack (4.0.0) lib/action_dispatch/journey/router.rb:71:in `block in call'
actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `each'
actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `call'
actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:655:in `call'
rack (1.5.2) lib/rack/etag.rb:23:in `call'
rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
rack (1.5.2) lib/rack/head.rb:11:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/flash.rb:241:in `call'
rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/cookies.rb:486:in `call'
activerecord (4.0.0) lib/active_record/query_cache.rb:36:in `call'
activerecord (4.0.0) lib/active_record/connection_adapters/abstract/connection_pool.rb:626:in `call'
activerecord (4.0.0) lib/active_record/migration.rb:369:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
activesupport (4.0.0) lib/active_support/callbacks.rb:373:in `_run__673544566__call__callbacks'
activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/reloader.rb:64:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
railties (4.0.0) lib/rails/rack/logger.rb:38:in `call_app'
railties (4.0.0) lib/rails/rack/logger.rb:21:in `block in call'
activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `block in tagged'
activesupport (4.0.0) lib/active_support/tagged_logging.rb:25:in `tagged'
activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `tagged'
railties (4.0.0) lib/rails/rack/logger.rb:21:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/request_id.rb:21:in `call'
rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
rack (1.5.2) lib/rack/runtime.rb:17:in `call'
activesupport (4.0.0) lib/active_support/cache/strategy/local_cache.rb:83:in `call'
rack (1.5.2) lib/rack/lock.rb:17:in `call'
actionpack (4.0.0) lib/action_dispatch/middleware/static.rb:64:in `call'
railties (4.0.0) lib/rails/engine.rb:511:in `call'
railties (4.0.0) lib/rails/application.rb:97:in `call'
rack (1.5.2) lib/rack/lock.rb:17:in `call'
rack (1.5.2) lib/rack/content_length.rb:14:in `call'
railties (4.0.0) lib/rails/rack/debugger.rb:20:in `call'
rack (1.5.2) lib/rack/handler/webrick.rb:60:in `service'
/home/dburke/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:138:in `service'
/home/dburke/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/httpserver.rb:94:in `run'
/home/dburke/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/webrick/server.rb:295:in `block in start_thread'
Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"x7HyftWwAGTYw1zRkhD/5OmZM680CRz3FGAm/OtM42w=",
 "user"=>{"email"=>"dylan.burke@gmail.com",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]"},
 "commit"=>"Create User"}
Dylan
  • 563
  • 4
  • 15

1 Answers1

0

Your controller receives its params directly from the form you submitted - ie. it gets a password and password_confirmation field. (You can check your logs to see that these are being passed to your controller - the values will be marked as [FILTERED] but they will be there.)

Then you do the parameter sanitizing, then you pass the sanitized values to the model. Inside the model is where the encrypting and the like occur, before saving.

No-one who is working with Rails 4 is doing it differently - do you have any examples of this?

sevenseacat
  • 24,699
  • 6
  • 63
  • 88
  • I don't have a specific example. I've looked at many tutorials and many of them seem to handle parameters just a little bit differently in this regard; enough to confuse me as to what the proper order of processing is. So you're saying that I should put `:password` and `:password_confirmation` into the whitelist? I've done that and it gets rid of the `Unpermitted parameters` error, but doesn't change the results; my parameters still end up `nil`. – Dylan Oct 29 '13 at 05:08
  • if you want those attributes to get into your model when you call `User.new`, then they must be whitelisted. You also shouldn't call `params[user_params]` - just `user_params` is fine. – sevenseacat Oct 29 '13 at 05:10
  • Using `@user = User.new(user_params)` gets me `undefined method `stringify_keys' for 1:Fixnum`. If I leave that line as it is and just whitelist the params I'm still left with the same issue despite not having it complain about unpermitted parameters. – Dylan Oct 29 '13 at 05:17
  • well we need a bit more information than that. Can you add the entire error to the question? – sevenseacat Oct 29 '13 at 05:19
  • It's updated. Just so you know, every tutorial I've looked at thus far for building user registration from scratch has delivered the parameters inside `params[]`. For example: http://www.sitepoint.com/rails-userpassword-authentication-from-scratch-part-i/ and http://railscasts.com/episodes/250-authentication-from-scratch Could you touch on why they would do this? From what I've read, `params[]` is used to access the actual parameters from the browser which I agree, doesn't seem to make much sense, though that code has allowed me to get farther than anything thus far. – Dylan Oct 29 '13 at 15:19
  • None of those tutorials are for Rails 4 and do not use strong parameters. – sevenseacat Oct 30 '13 at 02:42