#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’. Я думал, что это неявно, но я думаю, что нет.