Rails: попытка вывести содержимое объекта, когда вы не знаете, к какому классу принадлежит объект - PullRequest
1 голос
/ 16 декабря 2010

Преамбула:

Не пугайтесь того факта, что приложение My Rails 3 использует гем has_many_polymorphs , так как я не думаю, что вы должны быть знакомы с гемом, чтобы помочь мне здесь:)

Мой код:

У меня есть модель Post, в которой много фрагментов. Существуют четыре дополнительные модели, снимаемые , то есть типа сниппет :

class Post < ActiveRecord::Base
  has_many_polymorphs :snippets, 
                      :from => [:texts, :videos, :images, :codes], 
                      :through => :snippets
end

class Snippet < ActiveRecord::Base
  belongs_to :post
  belongs_to :snippetable, :polymorphic => true      
  attr_accessible :post_id, :snippetable_type, :snippetable_id
end

# There following four models are snippetable:

class Code < ActiveRecord::Base
  # note that the attribute name is the same as the Class name
  attr_accessible :code
end

class Text < ActiveRecord::Base
  # note that the attribute name is the same as the Class name
  attr_accessible :text
end

class Image < ActiveRecord::Base
  # note that the attribute name is the same as the Class name
  attr_accessible :image
end

class Video < ActiveRecord::Base
  # note that the attribute name is the same as the Class name
  attr_accessible :video
end

Добавление фрагментов в сообщение

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

# find the first post
p = Post.first

p.texts << Text.create(:text => "This is the first sentence")
p.images << Image.create(:image => "first_image.jpg")
p.texts << Text.create(:text => "This is the second sentence")
p.images << Image.create(:image => "second_image.jpg")

В результате получается сообщение в блоге, которое выглядит так:

  • фрагмент текста
  • фрагмент изображения
  • фрагмент текста
  • фрагмент изображения

Моя проблема

У меня возникли проблемы с отображением содержимого каждого фрагмента в моем представлении.

Я мог бы сделать следующее, на мой взгляд:

- for text in @post.texts
  = text.text
- for image in @post.images
  = image.image
- for code in @post.codes
  = code.code
- for video in @post.videos
  = video.video

НО это приведет к записи в блоге, которая выглядит следующим образом:

  • фрагмент текста
  • фрагмент текста
  • фрагмент изображения
  • фрагмент изображения

Я не хочу, чтобы фрагменты группировались по классу таким образом.

Как я могу решить это?

Ну, я посмотрел на проблему. Я знаю, что я CAN делаю следующее:

- for snippet in @post.snippets
  = snippet.snippetable_type.downcase

, и это выведет имя класса каждого фрагмента, как показано:

  • текст
  • изображение
  • текст
  • изображение

НО я хочу содержимое каждого фрагмента.

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

- for snippet in @post.snippets
  = "#{snippet.snippetable_type.downcase}.#{snippet.snippetable_type.downcase}"

И это выведет имя класса И имя атрибута каждого фрагмента:

  • text.text
  • image.image
  • text.text
  • image.image

Если бы я мог просто найти способ получить доступ к контенту, а не к именам классов, тогда я был бы в порядке. У кого-нибудь есть подсказка?

Я буду очень удивлен, если кто-нибудь получит это. Спасибо, если вы прочитали это далеко.

Ответы [ 2 ]

3 голосов
/ 16 декабря 2010

Таким образом, вы хотите получить его в том порядке, который вам дает for snippet in @post.snippets, но вам нужно отправить текст, изображение, код или видео в зависимости от snippetable_type, или я неправильно вас читаю?

- for snippet in @post.snippets
  = snippet.snippetable.send(snippet.snippetable_type.downcase)
1 голос
/ 16 декабря 2010

Мне интересно, если либо (а) это приложение и эти фрагменты сложнее, чем вы показываете, или (б) вы используете has_many_polymorphs в ситуации, которая не требует накладных расходов.

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

Вкл.с другой стороны, если классы Post / Snippet имеют различное поведение в зависимости от типа, то лучшим решением будет использование утиной типизации для получения желаемого результата.(И на самом деле это может быть целой целью has_many_polymorphs, если я понимаю это из вашего кода.) Например: Каждый сниппируемый тип может реализовывать метод (тип утки) .to_html (), в котором каждый из них создает чистый HTMLпрезентация наиболее подходящая для этого.И тогда этот - это метод, который вы бы вызвали внутри своего цикла.

...