Записи, не отображаемые в базе данных

#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, чтобы убедиться, что вы всегда будете перезагружать массив, если это нежелательно, просто переключите его обратно.