Hello Chris,

I've checked. There was one little thing the act as votable couldn't do; I
can't remember exactly what, maybe the negative votes or something like
that. So I did my own.

But what I'm really after is improving the so many strings.

On Mon, Nov 9, 2009 at 04:36, Chris Drappier <[email protected]>wrote:

> check out the acts as voteable plugin on github, looks like you've already
> got your modeling done correctly to just drop it in.
>
> -C
> 2009/11/8 J. Pablo Fernández <[email protected]>
>
> Hello Railists,
>>
>> I have a piece of Ruby on Rails code that has a complex SQL query (well,
>> not that complex, but as far as I know beyond the ORM capabilities) and for
>> my taste it has too many strings and harcoded values. I'd like to improve it
>> as much as possible, so my question is open ended, what else can I do to
>> improve it?
>>
>> Some particular issues I have
>>
>> - Is there a way to get a table name to use it in a query in the same
>> escaped way as the ORM does? I think this is database independent,
>> being `items` for MySQL but not for other databases.
>> - In the same vein, is there a way to get a field name the same way Rail's
>> ORM would put it in a SQL query?
>> - Maybe there's a way to get both, the table name and the field name in
>> one operation. I'm imaging something like Item.voteable_id.for_query
>> => "`items`.`voteable`".
>> - How do I escape code to avoid SQL injection when not in conditions? I'm
>> using the user_id variable directly in a query and although it's impossible
>> for a user to put anything in it, I'd rather escape it properly. In a
>> condition I would do ['user_id = ?', user_id], but in a join or a select,
>> how do I do it?
>> - Does my use of class constants here make sense?
>> - Is there any chance at all of using the ORM and less string?
>> - Any other thing to do to it?
>>
>> The code is this one
>>
>> class Item < ActiveRecord::Base
>>   has_many :votes, :as => :voteable
>>
>>   def self.ranking(user_id)
>>     Item.find(:all,
>>       # items.* for all the Item attributes, score being the sum of votes,
>> user_vote is the vote of user_id (0 if no vote) and voter_id is just user_id
>> for latter reference.
>>       :select => "items.*,
>>                   IFNULL(sum(all_votes.value), 0) as score,
>>                   user_votes.value as user_vote,
>>                   \"#{user_id}\" as voter_id",
>>       # The first join gets all the votes for a single item (to be summed
>> latter).
>>       # The second join gets the vote for a single user for a single item.
>>       :joins => ["LEFT JOIN votes as all_votes ON
>>                     all_votes.voteable_id = items.id and
>>                     all_votes.voteable_type = \"Item\"",
>>                  "LEFT JOIN votes as user_votes ON
>>                     user_votes.voteable_id = items.id and
>>                     user_votes.user_id = \"#{user_id}\" and
>>                     user_votes.voteable_type = \"Item\""
>>                 ],
>>       :group => :id,
>>       :order => "score DESC")
>>
>>     # This is the query it should generate
>>     # SELECT items.*, user_votes.value as user_vote, sum(all_votes.value)
>> as score
>>     # FROM items
>>     # LEFT JOIN votes as all_votes ON
>>     #     all_votes.voteable_id = items.id and
>>     #     all_votes.voteable_type = "Item"
>>     # LEFT JOIN votes as user_votes ON
>>     #     user_votes.voteable_id = items.id and
>>     #     user_votes.user_id = 2 and
>>     #     user_votes.voteable_type = "Item"
>>     # GROUP BY items.id
>>     # ORDER BY score DESC
>>   end
>>
>>   def score
>>     s = read_attribute("score")
>>     if s == nil
>>       votes.sum :value
>>     else
>>       Integer(s)
>>     end
>>   end
>>
>>   def user_vote(user_id)
>>     if Integer(read_attribute("voter_id")) == user_id
>>       Integer(read_attribute("user_vote"))
>>     else
>>       vote = votes.find(:first, :conditions => ["user_id = ?", user_id])
>>       if vote
>>         vote.value
>>       else
>>         0
>>       end
>>     end
>>   end
>> end
>>
>> Thanks.
>> --
>> J. Pablo Fernández <[email protected]> (http://pupeno.com)
>>
>>
>>
>
> >
>


-- 
J. Pablo Fernández <[email protected]> (http://pupeno.com)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to