Happy hacking with Conditions, Count, Group, Joins, Random, Scope and Select

UPDATE: use http://github.com/grosser/random_records for random

This morning i wanted to:

  • Select records
  • Scoped
  • Random
  • Unique
  • Joined through 2 tables

The scope
Person.filmmakers

named_scope :filmmakers, :joins=>{:team_memberships=>:movie}, 
  :conditions=>{'movies.status'=>'online'}, 
  :group=>'people.id'

So we want people that participated in a movie, and add group so that there are no duplicates.

Counting
Person.filmmakers.count

Does not work! Count discards group, since cont(:group=>something) would result in [[a,number_of_records_with_a],…]
So lets add a counting that works as expected, by returning the sum of all count results(sum of the distinct values).

scope_from_above do
  def count
    super(:group=>'people.id').size
  end
end

Random
Person.filmakers.random(3)

Normally random looks like this.

#UPDATE: use http://github.com/grosser/random_records for random 
class ActiveRecord::Base
  def self.random(num=1,options={})
    return [] if num.zero?
    num_records = count
    find(:all, {:offset => [rand(num_records),num_records-num].min, 
      :limit=>num}.merge(options))
  end
end

It does not use the scope count that we defined, but the regular count, so we have to pass in count separately.
And it returns records where the id is set to Movie.count or the last movie id, very strange.

Final scope and random

named_scope :filmmakers, :joins=>{:team_memberships=>:movie}, 
  :conditions=>{'movies.status'=>'online'}, 
  :group=>'people.id' do
  def count
    super(:group=>'people.id').size
  end
    
  def random(num=1,options={})
    #select people.* or id will always be Movie.count WTF
    super(num,options.merge(:count=>count,:select=>'people.*'))
  end
end

#UPDATE: use http://github.com/grosser/random_records for random 
class ActiveRecord::Base
  def self.random(num=1,options={})
    return [] if num.zero?
    num_records = count
    find(:all, {:offset => [rand(num_records),num_records-num].min, 
      :limit=>num}.merge(options))
  end
end

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s