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
이렇게 수정하면 어떠한 형태의 파라미터도 다이내믹하게 처리할 수 있겠네요.
우아해졌습니다 ~~
P.S. 보다보니 벌써 동영상이 #11 까지 올라왔네요.. 나머지도 한번 가서 보세요... 짧으니 한꺼번에 보시면 저같은 초보 분들은 도움이 될만한 것들을 금방 얻을 수 있겠습니다.
scope access method 관련해서 레일즈 플러그인이 하나 나왔네요.
AutoScope
Examples
Declare your scopes within your ActiveRecord::Base subclasses.
class Contact < ActiveRecord::Base이렇게 해주면 아래와 같이 사용하실 수 있습니다.
auto_scope \
:old => {:find => {:conditions => ["born_on < ?", 30.years.ago]}},
:young => {:find => {:conditions => ["born_on > ?", 1.year.ago]}}
end
class Testimonial < ActiveRecord::Base
auto_scope \
:approved => {
:find => {:conditions => ["approved_at < ?", proc {Time.now}]},
:create => {:approved_at => proc {Time.now}}},
:unapproved => {
:find => {:conditions => "approved_at IS NULL"},
:create => {:approved_at => nil}}
end
Testimonial.approved.count
Testimonial.unapproved.create!(params[:testimonial])
@young_contacts = Contact.young
@contacts = Contact.old.find(:all, :conditions => ["name LIKE ?", params[:name]])
'재미' 카테고리의 다른 글
오픈마루 첫번째 데브데이 - RubyTutorialSession 자료 및 후기 (1) | 2007.07.03 |
---|---|
루비세미나3회후기 (0) | 2007.06.19 |
Web-based IDE and debugger for Rails (0) | 2007.02.14 |
제 2회 루비 세미나 다녀왔습니다. (부제: 루비 코드를 말한다.) (16) | 2007.01.22 |
행복 + 웃음 + 엘프 + 크리스마스 (바이러스 맞군요) (0) | 2006.12.23 |