I am following Michael Hartl's RoR tutorial, and it is covering the basics of password encryption. This is the User model as it currently stands:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :name, :email,: password, :password_confirmation
email_regex = /^[A-Za-z0-9._+-]+#[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+[A-Za-z]$/
#tests for valid email addresses.
validates :name, :presence => true,
:length => {:maximum => 50}
validates :email, :presence => true,
:format => {:with => email_regex},
:uniqueness => {:case_sensitive => false}
validates :password, :presence => true,
:length => {:maximum => 20, :minimum => 6},
:confirmation => true
before_save :encrypt_password
private
def encrypt_password
#encrypted_password = encrypt(password)
end
def encrypt(string)
string
end
end
(Obviously this isn't doing any encrypting because the encrypt method isn't really implemented but that's not my question)
I then wrote the following Spec (according to the tutorial):
require 'spec_helper'
describe User do
before(:each) do
#attr = { :name => "Example User", :email => "user#example.com",
:password => "abc123", :password_confirmation => "abc123"}
end
describe "password encryption" do
before(:each) do
#user = User.create!(#attr) # we are going to need a valid user in order
# for these tests to run.
end
it "should have an encrypted password attribute" do
#user.should respond_to(:encrypted_password)
end
it "should set the encrypted password upon user creation" do
#user.encrypted_password.should_not be_blank
end
end
end
The first of these tests passes, but since #user.encrypted_password is nil, the second test fails. But I don't understand why it's nil since the encrypt_password method should be being called by before_save. I know I must be missing something -- can someone please explain?
The encrypt_password method is incorrect, it should read:
def encrypt_password
self.encrypted_password = encrypt(password)
end
Note the use of self, which will properly set the attribute for the user object rather than creating an instance variable which is forgotten.
This is an old question and this is more of a comment but I don't have enough reputation to comment yet. Just wanted to link this question too as it goes into some solid detail about self.
Why isn't self always needed in ruby / rails / activerecord?
Related
I want to return some message that tell the user their password is not match with the confirm password field.
This is my code
post '/signup' do
user = User.new(params[:user])
if user.create_user
"#{user.list}"
else
"password not match"
end
end
require 'bcrypt'
class User < ActiveRecord::Base
include BCrypt
# This is Sinatra! Remember to create a migration!
attr_accessor :password
validates :username, presence: true, uniqueness: true
validates :email, :format => { :with => /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i ,
:message => "Email wrong format" }
validates :email, uniqueness: true,presence: true
validates :encrypted_password, presence: true
validates :encrypted_password, length: { minimum: 6 }
before_validation :checking_confirm_password
def initialize(signup = {})
##signup = signup
super()
#username = signup["username"]
#email = signup["email"]
#password = signup["password"]
#confirm_password = signup["confirm_password"]
end
def create_user
p_p = Password.create(#password)
p_h ||= Password.new(p_p)
user_hash = {:username => #username,:email => #email, :encrypted_password => p_h}
return User.create(user_hash)
end
def list
User.all
end
private
def checking_confirm_password
if #password != #confirm_password
return false
end
end
end
So how can i specific the message that will send back to the user,
if their password is not match or the validation fail before create the dada?
Thanks!
The validations populate #user.errors with all validation errors with all validation errors by field, so you can easily return all validation errors at once like so:
post '/signup' do
user = User.new(params[:user])
if user.create_user
"#{user.list}"
else
user.errors.full_messages
end
end
Have a look at: http://edgeguides.rubyonrails.org/active_record_validations.html#working-with-validation-errors
It seems that Rails doens't let me pass in more than one parameter when using this validation syntax. It always has a syntax method for an unexpected comma after the first argument.
class Apartment < ActiveRecord::Base
geocoded_by :location
after_validation :geocode
has_many :image_attachments
validates_associated :image_attachments
accepts_nested_attributes_for :image_attachments
validates :location, presence: true
validates :description, presence: true
validates :price, :presence => true
,:format => { with: /^[0-9]+$/, message: 'must be a number' }
validates :longitude, presence: true
end
It's bad formatting (and very "unsexy") to have the comma at the beginning of the next line.
Better to do...
validates :price, :presence => true,
:format => { with: /^[0-9]+$/, message: 'must be a number' }
...which should work fine.
A more consistent style is to use the Ruby 1.9 convention for key/value when key is a symbol.
validates :price, presence: true,
format: { with: /^[0-9]+$/, message: 'must be a number' }
I have three models, Course, Category and partner, a course can have many categories and a course belongs to one partner. When i create my course factory i get the following error:
Partner has a valid factory for course
Failure/Error: expect(FactoryGirl.create(:course)).to be_valid
ActiveRecord::RecordInvalid:
Validation failed: Name has already been taken
Here are my models:
class Category < ActiveRecord::Base
has_many :categorisations
has_many :courses, :through=> :categorisations
belongs_to :user
#validation
validates :name, presence: true , uniqueness: { scope: :name }
end
class Partner < ActiveRecord::Base
has_many :courses
belongs_to :user
validates :name, presence: true, uniqueness: { scope: :name }
validates :short_name, presence: true
VALID_HEX_COLOR= /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\z/
validates :primary_color, presence: true, format: { with: VALID_HEX_COLOR}
validates :secondary_color, presence: true, format: { with: VALID_HEX_COLOR}
end
class Course < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: [:slugged, :history]
has_many :categorisations, :dependent => :destroy
has_many :categories, :through=> :categorisations
belongs_to :partner
belongs_to :user
# validates_uniqueness_of :title
validates :title, presence: true
# validates :start_date, presence: true
# validates :duration, presence:true
# validates :state, presence:true
validates :categories, length: { minimum: 1 , message:"please select"}
validates :partner_id, presence: true, allow_nil: false
end
Here are my factories:
factory :partner do |f|
f.name Faker::Name.name
f.short_name "UCT"
f.primary_color "#009bda"
f.secondary_color "#002060"
end
factory :course do |f|
f.title "Introduction to Accounting short course"
f.start_date "2014-02-27 00:00:00"
f.duration "10 WEEKS ONLINE"
partner
categorisation
end
factory :categorisation do |categorisation|
categorisation.category {|category| category.association(:category)}
categorisation.course {|course| course.association(:course)}
end
I am not to sure what i am doing wrong, if anyone could advise me on what the problem may be or the process i can go about fixing this problem may be that would be a great help
try this out:
factory :partner do |f|
f.sequence(:name) { |n| "#{Faker::Name.name} #{n}" }
f.short_name "UCT"
f.primary_color "#009bda"
f.secondary_color "#002060"
end
factory :category do |f|
f.sequence(:name) { |n| "Category #{n}" }
end
All that i had to do was to add the following line to my course factory:
categories {[FactoryGirl.create(:category)]}
couse factory:
factory :course do |f|
f.title "Introduction to Accounting short course"
f.start_date "2014-02-27 00:00:00"
f.duration "10 WEEKS ONLINE"
partner
categories {[FactoryGirl.create(:category)]}
end
This is stumping me; For some reason the db is saving the record with nil fields instead of my params. Can anyone help me understand why ActiveRecord isn't using my params?
db migration:
class CreateRoutes < ActiveRecord::Migration
def change
create_table :routes do |t|
t.integer :user_id
t.string :start_address
t.string :end_address
t.text :waypoints
t.text :schedule
t.integer :duration
t.timestamps
end
add_index :routes, :user_id
end
end
route.rb:
class Route < ActiveRecord::Base
attr_accessor :start_address, :end_address, :waypoints, :schedule, :duration
belongs_to :user
#serialize :waypoints, :schedule
validates :user_id, presence: true
validates :start_address, presence: true
validates :end_address, presence: true
validates :schedule, presence: true
validates :duration, presence: true, numericality: { only_integer: true, greater_than: 0 }
end
routes_controller.rb:
class RoutesController < ApplicationController
.
.
.
def create
logger.debug "\n\n*** #{params[:route]} ***"
#route = current_user.routes.build(params[:route])
logger.debug "*** The route is #{#route.inspect} ***\n\n"
if #route.save
flash[:success] = "Route saved!"
redirect_to user_path(current_user)
else
render 'new'
end
end
.
.
.
end
logger output:
*** {"start_address"=>"123 Sample St.", "end_address"=>"321 Elpmas St.", "waypoints"=>"None", "schedule"=>"Mondays", "duration"=>"15"} ***
*** The route is #<Route id: nil, user_id: 1, start_address: nil, end_address: nil, waypoints: nil, schedule: nil, duration: nil, created_at: nil, updated_at: nil> ***
The attr_accessors will overwrite the accessors generated by ActiveRecord, causing them to not be persisted in the DB--they'll be like plain old Ruby properties/members instead of the meta-programmed magic of ActiveRecord.
DB properties (persistent properties) can have things like attr_accessible, though.
See the full error here: http://notesapp.heroku.com/
I'm using DataMapper and dm-validations 0.10.2. No matter how much I tweak my models, I get the same error, or another one. Here's how my model looks like:
class User
include DataMapper::Resource
attr_accessor :password, :password_confirmation
property :id, Serial, :required => true
property :email, String, :required => true, :format => :email_address, :unique => true
property :hashed_password, String
property :salt, String, :required => true
property :created_at, DateTime, :default => Time.now
property :permission_level, Integer, :default => 1
validates_present :password_confirmation, :unless => Proc.new { |t| t.hashed_password }
validates_present :password, :unless => Proc.new { |t| t.hashed_password }
validates_is_confirmed :password
Looks like you have an old version of DataObjects (probably pre 0.10.0) installed. Please update to the latest version and I think this error will disappear. Depending on the database you use it's most likely either do_postgres or do_mysql you need to upgrade.