ActiveRecord find with include - ruby-on-rails-3

Let's say that Person has_many Addresses, and with this query I can go through the loop and use addresses for that peoples.
#people = Person.find(:all, :include => :addresses)
But, I want to include ONLY addresses where the user_id = 1 for example.
How to build query to do that?
P.S. New to RoR

#people = Person.find(:all, :include => :addresses, :conditions => ['user_id=?',params[:user_id]])
Make note that when you include you can only have one column of each or rails will give you an error about ambiguous find conditions.

Related

Rails - Delete rows from a non indexed table

I have a connection table that connects between 2 tables. It has 2 columns: user_id and course_id. The name of the table is: course_sub_managers. This table does not have an index. So, how do I delete all rows that meet a condition in which course_id = certain variable? As for now I use:
sql = "DELETE FROM course_sub_managers WHERE course_id = " + #course.id.to_s
ActiveRecord::Base.connection.execute(sql)
Is there a Rails way to write it?
I suspect you have an course model where you have written something like:
has_many :course_sub_managers
has_many :users, through => :course_sub_managers
in that case you can use:
#course.course_sub_managers.delete_all
It sounds you just want to handle the deletion of a course? Use the :dependent => :destroy on your relationships.
has_many :course_sub_managers, :dependent => :destroy
It will automatically remove the related table items when you destroy a course.

Counting Child Rows As a Condition in a Query

I have a table of Groups that have a "capacity" column and has a has_many relationship with Enrollments. I want to be able to find Groups whose count of enrollments is less than it's capacity, so using ActiveRecord + Ruby I can do this:
Group.all.select {|g| g.enrollments.count < g.capacity }.first
But it seems like there should be a way to do this in SQL, I just don't know how. Any ideas?
The pure SQL way of doing this would be
select groups.* from groups
inner join enrollments on enrollments.group_id = groups.id
group by groups.id
having count(*) < capacity
Or in activerecord
Group.joins(:enrollments).group('groups.id').having('count(*) < capacity)
A counter cache with an index on the counter column will be faster though, although obviously you have to not create enrollments behind acriverecord's back.
May use :counter_cache option.
Add a enrollments_count column to the Groups table
column :groups, :enrollments_count, :integer, :default => 0
set Enrollment's :counter_cache option
class Enrollment < ActiveRecord::Base
belongs_to :group, :counter_cache => true
end
Group.where("capacity > enrollments_count").first

How to do this sql with pure activerecord (rails)

I can't figure out how to manage this purely with active record. I understand it doesn't handle outer joins...
SQL:
SELECT * FROM people
LEFT OUTER JOIN responses
ON people.id = responses.person_id
WHERE responses.person_id is NULL;
MODELS:
Person
id
has_many :responses
Response
id
belongs_to :person
Any suggestions?
named_scope :without_responses, :include => :responses,
:conditions => "responses.id IS NULL"

Is it possible to define a single SQL query that draws a set of permissible foreign_keys from one table and then uses them to filter another?

Specifically, I'm trying to figure out if it's possible to generate SQL that does what I want to feed into Ruby-on-Rails' find_by_sql method.
Imagine there are Users, who are joined cyclically to other Users by a join table Friendships. Each User has the ability to create Comments.
I'd like a SQL query to return the latest 100 comments created by any friends of a given user so I can display them all in one convenient place for the user to see.
This is tricky, since essentially I'm looking to filter the comments by whether their foreign keys for their author are contained in a set of keys obtained derived from the user's friends' primary keys.
Edit: Clarifying the setup. I'm not exactly sure how to write a schema definition, so I'll describe it in terms of Rails.
class User
has_many :friends, :through => :friendships
has_many :comments
end
class Friendship
belongs_to :user
belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
end
def Comment
has_one :User
end
It's not that tricky, you just use joins. To get just the comments you only need to join the Friendships table and the Comments table, but you probably also want some information from the Users table for the person who wrote the comment.
This would get the last 100 comments from people who are friends with the user with id 42:
select top 100 c.CommentId, c.CommentText, c.PostDate, u.Name
from Friendships f
inner join Users u on u.UserId = f.FriendUserId
inner join Comments c on c.UserId = u.UserId
where f.UserId = 42
order by c.PostDate desc

Find records with more than one ActiveRecord HABTM Association

I've got two models, joined by a Has and Belongs To Many join table. Lets call these models User and Event. The majority of Users have 0 events, while few have one or more. I want to do something like:
User.find(:all, :joins => :events, :conditions => ["'Something that count the events' > ?"], 0)
The problem is, I'm not sure how to select only users that have 1 or more associated events.
I've found the answer:
User.find(:all, :joins => :events, :select => 'DISTINCT `users`.*')
Basically, the users.* restricts the result set to just the users table, and the DISTINCT keyword makes sure each user is only returned once.