Как получить родителя полиморфного объекта до его сохранения? - PullRequest
4 голосов
/ 09 февраля 2011

У меня есть стандартные полиморфные отношения, и мне нужно знать, кто его родитель, прежде чем я сохраню их.

Class Picture < AR::Base
  belongs_to :attachable, :polymorphic => true
end

Class Person < AR::Base
  has_many :pictures, :as => :attachable
end

Class Vehicle < AR::Base
  has_many :pictures, :as => :attachable
end

Я загружаю картинки через Paperclip и создаю процессор, который должен выполнять разные вещи.к различным изображениям (т. е. изображения человека должны иметь вид Polaroid, а изображения транспортного средства должны иметь наложение).Моя проблема в том, что перед сохранением изображения я не знаю, связано ли оно с человеком или транспортным средством.

Я попытался поместить «маркер» в меню «Человек и транспортное средство», чтобы я мог сообщить им об этом,но когда я нахожусь в процессоре Paperclip, единственное, что я вижу, это класс Picture.:( Моя следующая мысль - подняться по стеку, чтобы попытаться найти родительского абонента, но мне это кажется довольно вонючим. Как бы вы это сделали?

Ответы [ 3 ]

5 голосов
/ 09 февраля 2011

Вы должны быть в состоянии получить его от полиморфной ассоциации.

Class Picture < AR::Base
  belongs_to :attachable, :polymorphic => true

  before_create :apply_filter

  private

  def apply_filter
    case attachable
    when Person
      #apply Person filter
    when Vehicle
      #apply Vehicle filter
    end
  end
end

Или вы можете просто задать ему тип ассоциации, чтобы не нужно было строить и сравнивать объекты, а просто сравнивать строки.

Class Picture < AR::Base
  belongs_to :attachable, :polymorphic => true

  before_create :apply_filter

  private

  def apply_filter
    case attachable_type
    when "Person"
      #apply Person filter
    when "Vehicle"
      #apply Vehicle filter
    end
  end
end
1 голос
/ 12 февраля 2011

Я «решил» эту проблему и хотел опубликовать ее здесь, чтобы она могла помочь кому-то еще.Мое решение состояло в том, чтобы создать «родительский» метод для класса Picture, который поднялся по стеку и обнаружил нечто, похожее на его родительский.

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

caller.select {|i| i =~ /controller.rb/}.first.match(/\/.+_controller.rb/).to_s.split("/").last.split("_").first.classify.constantize

Что этот код делает, так это поднимается по дереву caller в поисках предкапо имени *_controller.rb.Если он находит один (и должен), он разбирает имя на класс, который должен быть родительским классом вызывающего кода. вот так

Кстати: я бросил скрепку и начал использовать CarrierWave .Он делает такие вещи намного проще, и я смог заставить его работать в два раза быстрее.Да CarrierWave!

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

Я создал интерполяцию для ее решения.Моя модель скрепки Asset, а Project - родительская модель.Существуют и другие модели, например, Статьи, которые находятся под моделью проекта и могут иметь вложения.

Paperclip.interpolates :attachable_project_id do |attachment, style|
  attachable = Asset.find(attachment.instance.id).attachable
  if attachable.is_a?(Project)
    project_id = attachable.id
  else
    project_id = attachable.project.id
  end
  return project_id
end

Paperclip.interpolates :attachable_class do |attachment, style|
  Asset.find(attachment.instance.id).attachable.class
end

И использовали его в модели, например:

  has_attached_file :data,
  :path => "private/files/:attachable_project_id/:attachable_class/:id/:style/:basename.:extension",
  :url => "/projects/:attachable_project_id/:attachable_class/:id/:style",
  :styles => { :small => "150x150>" }
...