#ruby-on-rails #ruby #ruby-on-rails-3
#ruby-on-rails #ruby #ruby-on-rails-3
Вопрос:
Мы начинаем операцию, убедившись, что у клиента достаточно элементов для работы. Итак, мы начинаем со сбора всех их текущих элементов в массив:
@items = SOrder.where(:user_id => current_user.id).order("order")
Затем мы определяем, сколько элементов у них должно быть. Если у кого-то есть бесплатная учетная запись, у него должно быть 5 элементов. Если это платная учетная запись, в ней должно быть 20 элементов:
if current_user.paid
should_have = 19 # one less than 20 because of 0 position in the array
else
should_have = 4
end
Затем, если нам нужно добавить пустые записи, мы выясняем, с чего нам следует начать:
if @items.empty?
start = 0
else
start = @items.length 1
end
Если начальное значение меньше или равно тому, которое у кого-то должно быть, тогда мы добавляем пустые записи:
if start <= should_have
value = [start .. should_have].each do |v|
SOrder.create(:user_id => current_user.id, :order => v, :item_id => 0 )
end
@items = SOrder.where(:user_id => current_user.id).order("order") # reload array
end
Записи, которые должны быть добавлены, не отображаются в базе данных.
Где ошибка?
Ответ №1:
Попробуйте
value = (start .. should_have).each do |v|
вместо
value = [start .. should_have].each do |v|
[start .. should_have]
просто вернет массив с единственным элементом range в нем. (start .. should_have)
вернет диапазон, с которым each
перечислитель будет работать так, как вы ожидаете.
Комментарии:
1. @Jay, это хорошее место для использования ruby-debug . Это быстро окупит время, затраченное на его изучение. Вы можете пошагово просмотреть свой код и проверить, соответствуют ли значения переменных ожидаемым по ходу работы.
2. Если вы хотите быстро выполнить отладку, попробуйте просто добавить переменные, которые вы хотите проверить, в свой шаблон.
<%= start %>
и т. Д
Ответ №2:
Ошибка может возникнуть при вызове .length
из объекта Arel, а не из набора записей.
@items = SOrder.where(:user_id => current_user.id).order("order").all
Однако, поскольку вам нужно количество только для первого запроса, я бы предложил использовать .count
. Если бы я писал это, я бы сделал что-то вроде:
number_of_items = SOrder.where(:user_id => current_user.id).count
number_of_blank_items_to_add = current_user.allowed_items - number_of_items
if number_of_blank_items_to_add > 0
number_of_blank_items_to_add.times do |num|
SOrder.create(:user_id => current_user.id, :order => (number_of_items num), :item_id => 0 )
end
end
@str_order = SOrder.where(:user_id => current_user.id).order("order")
В пользовательской модели:
def allowed_items
if paid
20
else
5
end
end
Еще лучше
В пользовательской модели:
has_many :s_orders, :order => "s_orders.order asc"
def add_extra_blank_orders
number_of_items = s_orders.count
number_of_blank_items_to_add = allowed_items - number_of_items
if number_of_blank_items_to_add > 0
number_of_blank_items_to_add.times do |num|
s_orders.create(:order => (number_of_items num), :item_id => 0 )
end
end
def allowed_items
if paid
20
else
5
end
end
В контроллере:
current_user.add_extra_blank_orders
@str_order = current_user.s_orders
Хотя я уверен, что у вас есть веская причина, я задаюсь вопросом, почему пустые элементы вообще должны быть в базе данных. И, если бы здесь можно было использовать перехват after_create.
Комментарии:
1. Спасибо. обычно я заставляю все работать в контроллере, а затем перемещаю фрагменты в модель позже. Не знаю почему… думаю, это просто плохая привычка. :=]
Ответ №3:
Попробуйте этот код, чтобы убедиться, что ваш код входит в цикл создания записей, добавив puts "entered the loop"
внутри цикла следующим образом:
if start <= should_have
(start .. should_have).each do |v|
puts "entered loop"
SOrder.create(:user_id => current_user.id, :order => v, :item_id => 0 )
end
@items = SOrder.where(:user_id => current_user.id).order("order") # reload array
end
Если выводится «введенный цикл», попробуйте .create!
убедиться, что все проверки пройдены (если какая-либо из них не удалась, будет выдана ошибка ActiveRecord с указанием проверки)
if start <= should_have
(start .. should_have).each do |order|
SOrder.create!(:user_id => current_user.id, :order => order, :item_id => 0 )
end
@str_order = SOrder.where(:user_id => current_user.id).order("order") # reload array
end
Комментарии:
1. Согласен с @rubyprince здесь,
.create!
может пролить некоторый свет на любые возникающие у вас сбои.
Ответ №4:
Я не вижу, что вы используете value
, и не уверен, зачем вы это используете.
Можете ли вы использовать это?:
if start <= should_have
(start .. should_have).each do |order|
SOrder.create(:user_id => current_user.id, :order => order, :item_id => 0 )
end
end
@str_order = SOrder.where(:user_id => current_user.id).order("order") # reload
Редактировать: я переместил @str_order за пределы вашего оператора if, чтобы убедиться, что вы всегда будете перезагружать массив, если это нежелательно, просто переключите его обратно.