Thursday, 20 August 2015

How To: Create custom layouts for devise:


1, Define layouts in the ApplicationController
2, Define layouts in config (config/environment.rb for rails 2, config/application.rb in rails 3)

Define layouts in the ApplicationController:

class ApplicationController < ActionController::Base
  layout :check_layout

  protected

  def check_layout
    if devise_controller? && resource_name == :user && action_name == "new"
      "layout_for_devise"
    else
      "application"
    end
  end
end

devise_controller? --> Determine weather it's devise controller or not
resource_name ---> Dealing with roles
action_name --> To determine specific action

2, Define in config:

Below code need to write in application.rb:

#to set layout for specific controller
config.to_prepare do
  Devise::SessionsController.layout "layout_for_sessions_controller"
  Devise::RegistrationsController.layout proc { |controller| user_signed_in? ? "application" : "devise" }
end

#to set layout for devise mailer
config.to_prepare do
  Devise::Mailer.layout "email_layout" #email_layout.erb
end

If u want to write these configurations in devise.rb:
# append to end of config/initializers/devise.rb
Rails.application.config.to_prepare do
  Devise::SessionsController.layout "layout_for_sessions_controller"
  Devise::RegistrationsController.layout proc { |controller| user_signed_in? ? "application" : "layout_for_registration_controller" }
end


that's it..

To generate devise views:
rails generate devise:views

To destroy generate devise views:
rails destroy devise:views

if you want to destroy an especific set of views use:
rails destroy devise:views model
instead of model use the name of the model you want to destroy, for example user, or admin whichever your model is.

Monday, 3 August 2015

Rails touch method

touch method:

Saves the record with the updated_at/on attributes set to the current time.

Product.last.touch # it will set update_at with current date and time

Product.last.touch(:last_signed_in) # it will set last_signed_in with current date and time

How to skip rails validation



Skip all validations:

validates :name, presence: true

@user.name = ""
@user.save(validate: false)

It saves the record without running any validations.

Skipping individual validations:

Skipping individual validations requires a bit more work. First, we need to create a property on our model called something like skip_name_validation:

attr_accessor :skip_name_validation, :skip_price_validation

Next we will tell Rails to check and see if that property is set to true:

validates :name, presence: true, uniqueness: true, unless: :skip_name_validation
Validates: price, presence: true, numerically: {greater_than: 0 }, unless: :skip_price_validation

Finally we will set the property to true any time we want to skip validations. For example:

def create
   @product = Product.new(product_params)
   @product.skip_name_validation = true
   if @product.save
    redirect_to products_path, notice: "#{@product.name} has been created."
  else
    render 'new'
  end
end

def update
  @product = Product.find(params[:id])
  @product.attributes = product_params
  @product.skip_price_validation = true
  if @product.save
    redirect_to products_path, notice: "The product \"#{@product.name}\" has been updated. "
  else
    render 'edit'
  end
end

Above you will see that for the create method we skip name validation; and for the update method we skip price validation. A complete listing of the model is shown below.

class Product < ActiveRecord::Base
  validates :name, presence: true, uniqueness: true, unless: :skip_name_validation
  validates :price, presence: true, numericality: { greater_than: 0 }, unless: :skip_price_validation

  attr_accessor :skip_name_validation, :skip_price_validation
end
That's it...:-)


Friday, 1 May 2015

Usage Of Yield In Template Rendering

Without any arguments, yield will render the template of the current controller/action. So if you're on the cars/show page, it will render views/carts/show.html.erb.
When you pass yield an argument, it lets you define content in your templates that you want to be rendered outside of that template. For example, if your cars/show page has a specific html snippet that you want to render in the footer, you could add the following to your show template and the car_general layout:
<% content_for :footer do %>
  This content will show up in the footer section
<% end %>
layouts/car_general.html.erb
<%= yield :footer %>

Monday, 20 April 2015

Difference between += and .concat


example:

2.1.1 :009 > x="saritha"
 => "saritha"
2.1.1 :010 > x+="srinivas"
 => "sarithasrinivas"
2.1.1 :011 > x.object_id
 => 19461520
2.1.1 :012 > x+="sree"
 => "sarithasrinivassree"
2.1.1 :013 > x.object_id
 => 19365720
2.1.1 :014 > x="hello"
 => "hello"
2.1.1 :015 > x.object_id
 => 19016160
2.1.1 :016 > x.concat("hi")
 => "hellohi"
2.1.1 :017 > x.object_id
 => 19016160
 2.1.1 :018 > x.concat(2)
 => "hellohi\u0002"
2.1.1 :019 > x.object_id
 => 19016160
2.1.1 :020 > i=10
 => 10

Based on above exple, += always creates a new object to perform string operation and .concat work on existing object only. so concat() is faster than +.
another exmple:
2.1.1 :021 > x = "hello"
 => "hello"
2.1.1 :022 > x.object_id
 => 19923680
2.1.1 :023 > x << "joy"
 => "hellojoy"
2.1.1 :024 > x.object_id
 => 19923680
2.1.1 :025 > x << "2015"
 => "hellojoy2015"
2.1.1 :026 > x.object_id
 => 19923680

<< alias for .concat
Fair question. The plus symbol, it seems, creates an intermediary copy of the variables before combining them, whereas << and concat directly concatenate the variables to each other without first producing an intermediary copy.

Thursday, 16 April 2015

Pagination With Ajax Using Will Paginate in Ruby on Rails



step1: I have and index page. TO display all records.

controller method:
    def index
      @products = Product.paginate(:order =>"name ASC" ,:page => params[:page], :per_page => 14)
      respond_to do |format|
        format.html # index.html.erb
        format.json { render json: @products }
        format.js
      end
    end


step2: i have a dorp down with type1 ans type2 categories.
index.html.erb

<h1>Products</h1>
<%= select_tag :type, options_for_select([["type1",1],["type2",2]]), { :prompt => 'Select Category', :class => 'form-control', :id =>"type", :style => "width: 24%;margin-bottom: 7px;"} %>
<div id="products">
 <%= render "products/products" %>
</div>

<script>
$( document ).ready(function() {
    $("#type").change(function() {
        var type = $('select#type :selected').val();
        $.ajax({
            url: '/admin/index/'+type,
                dataType: "script"
        });
    });
    $(function(){
           $('.pagination a').attr('data-remote', 'true')
    });
});
</script>

step 3:
index.js.erb

jQuery('#products').html(" 'products/products' )%>");
$('.pagination a').attr('data-remote', 'true');

step 4:
_products.html.erb
<div class="listing">
      <% @products.each do |product| %>
        <div>
     <span> <%= product.title %> </span>
           <span> <%= product.price %>  </span>
        </div>
     <% end %>
</div>
<%= will_paginate @products %>


Thats all. ajax based pagination is done....

Thursday, 9 April 2015

Mongoid scopes usage

class Person
  include Mongoid::Document
  field :occupation, type: String
  field :age, type: Integer

  scope :rock_n_rolla, -> { where(occupation: "Rockstar") }
  scope :washed_up, where(:age.gt => 30)
  scope :age_or_occupation, ->  {any_of({occupation: "Rockstar"}, {age: 18}) }
  scope :over, ->(limit) { where(:age.gt => limit) }
end

# Find all the rockstars.
Person.rock_n_rolla

# Find all rockstars age greater than 30.
Person.washed_up.rock_n_rolla

# Find all rockstars or other persons have their age as 18 (or operation)
Person.age_or_occupation

# Find a criteria rockstart with 60 as their aget.
Person.rock_n_rolla.over(60)