Dec
22
2011

How to Pass Params to Named Scope in Rails

Hi guys meet again with me, Dadan Ramdan. In my previous post in create named scope in rails, I told you about named scope in rails, what excess of named scope,how to create and how to use it. Now i will tell you, how to pass params to named scope in rails. For example, we will search for users by user_name, first_name, last_name, email and city. Most of us, will create the in the controller like this :

 

class UsersController < ApplicationController
  def search
      @users = User.where(["user_name LIKE ? OR first_name LIKE ? OR last_name LIKE ? OR email LIKE ? OR city LIKE ?",
      "%#{params[:keyword]}%", "%#{params[:keyword]}%", "%#{params[:keyword]}%", "%#{params[:keyword]}%", "%#{params[:keyword]}%"])
  end
end

 

That’s will work correctly, but that’s not recomended by rails development. I think the best way to do it is to create named scope and pass the params to named scope. Please look below, how to pass params to named scope in rails.

In user model :

class User < ActiveRecord

   scope :search, lambda{|keyword| where(["user_name LIKE ? OR first_name LIKE ? OR last_name LIKE ? OR email LIKE ? OR city LIKE ?",
      "%#{keyword}%", "%#{keyword}%", "%#{keyword}%", "%#{keyword}%", "%#{keyword}%"])}
end

In user controller :

class UsersController < ApplicationController
  def search
      @users = User.search(params[:keyword])
  end
end
Share

Dec
20
2011

How to Create Named Scope in Rails

Named scope used to specify commonly used sql queries which can be define as method on model or on the association objects. With named scope, you can use every that have been included ActiveRecord method such us joins, select, where and etc.

Most of us start out writing our queries directly in the controllers, like this :

class  ArticleController < ApplicationController

  def article_today
    @articles = Article.where(["created_at > ?", Time.now.beginning_of_day])
  end
end

That’s works, but it’s broken cardinal role of Rails development. Rather than we embedding sql query in our controller to find article which created today in our site, much better to write something code called named scope in model which would return a collection of Article objects. To create a scope, we use the named_scope method in Rails 2 and scope method in Raials 3 above inside the class model.

Rails 2 :

class Article < ActiveRecord::Base

 named_scope :today, where(["created_at > ?", Time.now.beginning_of_day])
end

Rails 3 above :

class Article < ActiveRecord::Base

 scope :today, where(["created_at > ?", Time.now.beginning_of_day])
end

Then in our controller we call :

calss ArticlesController < ApplicationController
 def article_today
 @articles = Article.today
 end
end

That’s would return a collection of Article objects which created today. It’s look DRY query. In addition we also use scope to get object with join table. Please look below :

Rails 2 :

class User < ActiveRecord::Base
 has_many :addresses

 named_scope :group_by_city, joins(:addresses).where(["addresses.city = ?", "Jakarta"])
end

Rails 3 above :

class User < ActiveRecord::Base
 has_many :addresses

 scope :group_by_city, joins(:addresses).where(["addresses.city = ?", "Jakarta"])
end

 

Share

Dec
12
2011

How to Connect to Multiple Database in Rails

I have problem in build rails application that how to connect to multiple database in rails. After I searching i found how to fix my problem in here and in Rails Recipe B3 ebook.

By default Rails have a connection to one database per aplication. But if you want to connect to multiple databse, it’s very simple in rails. To create connection to multiple database in a rails application, we must set up named connection in database configuration(database.yml), configure model, and use inheritance to safely allow multiple models to use the new named connection.

In this case we have scenario like this :

 

connect to multiple database in rails

OK, let’s create a new rails application with mysql databse :

rails new multiple_database –database=mysql

In this case I use rails 3.1, but I think this same way in rails 3.0

Configure databse.yml to be like this:

development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: multiple_database_development
  pool: 5
  username: root
  password: root
  socket: /var/run/mysqld/mysqld.sock

external_development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: multiple_database_external
  pool: 5
  username: root
  password: root
  socket: /var/run/mysqld/mysqld.sock

Now create database whit this command line :

rake db:create:all

Create article and comment model :

rails g model article title:string content:text
rails g model comment article_id:integer name:string content:text

