1

前言:

不要被 My Rails 3 应用程序使用has_many_polymorphs gem的事实吓到,因为我认为您不需要熟悉 gem 来帮助我:)

我的代码:

我有一个包含许多片段的 Post 模型。还有四个额外的模型是可片段的​​,即Snippet类型:

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

但是这将导致一个看起来像这样的博客文章:

  • 文本片段
  • 文本片段
  • 图像片段
  • 图像片段

我不希望片段以这种方式按类分组。

我该如何解决这个问题?

好吧,我看看这个问题。我知道我可以做到以下几点:

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

这将输出每个片段的类名,如下所示:

  • 文本
  • 图片
  • 文本
  • 图片

但我想要每个片段的内容。

扩展我们上面的内容,因为每种类型的代码片段都有一个与类本身同名的属性,我也可以这样做:

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

这将输出每个片段的类名和属性名:

  • 文本.文本
  • 图像.图像
  • 文本.文本
  • 图像.图像

如果我能找到一种获取内容而不是类名的方法,那么我就可以了。有人有任何线索吗?

如果有人得到这个,我会感到非常惊讶。谢谢你读到这里。

4

2 回答 2

3

所以你想要它按照for snippet in @post.snippets给你的顺序,但你需要它来发送文本、图像、代码或视频,这取决于snippetable_type,还是我误读了你?

- for snippet in @post.snippets
  = snippet.snippetable.send(snippet.snippetable_type.downcase)
于 2010-12-15T23:43:35.667 回答
1

我想知道(a)这个应用程序和这些片段是否比您显示的更复杂,或者(b)您在不保证开销的情况下使用 has_many_polymorphs。

我的意思是:如果这些片段类型除了类名和访问器名之外都完全相同,那么您根本不需要子类:一个通用的 Post 类就可以了。

另一方面,如果 Post/Snippet 类确实根据类型具有不同的行为,那么更好的解决方案是使用鸭子类型来获得所需的输出。(如果我从您的代码中理解它,这实际上可能是 has_many_polymorphs 的全部目的。)例如:每个可片段化类型都可以实现一个方法(鸭子类型) .to_html() ,其中每个都会创建一个简单的 html最适合它的介绍。然后是您在循环中调用的方法。

于 2010-12-16T02:02:05.120 回答