为什么ruby返回数组类型而不是属性

时间:2011-05-13 00:51:05

标签: ruby-on-rails ruby view controller

我在视图中有这段代码

<% @items.each do |i| %>
  <tr>
    <td><%= i.name %></td>
  </tr>
<%end%>

和我控制器中的代码

  @categories = Category.find_by_sql("SELECT * FROM categories WHERE users_id =#{session[:user_id]}")
  @categories.each do |c|
    @items << (Item.where(:categorys_id => c.id))
  end

当我运行它时,代码生成一个如下所示的页面: “您的用户名是项目项目项” 代替 “您的用户名是Digital Fortress Oceans Eleven Settlers”

3 个答案:

答案 0 :(得分:2)

你想要实现的目标可以这样做:

  

Item.where(:categorys_id =&gt; c.id)。 first

Item.where返回一个范围,它实际上并不构造或运行查询。

方法firstlast将使用LIMITORDER BY运行查询并返回元素。

eachall之类的方法构造并运行查询并返回结果数组。

代码审核

您的控制器代码很容易进行SQL注入,如果session[:user_id]中存在邪恶,则会显示图像。 "#{stuff}"不会在Ruby中对stuff进行任何转义。

摆脱注射问题:

ruby @categories = Category.where(:users_id => session[:user_id]) # Are you sure the column is not user_id but users_id?

我们应该做的第二件事是避免进行N + 1查询,其中N是结果类别的数量。

执行此操作的正常方法是使用SQL IN运算符。 ruby @items = Item.where(:categorys_id => @categories.map(&:id)) #

答案 1 :(得分:1)

我会按如下方式重写您的控制器代码:

@categories = Category.find_all_by_user_id(session[:user_id], :include => :items)
@items      = @categories.map(&:items).flatten

现在在你看来:

<% @items.each do |item| %>
  <tr>
    <td><%= item.name %></td>
  </tr>
<%end%>

答案 2 :(得分:0)

Item.where(:categorys_id => c.id)将为您提供ActiveRecord对象,而不是单个属性。因此,当您迭代这些时,iItem对象,而不是属性。

假设你真的想要输出项目的name字段,那么你会这样做:

<% @items.each do |i| %>
  <tr>
    <td><%= i.name %></td>
  </tr>
<%end%>