rake db:seed thorwing Can't mass-assign protected attributes - ruby-on-rails

I am learning ruby on rails. I am creating a model for storing User information and when calling rake db:seed then I am getting the following error , any idea what I am missing ?
rake db:seed
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :email, :password
validates :email, :uniqueness => true,
:length => {:within => 5..50},
:presence => true
validates :password, :confirmation => true, :length => { :within => 4..20 }, :presence => true, :if => :password_required?
has_one :profile
has_many :articles, :order => 'published_at DESC, title ASC',
:dependent => :nullify
has_many :replies, :through => :articles, :source => :comments
before_save :encrypt_new_password
def self.authenticate(email, password)
user = find_by_email(email)
return user if user && user.authenticated?(password)
end
def authenticated?(password)
self.hashed_password == encrypt(password)
end
def encrypt_new_password
return if password.blank?
self.hashed_password = encrypt(password)
end
def password_required?
hashed_password.blank? || password.present?
end
def encrypt(string)
Digest::SHA2.hexdigest(string)
end
end
Can't mass-assign protected attributes: password_confrimation
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activemodel-3.2.3/lib/active_model/mass_assignment_security.rb:230:in `sanitize_for_mass_assignment'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/base.rb:498:in `initialize'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/persistence.rb:44:in `new'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/persistence.rb:44:in `create'
C:/Users/huzaifa.gain/My Documents/Aptana Studio 3 Workspace/blog/db/seeds.rb:6:in `<top (required)>'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `load'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:245:in `block in load'
c:/Ruby192/lib/ruby/gems/1.9.1/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:23

You have to add password_confirmation to attr_accessible
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :email, :password, :password_confirmation
and it should work.

As logs says "Can't mass-assign protected attributes: password_confrimation"
you need to add password_confrimation to User Model
attr_accessible :password_confrimation

Related

rspec with "should_receive" expectation fail

Below is error and the spec listed for my failing test , not sure why it keep getting failed with following message even though I see the method getting invoked on #user.save
Failure/Error: expect(#performer).should_receive(:store_performer)
(#<RSpec::Expectations::ExpectationTarget:0x007f9ec42b5808>).store_performer(any args)
expected: 1 time
received: 0 times
Once again
if I comment the should_receive I do see the method getting invoked (confirmed by virtue of puts) on #user.save call (During that I also examine the object_id of #performer inside the spec and inside the invoked method and found them to be same)
Note: Basically the store_performer , update_minimum_payout and update_to_be_paid are after_save callback
FYI the test case
it 'should invoke callback method' do
new_single_performer
#performer = #user.performer
expect(#performer).should_receive(:store_performer)
expect(#performer).should_receive(:update_minimum_payout)
expect(#performer).should_receive(:update_to_be_paid)
#user.save
end
User.rb
class User < ActiveRecord::Base
# Activity Log (formerly called User Activity)
cattr_accessor :current_user
has_one :performer,
:dependent => :destroy, :validate => true,:inverse_of => :user,:include => :profile # auto load the profile
## Some more association
scope :performers, where(:is_performer => true)
scope :active, where(:active => true)
## Some more scope
## Validation
validates_presence_of :first_name, :last_name, :email #, :password, :password_confirmation
validates_presence_of :site_id, :unless => :is_referrer?
validates_format_of :first_name, :message => "Characters not allowed: $\##!^&*(){}", :with => /^[\w\s]+z/
validates_format_of :last_name, :message => "Characters not allowed: $\##!^&*(){}", :with => /^[\w\s]+z/
validates_format_of :email, :message => "Invalid Email address", :with => /[\w\.\-\#]+z/
before_save :geocode, :if => :should_change_geocode?
before_save :check_role
after_create :update_vendor_id
after_create :notify_admin
after_save :store_changes,:if => :if_changed?
after_save :setup_account,:if => :studio_active_changed?
after_save :approval_notification,:if => :send_notification_present?
end
Performer.rb
class Performer < ActiveRecord::Base
belongs_to :user, :conditions => {:is_performer => true},:inverse_of => :performer
# validations
validates :date_of_birth, :address_1, :city, :state, :zipcode, :country, :phone_number,
after_save :store_performer
after_destroy :destroy_performer_source
after_save :update_minimum_payout ,:if => :minimum_payout_changed?
after_save :update_to_be_paid ,:if => :include_in_payouts_changed?
private
def store_performer
## Performer Source is Mongo document
performer_source = PerformerSource.find_or_create_by(:performer_id => self.id)
performer_source.update_attributes(performer_hash)
performer_source
end
def update_minimum_payout
self.current_payout.update_attributes(:minimum_payout => self.minimum_payout)
end
def update_to_be_paid
self.current_payout.update_attributes(:to_be_paid => self.include_in_payouts)
end
end
PerformerSource
class PerformerSource
include Mongoid::Document
end
JFI my Rspec Version is 2.12.2

WARNING:"Can't mass-assign protected attributes: created_at, updated_at",when I use gem ''omniauth-identity"

I get this error
ActiveModel::MassAssignmentSecurity::Error in SessionsController#create
Can't mass-assign protected attributes: created_at, updated_at
I think I can add some codes to solve this problem.
class User < ActiveRecord::Base
attr_accessible :email, :nickname, :authentications_attributes, :created_at, :updated_at
Why Omniauth changes the created_at and updated_at?
In addition to add "attr_accessible :created_at, :updated_at", there are other ways?
This is my models/user.rb
class User < ActiveRecord::Base
attr_accessible :email, :nickname, :authentications_attributes, :created_at, :updated_at
validates :nickname, :presence => true
validates :email, :presence => true, :uniqueness => true
has_many :authentications
accepts_nested_attributes_for :authentications
class << self
def from_auth(auth)
Authentication.find_by_provider_and_uid(auth[:provider],
auth[:uid]).try(:user) ||
create!(
:nickname => auth[:info][:nickname],
:email => auth[:info][:email],
:authentications_attributes => [
Authentication.new(:provider => auth[:provider],
:uid => auth[:uid]
).attributes
])
end
end
end
This is my models/identity.rb
class Identity < OmniAuth::Identity::Models::ActiveRecord
attr_accessible :nickname, :email, :password, :password_confirmation, :authentications_attributes
validates_presence_of :nickname, :email
validates_uniqueness_of :nickname, :email
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
end
This is my models/authentication.rb
class Authentication < ActiveRecord::Base
attr_accessible :user_id, :provider, :uid, :authentications_attributes, :created_at, :updated_at
validates :provider, :presence => true, :uniqueness => {:scope => :user_id}
validates :uid, :presence => true, :uniqueness => {:scope => :provider}
belongs_to :user
end
This is my controllers/sessions_controller.rb
class SessionsController < ApplicationController
def create
user = User.from_auth(request.env['omniauth.auth'])
session[:user_id] = user.id
flash[:notice] = "Welcome #{user.nickname}"
redirect_to root_path
end
end
Thanks for your thoughts and pointers.
The problem is this bit of code:
Authentication.new(:provider => auth[:provider],
:uid => auth[:uid]
).attributes
This will return the full set of attributes, including the created_at and updated_at dates, which you're then passing to create, so mass assigning.
You could create the user, then build the attributes like so:
authentication = Authentication.find_by_provider_and_uid(auth[:provider],
auth[:uid]).try(:user)
unless authentication
user = create!(
:nickname => auth[:info][:nickname],
:email => auth[:info][:email])
user.authentications.build(:provider => auth[:provider])
end

undefined local variable or method `hashed_password' for User model

