Wednesday, 28 November 2012

Guest user functionality in rails app

Hi,

In many requirements you may be asked to provide guest user functionality in application. Here are the simple steps to make that functionality simple.


rails g migration add_guest_to_users guest:boolean
rake db:migrate


index.html.erb
<p><%= button_to "Guest User!", users_path, method: :post %></p>



layouts/application.html.erb
Logged in as <strong><%= current_user.name %></strong>.
<% if current_user.guest? %>
  <%= link_to "Become a member", signup_path %>
<% else %>
  <%= link_to "Log Out", logout_path %>
<% end %>


user_controller.rb
def create
  @user = params[:user] ? User.new(params[:user]) : User.new_guest
  if @user.save
    current_user.move_to(@user) if current_user && current_user.guest?
    session[:user_id] = @user.id
    redirect_to root_url
  else
    render "new"
  end
end


models/user.rb
class User < ActiveRecord::Base
  has_many :tasks, dependent: :destroy

  attr_accessible :username, :email, :password, :password_confirmation

  validates_presence_of :username, :email, :password_digest, unless: :guest?
  validates_uniqueness_of :username, allow_blank: true
  validates_confirmation_of :password

  # override has_secure_password to customize validation until Rails 4.
  require 'bcrypt'
  attr_reader :password
  include ActiveModel::SecurePassword::InstanceMethodsOnActivation
 
  def self.new_guest
    new { |u| u.guest = true }
  end
 
  def name
    guest ? "Guest" : username
  end
 
  def move_to(user)
    tasks.update_all(user_id: user.id)
  end
end


lib/tasks/guests.rake
namespace :guests do
  desc "Remove guest accounts more than a week old."
  task :cleanup => :environment do
    User.where(guest: true).where("created_at < ?", 1.week.ago).destroy_all
  end
end


By applying above simple steps you can add guest user functionality in existing rails application easily .

Thank You,
Uma Mahesh.

ruby 1.9.3 perfomance

Hi,

Recently I have read article about ruby performance issue compared to ruby 1.9.2 and ruby 1.9.3 and came to see few important points that need to be noted. Below is the discussion.

We just switched a site from Apache + ruby 1.9.2 to nginx + ruby 1.9.3 a few days ago and I noticed that somehow the site speed has noticably dropped on the ruby side of things and I just couldn’t understand why.

/opt/nginx/logs# rvm use 1.9.3
Using /usr/local/rvm/gems/ruby-1.9.3-p327
/opt/nginx/logs# time ruby -e "count = 0; while(count < 100000000); count = count + 1; end; puts count"
100000000
real 0m7.655s
user 0m7.632s
sys 0m0.012s
/opt/nginx/logs# rvm use 1.9.2
Using /usr/local/rvm/gems/ruby-1.9.2-p320
/opt/nginx/logs# time ruby -e "count = 0; while(count < 100000000); count = count + 1; end; puts count"
100000000
real 0m4.716s
user 0m4.716s
sys 0m0.000s
Checking make.log showed that 1.9.3 was indeed compiled w/o any optimizations. After I hand-compiled a 1.9.3, I got this:

/opt/ruby193opt/bin# ./ruby -v
ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-linux]
/opt/ruby193opt/bin# time ./ruby -e "count = 0; while(count < 100000000); count = count + 1; end; puts count"
100000000
real 0m4.641s
user 0m4.628s
sys 0m0.008s
/opt/ruby193opt/bin# ruby -v
ruby 1.9.2p320 (2012-04-20 revision 35421) [x86_64-linux]
puck352:/opt/ruby193opt/bin# time ruby -e "count = 0; while(count < 100000000); count = count + 1; end; puts count"
100000000
real 0m4.634s
user 0m4.624s
sys 0m0.012s
Now it performs on par with 1.9.2
 Thank You,
Uma Mahesh.



Thursday, 1 November 2012

ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint

ActiveRecord::RecordNotUnique (PG::Error: ERROR:  duplicate key value violates unique constraint

ActiveRecord::RecordNotUnique: PG::Error: ERROR: duplicate key value violates unique constraint "users_pkey" DETAIL: Key (id)=(143) already exists.

The above issue will raise when you dump data to database and start creating records after that. You need to set the sequence value manually to over come this issue. Below is the command to set the value for 'users_id_seq'


SELECT setval('users_id_seq', (SELECT max(id) FROM users));

In the above query 'users' is the tale and you are manually changing the 'users_id_seq' value to max(id) of users.


Thank You,
Uma Mahesh.