by sandipransing
Paypal standard website payment service allows online payment transactions for websites.
Before implementing payments inside rails app needs to have following things in place-
1. Register Paypal sandbox account
2. Paypal Merchant account api credentials i.e. login, password, signature, application_id
3. Paypal Buyer account creds to test payments
Bundle Install
# Gemfile
gem 'activemerchant
Gateway config
# config/gateway.yml
development: &development
mode: test
login: rana_1317365002_biz_api1.gmail.com
password: '1311235050'
signature: ACxcVrB3mFChvPIe8aDWQlLhAPN46oPBQCj7rJWPza6CDZmBURg.
application_id: APP-76y884485P519543T
production:
<<: *development
test:
<<: *development
New Payment Form
= form_for @payment ||= Payment.new, :url => pay_bill_url, :html => {:id => :payForm} do |p|
= p.text_field :amount
= p.submit 'Pay'
Generate & Migrate Payment Model
rails g model payment status:string amount:float transaction_number:string
rake db:migrate
Payment Model
# app/models/payment.rb
class Payment < ActiveRecord::Base
PROCESSING, FAILED, SUCCESS = 1, 2, 3
validates :amount, :presence => true, :numericality => { :greater_than => 0 }
def self.conf
@@gateway_conf ||= YAML.load_file(Rails.root.join('config/gateway.yml').to_s)[Rails.env]
end
## Paypal
def setup_purchase(options)
gateway.setup_purchase(amount * 100, options)
end
def redirect_url_for(token)
gateway.redirect_url_for(token)
end
def purchase(options={})
self.status = PROCESSING
#:ip => request.remote_ip,
#:payer_id => params[:payer_id],
#:token => params[:token]
response = gateway.purchase(amt, options)
if response.success?
self.transaction_num = response.params['transaction_id']
self.status = SUCCESS
else
self.status = FAILED
end
return self
rescue Exception => e
self.status = FAILED
return self
end
private
def gateway
ActiveMerchant::Billing::Base.mode = auth['mode'].to_sym
ActiveMerchant::Billing::PaypalExpressGateway.new(
:login => auth['login'], :password => auth['password'],
:signature => auth['signature'])
end
def auth
self.class.conf
end
end
Billing routes
## Callback URL
match '/billing/paypal/:id/confirm', :to => 'billing#paypal', :as => :confirm_paypal
## Create payment
match '/billing', :to => 'billing#create', :as => :pay_bill
## Request URL
match '/billing/paypal/:id', :to => 'billing#checkout', :as => :billing
match '/billing/thank_you/:id', :to => 'billing#checkout', :as => :billing_thank_you Billing Controller
# app/controllers/billing_controller.rb
class BillingController < ApplicationController
before_filter :get_payment, :only => [:checkout, :paypal, :thank_you]
def create
@payment = Payment.new params[:payment]
if @payment.save
## Paypal Checkout page
redirect_to billing_url
else
render :action => :new
end
end
# ASSUMPTION # payment is valid i.e. amount is entered
def checkout
response = @payment.setup_purchase(:return_url => confirm_paypal_url(@payment), :cancel_return_url => root_url)
redirect_to @payment.redirect_url_for(response.token)
end
## CALL BACK
def paypal
@payment = @payment.purchase(:token => params[:token], :payer_id => params[:PayerID], :ip => request.remote_ip)
@payment.save
redirect_to thank_you_billing_url(@order)
end
private
def get_payment
@payment = Payment.find_by_id(params[:id])
@payment && @payment.valid? || invalid_url
end
end
Views
# app/views/billing/thank_you.html.haml
- if @payment.success?
%p The transaction is successfully completed
- else
%p The transaction failed
Read More…
by sandipransing
Authorize Net SIM gateway transaction skips merchant side creditcard details form and directs transaction to be take place on gateway server.
# Gemfile
gem 'authorize-net'
Register for authorize net sandbox account click herePayment gateway credentials
# config/gateway.yml
development: &development
mode: test
login: 9gdLh6T
key: 67fu45xw6VP92LX1
production:
<<: *development
test:
<<: *development
Generate & Migrate Payment Model
rails g model payment status:string amount:float transaction_number:string
rake db:migrate
SIM gateway methods extracted and added to payment model
# app/models/payment.rb
class Payment < ActiveRecord::Base
PROCESSING, FAILED, SUCCESS = 1, 2, 3
validates :amount, :presence => true, :numericality => { :greater_than => 0 }
def self.conf
@@gateway_conf ||= YAML.load_file(Rails.root.join('config/gateway.yml').to_s)[Rails.env]
end
def success?
self.status == SUCCESS
end
## Authorize :: SIM
def setup_transaction(options ={})
options.merge!(:link_method => AuthorizeNet::SIM::HostedReceiptPage::LinkMethod::POST)
t = AuthorizeNet::SIM::Transaction.new(
auth['login'], auth['key'], amount,
:hosted_payment_form => true,
:test => auth['mode']
)
t.set_hosted_payment_receipt(AuthorizeNet::SIM::HostedReceiptPage.new(options))
return t
end
def auth
self.class.conf
end
end
Payment routes
## Callback URL
match '/billing/:id/confirm', :to => 'billing#authorize', :as => :confirm_billing
## Request URL
match '/billing/:id', :to => 'billing#checkout', :as => :billing
match '/billing/:id/thank_you', :to => 'billing#thank_you', :as => :thank_you_billing
Billing controller
# app/controllers/billing_controller.rb
class BillingController < ApplicationController
helper :authorize_net
before_filter :get_order, :only => [:checkout, :authorize, :thank_you]
def checkout
# ASSUMPTION order is valid means amount is entered
@transaction = @order.setup_transaction(
{:link_text => 'Continue',
:link_url => confirm_billing_url(@order)})
end
## CALL BACK
def authorize
resp = AuthorizeNet::SIM::Response.new(params)
if resp.approved?
@order.status = Payment::SUCCESS
@order.transaction_num = resp.transaction_id
else
@order.status = Payment::FAILED
end
@order.save(:validate => false)
redirect_to thank_you_billing_url(@order)
end
private
def auth
Payment.conf
end
def get_order
@order = Payment.find_by_id(params[:id])
@order && @order.valid? || invalid_url
end
end
Views Forms
# app/views/billing/checkout.html.haml
= form_for :sim_transaction, :url => AuthorizeNet::SIM::Transaction::Gateway::TEST, :html => {:id => :authForm} do |f|
= sim_fields(@transaction)
:javascript
$(document).ready(function(){
$('#authForm').submit();
})
# app/views/billing/thank_you.html.haml
- if @order.success?
%p The transaction is successfully completed
- else
%p The transaction failed
Read More…
by sandipransing
Customizing default rails form builder to adopt for labels, input fields, errors, hints, etc. in order to build forms just in minutes
# app/helpers/app_form_builder.rb
class AppFormBuilder < ActionView::Helpers::FormBuilder
HELPERS = %w[check_box text_field text_area password_field select date_select datetime_select file_field collection_select state_select label calendar_date_select]
def self.create_tagged_field(method_name)
define_method(method_name) do |name, *args|
errs = object.errors.on(name.to_sym) if object && object.errors
# initialize some local variables
if args.last.is_a?(Hash)
label = args.last.delete(:label)
suffix = args.last.delete(:suffix)
klass = args.last.delete(:class)
req = args.last.delete(:required)
end
label = 'none' if method_name == 'hidden_field'
label ||= name.to_s.titleize
label = nil if label == 'none'
klass = klass ? [klass] : []
# Custom class if it exists
if method_name =~ /text_field|check_box|select/
klass << method_name
end
klass << 'f' #A default selector
klass << 'error' if errs.present?
klass = klass.join(' ')
# Required Field Notations
if req == 'all' || (req == 'new' && object.new_record?)
label << @template.content_tag(:span, :*, :class => :req)
end
suffix = @template.content_tag(:label, suffix) if suffix.present?
label = @template.content_tag(:label, label) if label.present?
errs = @template.content_tag(:span, errs.to_s, :class => :message) if errs.present?
reverse = true if method_name == 'check_box'
if reverse
content = "#{super} #{suffix} #{label} #{errs}"
else
content = "#{label} #{super} #{suffix} #{errs}"
end
@template.content_tag(:div, content, :class => klass)
end
end
HELPERS.each do |name|
create_tagged_field(name)
end
end
Read More…
by sandipransing
Authorize Net Payment gateway provides api access to enable online payments
Gateway provides different api options to integrate-
1. Direct Post Method
In this method gateway handles all steps required in payment transaction flow securely and clean manner. To know more on this click here
2. Server Integration Method (SIM)
Here, Payment form and creditcard detail form resides on gateway site and all the steps in transaction carried out at gateway server
3. Advance Integration Method (AIM)
Provides full control of all the transaction steps at merchant server. Payment form resides on merchant side. merchnat server sends authorization and payment capture requests to gateway server where actual transaction takes place and response is sent back to merchant server to notify transaction status. To know detail integration on this click here
Prerequisites before getting started with integration
Sign up for a test account to obtain an API Login ID and Transaction Key. These keys will authenticate requests to the payment gateway.
Read More…
by sandipransing
railroady is UML class diagram generator for rails.
First you need to install `graphviz` pkg in order to have `dot` , `neato` commands available
group :development, :test do
gem railroady
end
Run below command to generate MVC diagrams
bundle install
rake diagram:all
Individual diagram generation
Model Diagram
railroady -M | dot -Tpng > models.png
Controller Diagram
railroady -C | dot -Tpng > controllers.png
AASM Diagram
railroady -A | dot -Tpng > aasm.png
Commands
-M, --models Generate models diagram
-C, --controllers Generate controllers diagram
-A, --aasm Generate "acts as state machine" diagram
Options
# Common options
-b, --brief Generate compact diagram
(no attributes nor methods)
-s, --specify file1[,fileN] Specify given files only for the diagram
(can take a glob pattern)
-e, --exclude file1[,fileN] Exclude given files
(can take a glob pattern)
-i, --inheritance Include inheritance relations
-l, --label Add a label with diagram information
(type, date, migration, version)
-o, --output FILE Write diagram to file FILE
-v, --verbose Enable verbose output
(produce messages to STDOUT)
Models diagram options:
-a, --all Include all models
(not only ActiveRecord::Base derived)
--all-columns Show all columns
(not just content columns)
--hide-magic Hide magic field names
--hide-types Hide attributes type
-j, --join Concentrate edges
-m, --modules Include modules
-p, --plugins-models Include plugins models
-t, --transitive Include transitive associations
(through inheritance)
Controllers diagram options:
--hide-public Hide public methods
--hide-protected Hide protected methods
--hide-private Hide private methods
Other Options
-h, --help Show this message
--version Show version and copyright
Read More…
by sandipransing
We all know Active Support library constantly keeps adding new extensions to ruby core library and hence rails framework.
Do you know now inside ruby class we can have class_attribute placeholder.
class A
class_attribute :counter, :access_time
end
A.counter = 12
A.counter #=> 12
A.new.counter #=> 12
Inheritance
class B < A
end
B.counter #=> 12
B.access_time #=> nil
B.access_time = Time.now
B.access_time #=> Wed Dec 28 18:55:06 +0530 2011
B.new.access_time #=> Wed Dec 28 18:55:06 +0530 2011
A.access_time = nil
Restricting instance from writing class_attributes
class V
class_attribute :counter, :instance_writer => false
end
V.new.counter = 12
NoMethodError: undefined method `counter=' for #
Other ways
a_class = Class.new{class_atrribute :counter}
a_class.counter = 13
a_class.counter #=> 13
a_class.new.counter #=> 13
p = Class.new { class_attribute :help, :instance_writer => false }
p.new.help = 'Got a second!'
NoMethodError: undefined method `help=' for #<#:0x7f8f9d5b1038>
p.help = 'Got a second!'
p.help #=> "Got a second!"
Read More…
by sandipransing
Authorize Net (AIM) method enables internet merchants to accept online payments via credit card.
Below post will show you how to integrate authorize net payment gateway inside rails app to accept online payments using activemerchant library.
# Gemfile
gem 'activemerchant', :require => 'active_merchant'
Register for authorize net sandbox account click here
Payment gateway credentials
# config/authorize_net.yml
development: &development
mode: test
login: 9gdLh6T
key: 67fu45xw6VP92LX1
production:
<<: *development
test:
<<: *development
Payment & creditcard form
# app/views/payments/new
= form_for @payment, :url => payments_url do |f|
= f.text_field :amount
= fields_for :creditcard, @creditcard do |cc|
= cc.text_field :name
= cc.text_field :number
= cc.select :month, Date::ABBR_MONTHNAMES.compact.each_with_index.collect{|m, i| [m, i+1]}, {:prompt => 'Select'}
= cc.select :year, Array.new(15){|i| Date.current.year+i}, {:prompt => 'Select'}
= cc.text_field :verification_value
= f.submit 'Pay'
Payments Controller
# app/controllers/payments_controller.rb
class PaymentsController < ApplicationController
def new
@payment = Payment.new
@creditcard = ActiveMerchant::Billing::CreditCard.new
end
def create
@payment = Payment.new(params[:payment])
@creditcard = ActiveMerchant::Billing::CreditCard.new(params[:creditcard])
@payment.valid_card = @creditcard.valid?
if @payment.valid?
@payment = @payment.process_payment(@creditcard)
if @payment.success?
@payment.save
flash[:notice] = I18n.t('payment.success')
redirect_to payments_url and return
else
flash[:error] = I18n.t('payment.failed')
end
end
render :action => :new
end
end
Generate & Migrate Payment Model
rails g model payment status:string amount:float transaction_number:string
rake db:migrate
Payment Model
# app/models/payment.rb
class Payment < ActiveRecord::Base
PROCESSING, FAILED, SUCCESS = 1, 2, 3
validates :valid_card, :inclusion => {:in => [true], :message => 'Invalid Credit Card'}
validates :amount, :presence => true, :numericality => { :greater_than => 0 }
def process_payment(creditcard)
ActiveMerchant::Billing::Base.mode = auth['mode'].to_sym
self.status = PROCESSING
response = gateway.purchase(amount * 100, creditcard)
if response.success?
self.transaction_number = response.subscription_id
self.status = SUCCESS
else
self.status = FAILED
end
return self
rescue Exception => e
self.status = FAILED
return self
end
def success?
self.status == SUCCESS
end
private
def gateway
ActiveMerchant::Billing::AuthorizeNetGateway.new(
:login => auth['login'],
:password => auth['key'])
end
def auth
@@auth ||= YAML.load_file("#{Rails.root}/config/authorize_net.yml")[Rails.env]
end
end
Read More…
by sandipransing
active_admin is the good way to provide rails administrative interface.
It provides front-end db administration and its customizable too :)
# Gemfile
gem 'activeadmin'
gem 'sass-rails'
gem "meta_search", '>= 1.1.0.pre'
Bundle install, generate config & migrate db
bundle install
rails g active_admin:install
rake db:migrate
Config
# config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.site_title = "Web Site :: Admin Panel"
config.site_title_link = "/"
config.default_namespace = :siteadmin
config.authentication_method = :authenticate_admin_user!
config.current_user_method = :current_admin_user
config.logout_link_method = :delete
end
Registering new resource
rails generate active_admin:resource category
Customization
# app/admin/categories.rb
ActiveAdmin.register Category do
scope :published
form do |f|
f.inputs do
f.input :name, :label => 'Name'
f.input :for_type, :label => "Category Type"
end
f.buttons
end
end
Adding Dashboard
ActiveAdmin::Dashboards.build do
section "Recent Categories" do
table_for Category.published.recent.limit(2) do
column :name do |c|
link_to c.name, [:admin, c]
end
column :created_at
end
strong { link_to "View All Categories", admin_categories_path }
end
end
Read More…
by sandipransing
Below extensions to active record base simplifies its usage while coding.
# config/initializers/core_extensions.rb
class ActiveRecord::Base
def self.pagination(options)
paginate :per_page => options[:per_page] || per_page, :page => options[:page]
end
def self.options_for_select(opts={})
opts[:name] ||= :name
opts[:attr] ||= :id
opts[:prompt] ||= 'Please Select'
all.collect{|c| [c.send(opts[:name].to_sym), c.send(opts[:attr].to_sym)]}.insert(0, [opts[:prompt], nil])
end
end
Usage
class Student< ActiveRecord::Base
#attributes #=> name, age
end
##
Student.pagination({:page => 10})
Student.pagination({:per_page => 2, :page => 2})
Student.options_for_select
Student.options_for_select({:prompt => 'Please select'})
Student.options_for_select({:name => :age})
Read More…
by sandipransing
Twitter bootstrap is css toolkit for rapid front-end UI development.
To get will-paginate working with bootstrap css we need to override default pagination link renderer.
Using Bootstrap-sass for rails 3
# Gemfile
gem 'sass-rails'
gem 'bootstrap-sass'
# app/assets/stylesheets/application.css.sass
// Place all the styles related to the home controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
//= require bootstrap
Add WillPaginate LinkRenderer to intitializer
# config/initializers/will_paginate.rb
module WillPaginate
module ActiveRecord
module RelationMethods
alias_method :per, :per_page
alias_method :num_pages, :total_pages
alias_method :total_count, :count
end
end
module ActionView
def will_paginate(collection = nil, options = {})
options[:inner_window] ||= 0
options[:outer_window] ||= 0
options[:class] ||= 'pagination pull-left'
options[:renderer] ||= BootstrapLinkRenderer
super.try :html_safe
end
class BootstrapLinkRenderer < LinkRenderer
protected
def html_container(html)
tag :div, tag(:ul, html), container_attributes
end
def page_number(page)
tag :li, link(page, page, :rel => rel_value(page)), :class => ('active' if page == current_page)
end
def previous_or_next_page(page, text, classname)
tag :li, link(text, page || 'javascript:void(0)'), :class => [classname[0..3], classname, ('disabled' unless page)].join(' ')
end
def gap
tag :li, link(super, 'javascript:void(0)'), :class => 'disabled'
end
end
end
end
Read More…
by sandipransing
Scopes are partial query conditions to database queries. scopes are always prefixed to class finders. There are several ways to use scopes inside rails models.
# 1. Scope defined below gets loaded while class definition loads
scope :active, where(:active => true)
scope :archived, where(:archived => true, :post_type => :general)
# 2.Dynamic scopes needs to be always defined inside lambda
scope :not_expired, lambda { where('expiry_date <= ?', Date.today) }
# 3.Combining scopes
scope :visible, published.not_expired
# 4. Passing parameters to scopes
# avoid below
scope :created_by_user, lambda {|user|
where('user_id = ?', user)
}
# use this
scope :created_by_user, lambda {|user|
where(:user_id => user)
}
# 5. passing multiple parameters
# avoid below
scope :made_between, lambda{|from, to|
where('created_date >= ? and created_date <= ?', from, to)
}
# use this
scope :made_between, lambda{|from, to|
where('created_date >= :from and created_date <= :to', :from => from, :to => to)
}
# 6. associations inside scope (joins and includes)
# below will perform eager loading effective when rendering posts with comments
scope :with_user_comments, lambda{|user|
includes(:comments).where('comments.user_id = ?', user)
}
# faster
# also can be done as post.comments.where(:user_id => user)
scope :with_user_comments, lambda{|user|
joins(:comments).where('comments.user_id = ?', user)
}
So, at last would suggest making use of symbols when there are multiple parameters to scopes and make maximum use of scopes rather than having where conditions everywhere :)
Read More…
by sandipransing
Ruby language is dynamic and robust. We can define methods inside ruby classes at runtime.
# bash
class A
define_method :a do
puts "hello"
end
define_method :greeting do |message|
puts message
end
end
A.new.a #=> hello
A.new.greeting 'Ram ram' #=> Ram ram
Can you imagine using dynamic methods below 24 lines of code is optimized to just 8 lines
To know more on below code read
# Earlier code
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_staff, :current_employee, current_admin
def authenticate_staff!(opts={})
current_staff || not_authorized
end
def current_staff
current_user if current_user.is_a? Staff
end
def authenticate_employee!(opts={})
current_employee || not_authorized
end
def current_employee
current_user if current_user.is_a? Employee
end
def authenticate_admin!(opts={})
current_admin || not_authorized
end
def current_admin
current_user if current_user.is_a? Admin
end
end
# New Version using dynamic methods
%w(Staff Employee Admin).each do |k|
define_method "current_#{k.underscore}" do
current_user if current_user.is_a?(k.constantize)
end
define_method "authenticate_#{k.underscore}!" do |opts={}|
send("current_#{k.underscore}") || not_authorized
end
end
Read More…
by sandipransing
jQuery datepicker plugin is used to display inline calendar popup that eases user input experience while entering date/time fields. Calendar can be easily binded to any html DOM element. To Apply different styles download css from here
# Gemfile
gem "jquery-rails"
# console
bundle install
# app/assets/javascripts/application.js.coffee
//= require jquery
//= require jquery_ujs
//= require jquery-ui
# app/views/layouts/application.html.haml
= stylesheet_link_tag "application"
= stylesheet_link_tag "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css"
= javascript_include_tag "application"
Before using timepicker download jquery-ui-timepicker js
wget http://trentrichardson.com/examples/timepicker/js/jquery-ui-timepicker-addon.js app/assets/javascripts/
Add timepcker js to application.js.coffee
//= require jquery-ui-timepicker-addon
## inside views
# app/views/users/_form.html.haml
= form_for @user ||= User.new do |f|
= f.text_field :birth_date, :id => 'birthDate'
= f.text_field :birth_time, :id => 'birthTime'
= f.text_field :exam_on, :id => 'examOn'
:javascript
$(document).ready(function() {
$("#birthDate").datepicker();
$("#birthTime").timepicker();
$("#examOn").datetimepicker();
$('#ui-datepicker-div').removeClass('ui-helper-hidden-accessible')
# customizations
$('#birth_date').datepicker({ dateFormat: 'dd-mm-yy' });
$('#birth_date').datepicker({ disabled: true });
$("#examOn").datetimepicker({ ampm: true });
$("#examOn").datetimepicker({ timeFormat: 'h:m', separator: ' @ ' });
Read More…
by sandipransing
Heroku is readonly file system hence write operations can only be done inside tmp directory.
Asset compilation on heroku can be handled in different ways
#1. compiling locally and placing inside assets directory
RAILS_ENV=production bundle exec rake assets:precompile
#2. It compiles assets while slug compiles
#3. Run time asset compilation
# It compiles assets for every rails request if it notifies assets got modified
# config/application.rb
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.assets.prefix = Rails.root.join('tmp/assets').to_s
# config/environments/production.rb
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
Note: write operation made inside tmp directory can not make any guarantee of being persisted hence be careful while using.
Read More…
by sandipransing
Devise handles authentication, authorization part inside rails application quite easily and its customizable too. One can always customize default devise configurations.
This Post will show how to manage multiple resources (like admin, staff, employees, guests etc.) through devise and STI with individual registrations process but login section will be the same for all.
# Gemfile
gem 'devise'
# console
bundle install
rails g devise_install
rails g devise User
rake db:migrate
rake routes
# User model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :lockable, :timeoutable, :confirmable and :activatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation
end
## Single Table Inheritance
# Admin model
class Admin < User
end
# Staff
class Staff < User
end
# Employee
class Employee < User
end
# Guest
class Guest < User
end
# routes
devise_for :users, :skip => :registrations
devise_for :admins, :skip => :sessions
devise_for :staffs, :skip => :sessions
devise_for :employees, :skip => :sessions
devise_for :guests, :skip => :sessions
# customizing default login/logout routes, views, actions
devise_for :users, :controller => {:sessions => 'sessions'}, :skip => [:sessions, :registrations] do
delete '/logout', :to => 'sessions#destroy', :as => :destroy_user_session
get '/login', :to => 'sessions#new', :as => :new_user_session
post '/login', :to => 'sessions#create', :as => :user_session
end
# app/controllers/sessions_controller
class SessionsController < Devise::SessionsController
end
## overriding default after sign in path
# app/controller/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :account_url
def account_url
return new_user_session_url unless user_signed_in?
case current_user.class.name
when 'Customer'
edit_customer_registration_url
when 'Admin'
edit_home_page_section_url
else
root_url
end if user_signed_in?
end
end
# app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
stored_location_for(resource) || account_url
end
end
## Changing default login field email to username
# config/initializers/devise.rb
config.authentication_keys = [ :username ]
# app/models/user.rb
validates :username, :presence => true,
:uniqueness => {:allow_blank => true},
:format => {:with => /^\w+[\w\s:?']+$/i, :allow_blank => true}
def email_required?
false
end
Adding devise authentication and authorization helper methods for above resources.
read more here
Read More…
|