I am trying to set up the User model to successfully save user in the db but I'm hindered by, NameError: undefined local variable or method `hashed_password' for #<User:0x000001029fef18>
User model:
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
validates :email, :uniqueness => true,
:length => { :within => 5..50 },
:format => { :with => /^[^#][\w.-]+#[\w.-]+[.][a-z]{2,4}$/i }
validates :password, :confirmation => true,
:length => { :within => 4..20 },
:presence => true,
:if => :password_required?
has_one :profile
has_many :articles, :order => 'published_at DESC, title ASC',
:dependent => :nullify
has_many :replies, :through => :articles, :source => :comments
before_save :encrypt_new_password
def self.authenticate(email, password)
user = find_by_email(email)
return user if user && user.authenticated?(password)
end
def authenticated?(password)
self.hashed_password == encrypt(password)
end
protected
def encrypt_new_password
return if password.blank?
self.hashed_password = encrypt(password)
end
def password_required?
hashed_password.blank? || password.present?
end
def encrypt(string)
Digest::SHA1.hexdigest(string)
end
end
Add the hashed_password field to your users table by using a migration. It's currently missing.
My first bet is that hashed_password is not defined as a column in your model. Might want to check your migration file for this specific model
Add
attr_accessor :password, :password_confirmation
to Users.rb

Rails - Submitting Nested Values That Already Exist

I have a model, Tran that has a foreign key to the User model. In the view for creation a Tran (transaction), I have a dropdown that allows the user to select the User that started the transaction. When I post this transaction, the record is set with the correct user ID:
Then, in my Trans model I added "belongs_to", as I understand I should do this for foreign keys:
class Tran < ActiveRecord::Base
belongs_to :buying_user, :class_name => 'User'
Now, when my client passes up the params in the post, my Tran.new craps out because I am passing up a userID and not a full record. Is the
#trans_controller.rb
def create
#title = "Create Transaction"
#bombs on this call
#tran = Tran.new(params[:tran])
How am I supposed to handle this?
Update as requested:
tran.rb
class Tran < ActiveRecord::Base
has_many :transaction_users, :dependent => :destroy, :class_name => 'TransactionUser'
belongs_to :submitting_user, :class_name => 'User'
belongs_to :buying_user, :class_name => 'User'
accepts_nested_attributes_for :transaction_users, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
validates :description, :presence => true,
:length => {:maximum => 100 }
validates :total, :presence => true
validates_numericality_of :total, :greater_than => 0
validates :submitting_user, :presence => true
validates :buying_user, :presence => true
validates_associated :transaction_users
end
user.rb
class User < ActiveRecord::Base
has_many :trans
attr_accessor :password
attr_accessible :firstname, :lastname, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :firstname, :presence => true,
:length => {:maximum => 50 }
validates :lastname, :presence => true,
:length => {:maximum => 50 }
validates :email, :presence => true,
:format => {:with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
# Register callback to before save so that we can call extra code like password encryption
before_save :encrypt_password
# Class methods
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
def self.authenticate_with_salt(id, cookie_salt)
user = find_by_id(id)
(user && user.salt == cookie_salt) ? user : nil
end
# Public methods
def has_password?(submitted_password)
self.encrypted_password == encrypt(submitted_password)
end
def full_name
"#{self.lastname}, #{self.firstname}"
end
def self.active_users
# TODO
#User.find_
User.all
end
private
def encrypt_password
self.salt = make_salt if new_record?
self.encrypted_password = encrypt(password)
end
def encrypt (string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
params hash on submit:
{"commit"=>"Submit",
"tran"=>{"total"=>"100",
"submitting_user"=>"1",
"description"=>"Description"},
"authenticity_token"=>"88qI+iqF92fo/M9rPfMs1CLpEXqFLGQXfj0c9krXXac=",
"utf8"=>"✓",
"user"=>"1"}
error:
User(#70040336455300) expected, got String(#70040382612480)
beginning of controller:
def create
#title = "Create Transaction"
#tran = Tran.new(params[:tran])
It crashes on the Tran.new line. Thanks so much!
Typically the User model would have has_many :transactions, :class_name => Tran
Then you would do this...
#user.transaction_create(params[:tran])
or
#user.build
it depends on what parameters are actually passed in params[:tran], but the idea is that the has_many side does the creating of the belongs_to.
I figured it out! The problem the whole time was that my db column name on my Trans table that linked to my Users table was submitting_user instead of submitting_user_id. Then, when I added the belongs_to association to submitting_user rails got confused and made that field a User, instead of an integer.

ArgumentError in Chapter 7 of "Rails Tutorial" by Michael Hartl

everyone. I've got the following problem:
After implementing has_password? in section 7.2.3 RSpec displays the following error for "should create a new instance given valid attributes" test for example
1) User should create a new instance given valid attributes
Failure/Error: User.create!(#attr)
ArgumentError:
wrong number of arguments (1 for 0)
# ./app/models/user.rb:42:in secure_hash'
# ./app/models/user.rb:39:inmake_salt'
# ./app/models/user.rb:30:in encrypt_password'
# ./spec/models/user_spec.rb:14:inblock (2 levels) in '
Finished in 1.47 seconds
1 example, 1 failure
<-- Slave(1) run done!
I don't understand, what exactly causes the problem.
Here is my user.rb code:
require 'digest'
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
# Automatically create the virtual attribute "password_confirmation"
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
# Return 'true' if the user's password matches the submitted password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
private
def encrypt_password
self.salt = make_salt if new_record?
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash
Digest::SHA2.hexdigest(string)
end
end
What can it be?
Thank you in advance!
Your secure_hash method needs to take an argument.
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end

Resources