Why is ruby returning array type instead of attribute
I have this code in my view
<% @items.each do |i| %>
<tr>
<td><%= i.name %></td>
</tr>
<%end%>
and this code in my controller
@categories = Category开发者_JAVA技巧.find_by_sql("SELECT * FROM categories WHERE users_id =#{session[:user_id]}")
@categories.each do |c|
@items << (Item.where(:categorys_id => c.id))
end
and when I run it, the code generates a page looking like this: "Your username is a Item Item Item" instead of "Your username is a Digital Fortress Oceans Eleven Settlers"
What you are trying to achieve can be done like this:
Item.where(:categorys_id => c.id).first
Item.where
returns a scope, it doesn't actually construct or run the query.
Methods first
and last
will run the query with LIMIT
and ORDER BY
and will return the element.
Methods like each
and all
construct and run the query and return the array of results.
Code review
Your controller code is prone to SQL injection, image if something evil was in session[:user_id]
. "#{stuff}"
does not do any escaping of stuff
in Ruby.
To get rid of the injection problem:
ruby
@categories = Category.where(:users_id => session[:user_id]) # Are you sure the column is not user_id but users_id?
The second thing we should do is to avoid doing N + 1 query where N is the number of resulting categories.
An OK way to do this is by using the SQL IN
operator.
ruby
@items = Item.where(:categorys_id => @categories.map(&:id)) #
I would rewrite your controller code as follows:
@categories = Category.find_all_by_user_id(session[:user_id], :include => :items)
@items = @categories.map(&:items).flatten
Now in your view:
<% @items.each do |item| %>
<tr>
<td><%= item.name %></td>
</tr>
<%end%>
Item.where(:categorys_id => c.id)
will give you an ActiveRecord object, not an individual attributes. So when you iterate over these, i
is an Item
object, not an attribute.
Let's say you really wanted to output the item's name
field, then you would do this:
<% @items.each do |i| %>
<tr>
<td><%= i.name %></td>
</tr>
<%end%>
精彩评论