Railscasts
No1. Caching with instance variable
컨트롤러에서 모델의 find 메소드를 사용하는 경우 매번 DB 에 쿼리를 날리게 된다.
class ApplicationController < ActionController::Base
def current_user
User.find(session[:user_id])
@current_user ||= User.find(session[:user_id])
end
end
볼드체로된 부분 처럼 항상 DB 쿼리를 하지 않도록, 인스턴스 변수를 활용해서 캐싱하는 형태로 사용하면 항상 DB자원을 사용하는 것을 줄여줄 수 있다.
No2. Dynamic find by methods
find 메소드의 형태를 좀더 간소하게 사용할 수 있는 find_by_methods 의 사용에 대해서 알아보자. 간단하므로 아래 예제로 확인해볼 수 있다.
find 메소드의 컨디션에 해당하는 컬럼을 메소드 명으로 줄 수 있다.
class TasksController < ApplicationController
def incomplete
@tasks = Task.find(:all, :conditions => ['complete =?', false])
@tasks = Task.find_all_by_complete(false)
end
def last_incomplete
@task = Task.find(:first, :conditions => ['complete = ?', false], :order => 'created_at DESC')
@task = Task.find_by_complete(false, :order => 'created_at DESC')
end
end
No3. Find through association
모델간의 관계를 이용해서 데이타를 찾아도록 하는 방법
모델의 관계는 다음과 같다.
class Project < ActiveRecord::Base
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to :project
end
이경우 Association 을 이용해서 데이타를 가져오면서 No2 에서 제공하는 find_by_methods 까지 활용해보자.
class ProjectsController < ApplicationController
def show
@project = Project.find(params[:id])
@tasks = Task.find(:all, :conditions => ['project_id = ? AND complete = ?', @project.id, false])
@tasks = @project.tasks.find_all_by_complete(false)
end
end
깔끔한 코드 ~~
No4. Move find into model
custom find 메소드를 생성해서 find 메소드를 모델로 이동시킬 경우 얻을 수 있는 장점
class TaskController < ApplicationController
def index
@tasks = Task.find_all_by_complete(false, :order => 'created_at DESC')
@tasks = Task.find_incomplete
end
end
위와 같은 형태에서 find_all_by_complete 를 find_incomplete 라는 클래스 메소드로 활용하게 되면 Task 모델에 다음과 같은 클래스 메소드를 추가하면 된다.
def self.find_incomplete
find_all_by_complete(false, :order => 'created_at DESC')
end
이런식으로 모델의 클래스 메소드로 생성해 두는 경우 아래와 같이 컨트롤러에서도 활용 가능하다.
class ProjectController < ApplicationController
def show
@project = Project.find(params[:id])
@tasks = @project.tasks.find_all_by_complete(false, :order => 'created_at DESC')
@tasks = @project.taskts.find_incomplete
end
end
No5. Using with scope
find 메소드를 커스텀하게 작성해서 모델로 이동시켜서 사용하는 경우, 커스텀 find 메소드로는 파라미터를 어떻게 전달할까?
class Task < ActiveRecord::Base
belongs_to :project
def self.find_incomplete
find_all_by_complete(false, :order => 'created_at DESC')
end
end
이렇게 커스텀 find 메소드인 find_incomplete 를 생성했다. 이 메소드를 사용하는 컨트롤러에서는 호출시에 현재로서는 파라미터를 전달할 방법이 없다.
예를 들어서 아래와 같이 호출하고 싶은 경우 find_incomplete 메소드를 어떻게 수정하면 될까?
class TaskController < AppliationController
def index
@tasks = Task.find_incomplete :limit => 20 #이렇게 파라미터를 추가해서 호출하고 싶다.
end
end
방법은 Rails 에서 제공하는 함수인 with_scope 를 사용하면 좀더 우아하게 처리할 수 있다.
find_incomplete 클래스 메소드를 수정해보자.
def self.find_incomplete(options = {})
with_scope :find => options do
find_all_by_complete(false, :order => 'created_at DESC')
end
end
이렇게 수정하면 어떠한 형태의 파라미터도 다이내믹하게 처리할 수 있겠다.
우아해졌다 ~~
Comments (0)