6. active users
class User < ActiveRecord::Base
named_scope :active,
:condition=>["deleted = ?", false]
end
describe “activeなユーザ” do
it “は全員削除されて*いない*こと” do
User.active.should be_all{|u| not u.deleted }
end
end
7. active users
(with guideline)
class User < ActiveRecord::Base
named_scope(:active,
{:condition=>["deleted = ?", false]})
end
describe “activeなユーザ” do
it “は全員削除されて*いない*こと” do
User.active.should be_all{|u| not u.deleted }
end
end
8. hot n users
use scope with args
class User < ActiveRecord::Base
named_scope :active,
:condition=>["deleted = ?", false]
named_scope :hot,
Proc.new{|arg|
{:order =>"#{table_name}.popularity DESC",
:limit => arg}
}
end
9. describe “人気トップ3のユーザ” do
before do
@users = User.hot(3)
end
it "のうちトップはdahliaであること" do
@users.first.should == users(:dahlia)
end
end
hot n users
use scope with args
10. hot active users
crossover 2 scopes
describe "BAN! dahlia" do
before(:each) do
users(:dahlia).update_attribute(:deleted, true)
end
it "アクティブユーザで最も人気なのはcharlesであること" do
User.hot(3).active.first.should == users(:charles)
end
it "クエリ発行(select_all)は一回だけ呼ばれること" do
User.connection.should_receive(:select_all).once.and_return([])
User.hot(3).active.find(:all)
end
end
11. update using scope
class User < ActiveRecord::Base
named_scope :active,
:conditions=>["#{table_name}.deleted = ?", false] do
def ban
self.update_all(:deleted => true)
end
end
named_scope :hot,
Proc.new{|arg|
{:order =>"#{table_name}.popularity DESC",
:limit => arg}
}
end
12. update using scope
describe “User.active.ban” do
it "activeユーザ全員がBANされること" do
User.active.ban
User.should have(0).active
end
it "UPDATE文は一度だけ発行されること" do
User.connection.should_receive(:update).once
User.active.ban
end
end
16. AR::Base.named_scope
def named_scope(name, options = {}, &block)
scopes[name] = lambda do |parent_scope, *args|
Scope.new(parent_scope, case options
when Hash
options
when Proc
options.call(*args)
end, &block)
end
(class << self; self end).instance_eval do
define_method name do |*args|
scopes[name].call(self, *args)
end
end
end
20. Scope#method_missing
def method_missing(method, *args, &block)
if scopes.include?(method)
scopes[method].call(self, *args)
else
with_scope :find => proxy_options do
proxy_scope.send(method, *args, &block)
end
end
end