I try to change my rails-3.2-model to rails 4, but I dont understand it.
Maybe you can help me to change it.
3.2:
class User < ActiveRecord::Base
attr_accessible :email, :username, :password, :password_confirmation
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email, :on => :create
validates_presence_of :username, :on => :create
validates_uniqueness_of :email
validates_uniqueness_of :username
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
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
4.0.4:
class User < ActiveRecord::Base
validates :name, presence: true, uniqueness: {case_sensitive: true}, length: {minimum: 3, too_short: "must have at least %{count} characters"}
validates :email, presence: true, uniqueness: {case_sensitive: true}
validates :password_hash
end
I tried to get rid off the attr_accessible
and attr_accessor
, but I don't know how.
attr_accessor :password
and attr_accessible [...] :password_confirmation
are not stored in the database, so how can I use it in my view?
EDIT:
View:
<p>Sign Up</p>
<%= form_for @user, :as => :user, :url => auth_sign_up_path, :html => {:class => 'navbar-form', :role => 'login'} do |user_form_builder| %>
<p>
<%= user_form_builder.label 'name:' %><br/>
<%= user_form_builder.text_field :name %>
<%= show_field_error(@user, :name) %>
</p>
<p>
<%= user_form_builder.label 'email:' %><br/>
<%= user_form_builder.text_field :email %>
<%= show_field_error(@user, :email) %>
</p>
<p>
<%= user_form_builder.label 'password:' %><br/>
<%= user_form_builder.password_field :password %>
<%= show_field_error(@user, :password) %>
</p>
<p>
<%= user_form_builder.label 'password confirmation:' %><br/>
<%= user_form_builder.password_field :password_confirmation %>
<%= show_field_error(@user, :password_confirmation) %>
</p>
<p>
<%= user_form_builder.submit 'Sign Up' %>
<%= user_form_builder.submit 'Clear Form', :type => 'reset' %>
</p>
<% end %>
Controller:
def sign_up
@user = User.new
end
def register
@user = User.new(user_params)
if @user.valid?
@user.save
session[:user_id] = @user.id
flash[:notice] = 'Welcome.'
redirect_to :root
else
render :action => "sign_up"
end
end
private
def user_params
params.require(:user).permit(:email, :name, :password, :password_confirmation)
end
Model:
require 'bcrypt'
class User < ActiveRecord::Base
attr_accessor :name, :email, :password, :password_confirmation
before_save :encrypt_password
after_save :clear_password
validates :name, presence: true, uniqueness: {case_sensitive: true}, length: {minimum: 3, too_short: "must have at least %{count} characters"}
validates :email, presence: true, uniqueness: {case_sensitive: true}
validates :password, presence: true, length: {minimum: 8, too_short: "must have at least %{count} characters"}, :confirmation => true #password_confirmation attr
def initialize(attributes = {})
super # must allow the active record to initialize!
attributes.each do |name, value|
send("#{name}=", value)
end
end
def self.authenticate_by_email(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def self.authenticate_by_name(name, password)
user = find_by_username(name)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
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
def clear_password
self.password = nil
end
end
Migration:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.string :password_hash
t.string :password_salt
t.string :cal_owner, :array => true, :default => '{}'
t.string :cal_joined, :array => true, :default => '{}'
t.timestamps
end
end
end
Routes:
Calendar::Application.routes.draw do
# You can have the root of your site routed with "root"
root 'welcome#index'
get "auth/sign_up" => "auth#sign_up"
get "auth/sign_in" => "auth#sign_in"
get "auth/sign_out" => "auth#sign_out"
get "auth/settings"
get "auth/pwd_reset"
get "welcome/index"
post "auth/sign_in" => "auth#login"
post "auth/sign_up" => "auth#register"
end
I used a tutorial, but I didnt know why the author add this:
def initialize(attributes = {})
super # must allow the active record to initialize!
attributes.each do |name, value|
send("#{name}=", value)
end
end
The author wrote:
For each key-value pair (hash) we assign the value to the attribute by
calling the "send" function (all method calls in Ruby are actually
messages.)
Important:
We don't actually need to do this for the User class because the
constructor provided by Rails will allow us to do a "mass assign" from
a hash as long as the fields that we are assigning have been
designated as "attr_accessible", which they have. However, there are
cases when one wants to initialize several fields (such as ID's in a
many-to-many table) that are not intended to be accessible to a view
but instead are designated with an "attr_accessor" instead. The above
function is a simple way of providing safe mass assign capability for
internal constructors.