박유진
parkeugene7676@gmail.com
- RORLab Biweekly Lecture -
질의 (1~5장)
조인, Eager Loading (12,13장)
스코프, 동적 파인더(14,15장)
sql, explain (17,20장)
Null Object
none 메소드는 연쇄가 가능한 관계(ActiveRecord::Relation)를 돌려줍니다(레코드를 돌려주지 않습니다). 이 메소드에게 받은 관계에 어떤 조건을 연결하더라도, 항상 빈 관계가 생성됩니다. 이는 메소드나 스코프에 연쇄(chain) 가능한 응답이 필요하고, 결과를 돌려주고 싶지 않은 경우에 편리합니다.
# 아래의 visible_posts 메소드는 관계를 하나만 돌려줄 것이라고 기대됩니다.
@posts = current_user.visible_posts.where(name: params[:name])
def visible_posts
case role
when 'Country Manager'
Post.where(country: country)
when 'Reviewer'
Post.published
when 'Bad User'
Post.none # => 이 경우 []나 nil을 반환하여 호출된 쪽의 코드 실행을 중지한다
end
end
Scopes require a callable object
(like Proc or lambda)
#Rails3
scope :recent, where(published_at: Time.now - 2.weeks)
#Rails 4
class Post < ActiveRecord::Base
scope :published, -> { where(published: true) }
end
Model.all
Relation 객체가 반환됨
update_columns
@team.update_columns(name: 'X-Men', universe: 'Marvel')
#first
기본키의 정렬이 포함됨
Team.first
Rails 3: SELECT "teams".* FROM "teams" LIMIT 1
Rails 4: SELECT "teams".* FROM "teams" ORDER BY "teams"."id" ASC LIMIT 1
Deprecated Finders
Scope를 사용
# find_all_by_
Rails 3: Team.find_all_by_name('Justice League')
Rails 4: Team.where(name: 'Justice League')
# find_last_by_
Rails 3: Team.find_last_by_name('Justice League')
Rails 4: Team.where(name: 'Justice League').last
# find_or_create_by_
Rails 3: Team.find_or_create_by_name('Justice League')
Rails 4: Team.where(name: 'Justice League').first_or_create
# find_or_create_by_...!
Rails 3: Team.find_or_create_by_name!('Justice League')
Rails 4: Team.where(name: 'Justice League').first_or_create!
# find_or_initialize_by_
Rails 3: Team.find_or_initialize_by_name('Justice League')
Rails 4: Team.where(name: 'Justice League').first_or_initialize
# scoped_by_
Rails 3: Team.scoped_by_name('Justice League')
Rails 4: Team.where(name: 'Justice League')
find_by and find_by!
Model.find_by는 주어진 조건에 맞는 레코드 중 첫번째를 반환합니다.
Client.find_by first_name: 'Lifo'
# => #<Client id: 1, first_name: "Lifo">
Client.find_by first_name: 'Jon'
# => nil
Client.find_by! first_name: 'Lifo'
# => #<Client id: 1, first_name: "Lifo">
Client.find_by! first_name: 'Jon'
# => ActiveRecord::RecordNotFound
Client.where(first_name: 'Lifo').first
# => #<Client id: 1, first_name: "Lifo">
#pluck ( 레일스 가이드에 문서화됨 )
published_book_titles = Book.published.select(:title).map(&:title)
published_book_titles = Book.published.map(&:title)
published_book_titles = Book.published.pluck(:title)
where.not
names = %w(John James)
# Rails 3.2
User.where("name NOT IN (?)", names) # Database-dependent
# Rails 4.0
User.where.not(name: names) # We don't need to take care of type of 'names'
References
Team.includes(:members).where('members.name = ?', 'Batman')
# Rails 3
SQL (0.7ms) SELECT "teams"."id" AS t0_r0,
"teams"."name" AS t0_r1,
"teams"."created_at" AS t0_r2,
"teams"."updated_at" AS t0_r3,
"members"."id" AS t1_r0,
"members"."name" AS t1_r1,
"members"."bio" AS t1_r2,
"members"."team_id" AS t1_r3,
"members"."created_at" AS t1_r4,
"members"."updated_at" AS t1_r5
FROM "teams" LEFT OUTER JOIN "members"
ON "members"."team_id" = "teams"."id"
WHERE (members.name = 'Batman')
# Rails 4
DEPRECATION WARNING: It looks like you are eager loading table(s)
(one of: teams, members) that are referenced in a string SQL snippet.
...
Team.includes(:members)
.where("members.name = ?", 'Batman')
.references(:members)
Default Scopes
#before
User.all
# SELECT "users".* FROM "users"
WHERE "users"."state" = 'pending'
User.active
# SELECT "users".* FROM "users"
WHERE "users"."state" = 'active'
User.where(state: 'inactive')
# SELECT "users".* FROM "users"
WHERE "users"."state" = 'inactive'
#After
User.all
# SELECT "users".* FROM "users"
WHERE "users"."state" = 'pending'
User.active
# SELECT "users".* FROM "users"
WHERE "users"."state" = 'pending'
AND "users"."state" = 'active'
User.where(state: 'inactive')
# SELECT "users".* FROM "users"
WHERE "users"."state" = 'pending'
AND "users"."state" = 'inactive'
class User < ActiveRecord::Base
default_scope { where state: 'pending' }
scope :active, -> { where state: 'active' }
scope :inactive, -> { where state: 'inactive' }
end