ruby - Combining polymorphic Mongoid model scopes in the base class? -
i have simple bit of polymorphism each subclass has dead
scope, each implemented differently. able gather them dead
class method base class:
class animal include mongoid::document field :birthday, type: datetime def self.dead descendants.map(&:dead) end end class dog < animal scope :dead, ->{ where(birthday: { :$lt => time.now - 13.years }) } end class guineapig < animal scope :dead, ->{ where(birthday: { :$lt => time.now - 4.years }) } end class turtle < animal scope :dead, ->{ where(birthday: { :$lt => time.now - 50.years }) } end
as defined, animal::dead
method returns array each descendant model's scope criteria:
>> animal.dead => [#<mongoid::criteria selector: {"birthday"=>{:$lt=>2000-08-23 14:39:24 utc}} options: {} class: dog embedded: false> , #<mongoid::criteria selector: {"birthday"=>{:$lt=>2009-08-23 14:39:24 utc}} options: {} class: guineapig embedded: false> , #<mongoid::criteria selector: {"birthday"=>{:$lt=>1963-08-23 14:39:24 utc}} options: {} class: turtle embedded: false> ]
if want count dead animals, have this:
animal.dead.map(&:count).reduce(:+)
what prefer if animal::dead
method returned regular mongoid::criteria
of combined scopes (ored together) of each descendant's dead
criteria, do
animal.dead.count
any ideas how implemented?
if using datamapper, has nice feature can combine/"or" scopes using +
or |
(union operator). wasn't able determine if mongoid has such feature, if think solve issue.
here's quick rspec spec of i'm after:
describe animal.dead { should respond_to(:count, :all, :first, :destroy) } end describe animal before animal.all.destroy # create 1 dead dog, 2 dead guinea pigs, 3 dead turtles (total 6) 1.times{ dog.create(birthday: time.now - 20.years) } 2.times{ guineapig.create(birthday: time.now - 5.years) } 3.times{ turtle.create(birthday: time.now - 100.years) } # create 3 alive dogs 3.times{ dog.create(birthday: time.now - 6.years) } end 'should combine descendant animal dead scopes' expect(animal.dead.count).to eq(6) end end
i'm using rails can assume have activesupport , other helpers available.
i have temporary solution seems work:
class animal include mongoid::document field :birthday, type: datetime def self.dead self.or(*descendants.map{|d| d.dead.type(d).selector}) end end
however, seems hackish. leave question open while in case has cleaner suggestions.
Comments
Post a Comment