Hi, My work with Rails has been fairly straightforward, until yesterday... I''ve encountered rather a peculiar problem that I''m not able to solve myself as a rails-newbie. The model code looks like this: class Link < ActiveRecord::Base has_one :user_vote end class UserVote < ActiveRecord::Base belongs_to :user belongs_to :link end I have a SQL query that is responsible for pulling out all links along with votes from a database: links = Link.find_by_sql( ["SELECT * FROM links LEFT JOIN user_votes ON links.id = user_votes.link_id" + " AND user_votes.user_id = ?", session[:user_id]] ) If a user hadn''t voted for a given link yet, an empty record is returned (NULL). The problem is that when trying to call that unexisting associated object (link.user_vote) Rails attempts to retrieve it from the database. This can result in getting a vote that belongs to another user. Is it possible to disable the lazy-loading feature for that particular association? Is there any other way to perform the above-mentioned JOIN without using find_by_sql? thanks in advance, -- Piotr Chmolowski -- Posted via http://www.ruby-forum.com/.
> Is there any other way to perform the above-mentioned JOIN without using > find_by_sql?In your user model: class User < ActiveRecord::Base has_many :user_votes end Then you can say: User.find(session[:user_id]).user_votes Tom. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060513/dda4202b/attachment.html
Hi,> class User < ActiveRecord::Base > has_many :user_votes > end > > Then you can say: > > User.find(session[:user_id]).user_votesThis is not what I''m trying to achieve. I need a to pull out a list of links and check if the logged-in user has already voted for a given link. Using has_many would require n + 1 queries for n links. That''s way too much. Besides, when specyfying the has_many association I''d need to include session[:user_id] in :conditions, which is AFAIK unfeasible, as the session isn''t available in model: class Link has_many :user_votes, :conditions => ["user_id = ?", session[:user_id]] end -- Posted via http://www.ruby-forum.com/.
> This is not what I''m trying to achieve. I need a to pull out a list of > links and check if the logged-in user has already voted for a given > link. Using has_many would require n + 1 queries for n links.You can do User.find(session[:user_id], :include => :user_vote).user_votes to retrieve all the user votes in one query.> That''s way > too much. Besides, when specyfying the has_many association I''d need to > include session[:user_id] in :conditions, which is AFAIK unfeasible, as > the session isn''t available in model: > > class Link > has_many :user_votes, :conditions => ["user_id = ?", > session[:user_id]] > endYou wouldn''t need to do this. Since you''re looking for votes cast on links for a given user, just do @user.user_votes. Any links not voted on won''t have vote objects, so there won''t be any nil anywhere. This should probably do what you want: User.find(session[:user_id]).user_votes.find(:all, :include => :link) then just iterate through the list. Should only be 2 queries. -- Posted via http://www.ruby-forum.com/.
> This should probably do what you want: > > User.find(session[:user_id]).user_votes.find(:all, :include => :link) > > then just iterate through the list. Should only be 2 queries.OK, I guess I haven''t explained it clearly enough. My site is pretty similar to digg.com - I have a list of links, that everybody can vote on. Users can vote only after logging in. Only 1 vote is allowed for 1 link. The code you suggested wouldn''t be suitable here, as it would give me only the links that the user had already voted on, and I want them all :-) Basically, the SQL I''ve posted in my first message does exactly what I want, but Rails is messing up the result trying to load the vote again, which can result in getting another user''s vote. My link table looks like this: id title url description The votes table: id link_id user_id voted_at The SELECT * FROM links LEFT JOIN user_votes ON links.id user_votes.link_id AND user_votes.user_id = session[:user_id] lists all links. If the current user hadn''t voted for a given link yet, mysql returns an empty record. When iterating through that list of links I check if the user can vote for a given link: <% unless link.user_vote %> <%= link_to "vote!", :action => "vote" %> <% end %> Rather that returning nil here, Rails performs the following (or similar) SQL query: SELECT * FROM user_votes WHERE link_id = X LIMIT 1 English is still my Achilles heel, so forgive me for my grammar and the way of explaining things in general ;-) -- Posted via http://www.ruby-forum.com/.