Open article model, and edit to be like this :

class Article < ActiveRecord::Base
  has_many :comments
end

Open comment model, and edit to be like this :

class Comment < ActiveRecord::Base
  establish_connection("external_development") #external_development is a named configuration in database.yml
  belongs_to :article
end

Open create_comment migration file and add this section above def self.up in rails 3.0 or def change in rails 3.1:

def connection
    Comment.connection
end

so it becomes like this :

class CreateComments < ActiveRecord::Migration

  def connection
    Comment.connection
  end 

  def change
    create_table :comments do |t|
      t.integer :article_id
      t.string :name
      t.text :content

      t.timestamps
    end
  end
end

Note : Comment.connection is a method to determine which database is used in migration as it has been declared in comment model.

Don’t forgate migrate file to database:

rake db:migrate

 

Open rails console, and chek connection :

create article

article = Article.create(:title => "First Article", :content => "Content of first article")

create comment

comment = article.comments.create(:name => "Dan", :content => "this is comment content")

 

Check database connection :

Article Connection

Article.connection.current_database

will be return :

=> "multiple_database_development"

Comment Connection

Comment.connection.current_database

will be return :

=> "multiple_database_external"

Now we can see that different database used. Article model use “multiple_database_development” database and comment model use “multiple_database_external” database.

Share

Sep
10
2011

Rails Cache with Action Caching

We can’t use page caching for page that require to restrict access somehow and ignored  all get parameters is one more of Page caching issue. Therefore Action caching comes in. Before use action caching, you must setting perfome caching to true.

Action caching working like page caching except for the incoming request does go from the web server to the action pack and rails stack, thus before the cache served, before filters can be run on it. Action caching will allows  restriction and authentication to be run while the result of the output from cached copy still serving. Aside from that, the action caching have the exact same way of working with page caching.

To enable action caching, we simply add caching_action method to our class in controllers file:

class ArticlesController < ActionController

  caches_action :index

  def index
    @articles = Article.all
  end
end

 

 

We can passing a :cache_path option to modify the default caching action path. This is useful for actions with multiple routes that should be cached differently, because this will be passed to  ActionCachePath.path_for directly. For example, in this case we will use it for handle pagination. Let’s look this code :

caches_action :index, :cache_path => Proc.new {|c| c.request.url }

Finaly,to expire action caching, we simply add expire_action method to our controller :

def create
   @article = Article.new(params[:article])

    if @article.save
        expire_page :action => :index
    end
end

rails cache with action caching

 

Share

Aug
03
2011

Rails Cache with Page Caching

This is an introduction to the three types of caching techniques that Rails provides by default without the use of any third party plugins.

First we must to ensure rails caching is enabled. By default, rails caching enabled only in production environments and disbaled in development and test environments. To start playing with rails caching you must make sure that config.action_controller.perform_caching is set to true. You can make this change in your application’s environment files (in config/environments directory).

config.action_controller.perform_caching = true

Page caching is the most efficient and simplest form of Rails caching besides Action Caching. The first time  anyone user requests a particular URL, Rails application will gets invoked and generates a HTML page. Cache will save the contents of this page. Next time if there are anyone user request a same url, cache will deliver the html page already stored. Rails application never sees the request.
To enable page caching, we simply add caching_page method to our class in controllers file:

class ArticlesController < ActionController

  caches_page :index

  def index
    @articles = Article.all
  end
end

Let’s say we have a ArticlesController class and an index action that show list of all articles. For example user requests a /articles page, Rails will generate a file called articles.html in public directory by default. Before passes the next request for /articles, the web server will look for that file and delivered to user as HTML page.

To expire this cache, we simply add expire_page method. For example, in order this cache page expire when added a new article, we could add  expire_page method to ArticlesController in create action, like this :

def create
   @article = Article.new(params[:article])

    if @article.save
        expire_page :action => :index
    end
end

rails caching

Note  :

In page caching all parameters will be ignored. For example if we use pagination in our application, /articles?page=1 will be generated as products.html with no parameter reference to this page. So, if anyone user requests a /articles?page=2 later, they will get the same page with /articles?page=1.

Share

Older posts «