user2784630
user2784630

Reputation: 806

How can query the same model twice with different conditions?

I have a Kid model that belongs to a Mom and a Dad.

class Kid
  belongs_to :mom
  belongs_to :dad 
end

class Mom
  has_many :kids
  has_many :dads, through: :kids
end

class Dad
  has_many :kids
  has_many :moms, through: :kids
end

Now what I'm doing is listing a Dad's kids based on when it was created, age and distance from the Mom.

def show
  @dad = Dad.find(params[:id])
    near = Mom.near(@user_location, 100, :select => "kids.*") # Geocoder gem
  @kids = @dad.kids.joins(:mom).merge(near).order(age: :asc, created_at: :desc).page(params[:page])
end

I have a boolean field on the Mom model called is_online. I want this field to make it so results won't be based on the near method or distance and the the online moms will be in front. So, the results of the pagination would look like:

online kid, 2 years old
online kid, 3 years old
offline kid, 4 years old, 4 miles away
offline kid, 5 years old, 5 miles away

My problem is, I don't know how to make my Kid be just one scope so I don't have to make @online_kids and @offline_kids. I just want to keep it as @kids. Any suggestions?

Upvotes: 0

Views: 154

Answers (2)

Marek Lipka
Marek Lipka

Reputation: 51151

So you have to use order clause, I guess:

@kids = @dad.kids.joins(:mom).merge(mom).order('moms.is_online DESC, kids.age ASC, kids.created_at DESC').page(params[:page])

You build your Mom query this way, basing on other answer:

near = Mom.near(@user_location, 100, :select => "kids.*").where(is_online: false).where_values.reduce(:and)
online = Mom.where(is_online: true).where_values.reduce(:and)
mom = Mom.where(near.or(online))

Upvotes: 2

Saurabh
Saurabh

Reputation: 73589

You can create different scope for online and offline, like this:

class Kid
  belongs_to :mom
  belongs_to :dad 

 scope :online,  lambda { where(:is_online => true) }
 scope :offline, lambda { where(:is_online => false) }
end

Now, You can further filter search results by these scope.

For example

 kids = Kid.where(:age > 2)
 kids.online   # these will be online  kids
 kids.offline  # these will be offline kids

Upvotes: 0

Related Questions