Вложенный ресурс загружен не по порядку

#ruby-on-rails

#ruby-on-rails

Вопрос:

У меня есть класс tutorial и класс step. Учебное пособие состоит из множества шагов, и каждый шаг принадлежит учебному пособию. У меня есть эта настройка в моих моделях и в файле маршрутов. В действии show класса tutorial также загружаются все шаги, относящиеся к этому руководству. Проблема в том, что после создания нескольких шагов, 4-6, они выйдут из строя. Например, первым загруженным шагом является шаг 7, но после этого шаги выполняются по порядку. Я использую postgresql для базы данных и включаю драгоценный камень pg в свой gemfile. Учебная модель:

 class Tutorial < ActiveRecord::Base
  attr_accessible :name, :summary, :permalink   
  has_many :steps

  validates :name, :presence => true,
               :length => { :maximum => 50 },
               :uniqueness => { :case_sensitive => false }  

  validates :summary, :presence => true,
          :length => { :maximum => 2000 }

  before_create :set_up_permalink

  def to_param
permalink
  end

  private

  def set_up_permalink
    permalink = self.name.gsub(' ', '-').gsub(/[^a-zA-Z0-9_-.]/, '')
  self.permalink = permalink
end
  

Пошаговая модель:

 class Step < ActiveRecord::Base
  attr_accessible :tutorial_id, :body, :position
  belongs_to :tutorial

  validates :body, :presence => true

  before_create :assign_position

  private

  def assign_position
@tutorial = self.tutorial
@position = @tutorial.steps.size
    @position = @position   1
    self.position = @position
  end
end
  

Маршруты:

 resources :tutorials do
  resources :steps
end

def show
  @tutorial = Tutorial.find_by_permalink(params[:id])
  @steps = @tutorial.steps
  @next = @steps[0]
  @title = "#{@tutorial.name} - A Ruby on Rails tutorial"
  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => @tutorial }
  end
end
  

Просмотр обучающего шоу

 <%= render :partial => @tutorial.steps %>
  

Ответ №1:

Где вы устанавливаете порядок? Вы могли бы сделать это так:

 @steps = @tutorial.steps.order('position')
  

Или даже лучше, поскольку я не могу вспомнить ни одного случая, когда вы хотели бы, чтобы шаги были не по порядку:

В вашей пошаговой модели:

 default_scope order('position')
  

Кроме того, вы можете определить порядок в определении ассоциации:

В вашей обучающей модели:

 has_many :steps, :order => 'position'
  

редактировать и, черт возьми, вот гораздо более краткий способ написания вашего assign_position метода:

   def assign_position
    self.position = tutorial.steps.size   1
  end
  

Комментарии:

1. Спасибо, человек — переделка метода assign_position была в моем списке дел.

Ответ №2:

Ваша логика назначения позиции ошибочна, если шаги могут быть произвольно добавлены и удалены.

Например.

  • Я создаю учебное пособие и 3 шага с позициями [1,2,3].
  • Затем я удаляю шаг с позиции 2.
  • Теперь осталось 2 шага с позициями [1,3].
  • Позже я создаю еще один шаг, которому присваивается позиция 3.
  • Теперь есть три ступени, но их позиции таковы [1,3,3]. Это неправильно!

Есть пара подходов, которые я бы рассмотрел, чтобы исправить ситуацию:

Первый способ

Вы можете сохранить свой код для назначения позиции новому шагу, но когда шаг удаляется из руководства, обновите позиции, чтобы убедиться, что они последовательны. Вот набросок того, как это будет работать.

 class Tutorial
  def rectify_step_positions
    # reassign positions so that all the steps form a sequence
    # E.g. step positions [1,3,4] become [1,2,3]
  end
end

class Step
  after_destroy :trigger_rectify_positions

  def trigger_rectify_positions
    tutorial.rectify_step_positions
  end
end
  

Второй способ

Когда вы создаете новый шаг, вы можете назначить его положение на 1 больше максимального положения среди всех существующих шагов.

 def assign_position
  self.position = tutorial.steps.order("position DESC").first.position   1
end
  

Этот метод немного проще в реализации, чем первый. Конечно, теперь позиции не имеют такого большого значения, поскольку они не обязательно последовательны. Шаг с позицией 10 может быть 2-м шагом руководства.

Заключение

Как только вы исправите проблему с позицией, вы можете просто упорядочить шаги. Брикер показал несколько способов сделать это. Лично мне нравится has_many :steps, :order => 'position'

Комментарии:

1. Большое спасибо. Я бы проголосовал за ваш ответ, но моя репутация недостаточно высока.

2. Что это сделало, было has_many :steps, :order => ‘id’. Я думал, что это неявно, но я думаю, что нет.