Лучшая практика Rails: условное действие, множественные действия или метод? - PullRequest
0 голосов
/ 06 марта 2011

Мне любопытно получить информацию о фрагменте кода, над которым я недавно работал.

У меня есть модель, photos, которая иногда (но не всегда) принадлежит к collection. У меня есть страница, на которой пользователи могут управлять коллекцией, они могут добавлять любые неназначенные фотографии в коллекцию или удалять фотографии из коллекции.

Это ситуация «редактирования нескольких», поэтому я создал два новых действия контроллера: select, который обрабатывает запрос GET и представление, и assign, который обрабатывает запрос PUT из флажков в представлении выбора.

Поскольку пользователь может добавлять фотографии в коллекцию или удалять фотографии из коллекции, мое действие assign содержит условие, и оно выглядит следующим образом:

def assign
    @photos = Photo.find(params[:photo_ids])
    case params[:assignment]
    when 'add'
        @photos.each do |p|
            p.collection = @collection
            p.save!
        end
        notice = "Photos added to collection."
    when 'remove'
        @photos.each do |p|
            p.collection = nil
            p.save!
        end
        notice = "Photos removed from collection."
    end
    redirect_to select_collection_photos_path(@collection), :notice => notice
end

Это работает точно так, как ожидалось. Тем не менее, я чувствую себя неловко с этим, это не похоже на «путь рельсов».

Другие разработчики Rails, когда у вас возникнет такая ситуация, вы бы справились с этим, как я? Вы бы поделили это на два действия контроллера (то есть add_to_collection и remove_from_collection) или перенесли бы это в модель? Если бы вы переместили его в модель, как бы это выглядело?

Буду признателен за любые предложения и отзывы. Спасибо!

Ответы [ 2 ]

2 голосов
/ 06 марта 2011

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

Я бы, вероятно, сделал что-то вроде этого в вашем контроллере:

def assign
  Photo.update_collection(params, @collection)

  redirect_to select_collection_photos_path(@collection), :notice => "Photo collection updated"
end

Затем в вашей фотомодели:

class Photo < ActiveRecord::Base
  def self.update_collection(params, collection)

    photos = Photo.find(params[:photo_ids])

    case params[:assignment]
    when 'add'
      photos.each {|p| p.add_collection(collection) }
    when 'remove'
      photos.each {|p| p.remove_collection }
    end
  end

  def add_collection(collection)
    self.collection = collection
    save!        
  end

  def remove_collection
    self.collection = nil
    save!
  end
end

Разбиение функциональности на методы меньшей моделиоблегчает юнит-тестирование, которое вам следует делать, если вы не:)

0 голосов
/ 06 марта 2011

На самом деле это основной кандидат на acceptpts_nested_attributes_for.

Вместо того, чтобы думать о новых действиях в контроллере, придерживайтесь стандартных соглашений REST, когда это возможно.Исключая причудливые элементы отображения пользовательского интерфейса (например, ваше действие выбора), очень редко я нахожу, что мне нужно отклоняться от стандартных действий CRUD, присутствующих в сгенерированном scaffold_controller.

Если вы установите acceptpts_nested_attributes_for: collection в вашей модели Photo,Вы должны быть в состоянии создать специальную форму, которая назначает коллекции для фотографий.Я не буду вдаваться в подробности здесь, но вместо этого укажу на http://railscasts.com/episodes/196-nested-model-form-part-1 и http://railscasts.com/episodes/197-nested-model-form-part-2.Будет больше работы в представлении, но вы выйдете далеко вперед в более простых, легко тестируемых контроллерах и моделях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...