Как выполнить массовую проверку связи в Rails - PullRequest
2 голосов
/ 31 июля 2011

У меня есть следующий сценарий:

Одна из моих моделей, назовем ее «Пост», имеет несколько связанных моделей, Изображения.

Одно и только одно из этих изображений можетбыть ключевым Image для его Post (который представлен в виде логического флага на модели Image и применяется посредством проверки в модели Image, которая использует Post в качестве области действия).

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

Я знаю, эта вещь кричит о преобразованиив ассоциацию по модели Post, которая ссылается на ключевой образ, но есть ли способ проверить массовые ассоциации в Rails?

Что бы вы выбрали, вы бы сделали ключевой образ отдельной ассоциацией намодель Post или вы бы использовали логический флаг?

Ответы [ 2 ]

3 голосов
/ 31 июля 2011

есть простое решение, но оно требует некоторого доверия:

  • Удалить проверку "есть только одно основное изображение?"
  • Убедитесь, что будет только одно основное изображение, добавив фильтр

Большой плюс в том, что вам не нужно ничего проверять в контроллере или пост-модели. Просто возьмите изображение, установите is_primary в true и сохраните его.

Таким образом, установка может выглядеть следующим образом:

class Post < ActiveRecord::Base
  has_many  :images 

  # some sugar, @mypost.primary_image gets the primary image
  has_one   :primary_image, 
            :class_name => "Image", 
            :conditions => {:is_primary => true }
end

class Image < ActiveRecord::Base
  belongs_to :post

  # Image.primary scopes on primary images only
  scope :primary, where(:is_primary => true)

  # we need to clear the old primary if:
  # this is a new record and should be primary image
  # this is an existing record and is_primary has been changed to true

  before_save :clear_primary, 
              :if => Proc.new{|r| (r.new_record? && r.is_primary) || (r.is_primary_changed? && r.is_primary) }

  def clear_primary
    # remove old primary image
    Image.update_all({:is_primary => false}, :post_id => self.post_id)
  end
end

Edit:

Это будет работать в любом случае - почему?

  • before_save вызывается только в случае успешной проверки
  • все сохранение заключено в транзакцию, это означает, что если clear_primary или сохранение самого изображения завершится неудачно, все будет возвращено к исходному состоянию.
0 голосов
/ 31 июля 2011

Ну, вы можете сделать это в вашей модели Post:

# Post.rb
has_many :images, :conditions => ['primary = ?', false]
has_one :primary_image, :conditions => ['primary = ?', true]

Если вы хотите изменить основное изображение, сделайте что-то вроде этого:

# Post.rb
def new_primary_image(image_id)
    primary_image.primary = false
    Image.find(image_id).primary = true
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...