#ruby-on-rails #ruby #view #controller
#ruby-on-rails #рубин #Вид #контроллер #ruby
Вопрос:
На мой взгляд, у меня есть этот код
<% @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
и когда я запускаю его, код генерирует страницу, выглядящую следующим образом:
«Ваше имя пользователя — это элемент Item Item»
вместо
«Ваше имя пользователя — Digital Fortress Oceans Eleven Settlers»
Комментарии:
1. В вашем / console, когда вы запускаете код вашего контроллера, какой массив возвращается? Также вы не могли бы сделать
@categories = Category.find(:all, :conditions => ["user_id = ?", session[:user_id]])
Ответ №1:
То, чего вы пытаетесь достичь, может быть сделано следующим образом:
Item.where(:categorys_id => c.id ).сначала
Item.where
возвращает область видимости, на самом деле она не создает и не запускает запрос.
Методы first
и last
выполнят запрос с помощью LIMIT
и ORDER BY
и вернут элемент.
Такие методы, как each
и all
, создают и запускают запрос и возвращают массив результатов.
Обзор кода
Код вашего контроллера подвержен SQL-инъекции, представьте, что в нем было что-то злое session[:user_id]
. "#{stuff}"
не выполняет никакого экранирования stuff
в Ruby.
Чтобы избавиться от проблемы с внедрением:
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(amp;:id)) #
Комментарии:
1. Это просто дает мне нулевой объект. У меня есть таблица Users, которая имеет много типов, в которой много элементов. Я хочу показать все элементы всех типов, которыми владеет текущий пользователь.
Ответ №2:
Я бы переписал код вашего контроллера следующим образом:
@categories = Category.find_all_by_user_id(session[:user_id], :include => :items)
@items = @categories.map(amp;:items).flatten
Теперь, на ваш взгляд:
<% @items.each do |item| %>
<tr>
<td><%= item.name %></td>
</tr>
<%end%>
Ответ №3:
Item.where(:categorys_id => c.id)
даст вам объект ActiveRecord, а не отдельные атрибуты. Итак, когда вы перебираете их, i
это Item
объект, а не атрибут.
Допустим, вы действительно хотели вывести name
поле элемента, тогда вы бы сделали это:
<% @items.each do |i| %>
<tr>
<td><%= i.name %></td>
</tr>
<%end%>
Комментарии:
1. Это то, что я уже сделал (я пропустил .name, копируя его, и сейчас отредактировал его)
2. Не будет
Item.where
возвращать массив, когда аргумент является хэшем? Что означало бы@items <<
добавление массива, а не элемента