How to query across a nested resource with a condition - ruby-on-rails

I have the following models:
User (id)
UserRoom (user_id, room_id, banned(boolean)
Room (id, uuid)
Right now I can get all of a user's rooms as follows:
current_user.rooms.find_all_by_uuid(#requested_ids)
What I would like to do is expand this to only show rooms that aren't banned (banned => false).
What's the right rails way to add that condition to the query?
Thanks

Try using conditions like so:
current_user.rooms.find :all, :conditions => { :uuid => #requested_id, :banned => false }
Using #requested_ids as an array (probably not as elegant):
current_user.rooms.find :all, :conditions => ["uuid IN (?) AND banned=0", #requested_ids]

Related

Rails How to use join in this specific situation?

I have three models, each connected as such: Groups which has many Students which has many Absences.
Absences has a field called created_on.
I only have a group id and would like to obtain all students with an absence of today.
I have created this method inside my Student model:
# Inside student.rb
def self.absent_today_in_group (group)
#SQLITE
find(:all, :joins => :absences, :conditions => ["STRFTIME('%d', created_on) = ? AND STRFTIME('%m', created_on) = ?", Date.today.day, Date.today.month])
#POSTGRES
#find(:all, :joins => :absences, :conditions => ["EXTRACT(DAY FROM created_on) = ? AND EXTRACT(MONTH FROM created_on) = ?", Date.today.day, Date.today.month])
end
Why would that query not return anything? And how could I then also check for group_id?
What version of rails are you using? You can do this in rails 3:
def self.absent_today_in_group(group)
joins(:absences, :group).where(
'absences.created_on' => (Time.now.beginning_of_day..Time.now.end_of_day),
'groups.id' => group.id
)
end
That would find all users which were absent for today for given group.
Shouldnt this be :where and not :conditions?

Rails find at least one "order" with status "completed"

Not the best with Rails so this might be very simple.
I have a database with tables Groups and Orders - groups has_many orders, orders belongs_to groups. Orders have a string field called status, which can be in progress, canceled, completed. An order is considered "not in progress" when it is either canceled or completed.
I would like to be able to find all groups with no orders in progress and at least one order completed. So far I have the none in progress:
groups = Group.find(:all, :include => :orders, :conditions => ["orders.status != :in_progress", { :in_progress => Constant::IN_PROGRESS }])
Is there a way to find groups with at least one order completed (without simply iterating over this array and picking them out)?
Edit: Rails version 2.1.0 Sorry for the oversight!
If you put this into one find condition it's going to be really complicated and you will probably want to add more filters later so might want to break it into to finds.
#groups = []
groups = Group.find(:all, :joins => :orders, :conditions =>])
no_orders_in_progress = Group.find(:all, :jois => 'order', :conditions => ['status!=', 'in progress'], :limit => 5)
orders_completed = Group.find(:all, :joins => 'order', :conditions => ['status=?', 'completed'], :limit => 1)
#groups << orders_completed + no_orders_in_progress
Make sure to limit it however many you want.

Date condition in default_scope for a Model

I want to ensure that only Movies with a watched date are brought back and ordered by that value in ascending order.
I think I'm fairly close with the following:
default_scope :conditions => { :watched_date => not null },
:order => 'watched_date ASC'
But I don't know how to add a condition for a non-null date.
Does it work if you change the conditions to this?:
:conditions => 'watched_date IS NOT NULL'
You might want to include the table name incase this is used in joins like so:
:conditions => 'movies.watched_date IS NOT NULL'

Rails 2 :joins and :include resultset

When fetching content from a database using activerecord, I would like to fetch a custom resultset with specified columns across two tables.
SELECT users.name, users.username, users.age, users.city_id, cities.name as city_name FROM users INNER JOIN cities ON users.city_id = cities.id
Which would be in AR as
Users.find(:all,
:joins => :cities,
:select => "users.name, users.username, users.age, users.city_id,
cities.name as city_name")
But this only returns the user table results and not the city results. I am 100% sure that the inner join statement is going through (that both tables are being joined).
It seems as if the return object only has the columns associated with the model. So UserModel would only have the columns that the users table has and won't allow to fetch the columns of the cities table even though they're specified in the select.
Should I be using :joins or :include? Any idea what's going on?
If you alias the joined column name then returned object should have an attribute by the alias name, i.e.
u = User.first( :joins => :cities,
:select => "users.*, cities.name AS city_name")
u.city_name # returns the city_name.
In your case, :joins is appropriate than :include.
I checked this in my setup and it works for me ( I am on Rails 2.3.8)
In your returned instances, if the column's name is city_name, you should be using user.city_name. Alternatively, if you use :include, you would be telling ActiveRecord to load the associated city models, which you would then reference as user.city.name.
To summarize:
users = User.find(:all, :joins => :cities, :select => "users.name, users.username, users.age, users.city_id, cities.name as city_name")
users.map(&:city_name)
users = User.find(:all, :include => :cities)
users.map(&:city).map(&:name)
you can use specific column name in user table in place of "users.*" if you dont need all column. I think its good programming practice.
u = User.first( :joins => :cities,
:select => "users.name, users.username, users.age, users.city_id, cities.name AS city_name")
u.city_name # returns the city_name.

Activerecord: Finding non associated plus associated records with a single query

Given the following scenario, using activerecord:
User belongs_to Event
I want to find all the Users who do not have an Event with the name "party".
So I tried the following:
User.all(:joins => :event, :conditions => ["events.name != ?", "party"])
However, that will only return those Users who do have an event, but just not a "party" event. It won't return all the Users who have no event at all, because :joins automatically limits the results to associated records only.
I could do two queries and add the results together, but is there a way, in one query to fetch the non-associated records, plus the associated records that match the condition?
How about this?
User.all(
:include => :event,
:conditions => ["users.event_id IS NULL OR events.name != ?", "party"])

Resources