Rails:当您不知道对象属于哪个类时尝试输出对象的内容
序言:
不要被我的 Rails 3 应用程序使用 has_many_polymorphs gem 的事实吓到,就像我一样我认为您不需要熟悉 gem 才能在这里帮助我:)
我的代码:
我有一个包含许多片段的 Post 模型。还有四个附加模型,它们是snippetable,即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
但是这将导致博客文章如下所示:
- 文本片段 文本
- 片段 图像
- 片段
- 图像片段
我不想要片段以这种方式按 Class 分组。
我该如何解决这个问题?
好吧,我看看这个问题。我知道我可以执行以下操作:
- for snippet in @post.snippets
= snippet.snippetable_type.downcase
这将输出每个片段的类名称,如下所示:
- text
- image
- text
- image
但我想要每个片段的内容。
扩展我们上面的内容,由于每种类型的片段都有一个与类本身同名的属性,我也可以这样做:
- for snippet in @post.snippets
= "#{snippet.snippetable_type.downcase}.#{snippet.snippetable_type.downcase}"
这将输出每个片段的类名和属性名称:
- text.text
- image.image
- text.text
- image.image
如果我能找到一种获取内容而不是类名的方法,那么我就可以了。有人有任何线索吗?
如果有人得到这个,我绝对会感到惊讶。如果您已经读到这里,谢谢。
Preamble:
Don't be scared off by the fact My Rails 3 app uses the has_many_polymorphs gem as I don't think you need to be familiar with the gem in order to help me here :)
My code:
I have a Post model which has many Snippets. There are four additional models which are snippetable i.e. of type 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
Adding snippets to a Post
Now if I want to add two text snippets and two image snippets to a post I can do this:
# 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")
The result is a blog post that looks like this:
- text snippet
- image snippet
- text snippet
- image snippet
My Problem
I'm having some trouble displaying the content of each snippet in my view.
I could do the following in my view:
- 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
BUT this will result in a blog post that looks like this:
- text snippet
- text snippet
- image snippet
- image snippet
I don't want snippets to be grouped by Class in this way.
How can I solve this?
Well I've a look at the problem. I know that I CAN do the following:
- for snippet in @post.snippets
= snippet.snippetable_type.downcase
and this will output the Class name of each snippet as shown:
- text
- image
- text
- image
BUT I want the content of each snippet.
Expanding on what we have above, since each type of snippet has one attribute with the same name as the Class itself, I can also do this:
- for snippet in @post.snippets
= "#{snippet.snippetable_type.downcase}.#{snippet.snippetable_type.downcase}"
And this will output the classname AND the attribute name of each snippet:
- text.text
- image.image
- text.text
- image.image
If I could just find a way of getting to the content and not the Classnames then I'd be ok. Anyone got any clue?
I will be absolutely amazed if anyone gets this one. Thanks if you have read this far.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因此,您希望它按照
for snippet in @post.snippets
为您提供的顺序,但您需要它根据snippetable_type
发送文本、图像、代码或视频,还是我误读了你?So you want it in the order that
for snippet in @post.snippets
gives you, but you need it to send text, image, code or video depending on thesnippetable_type
, or am I misreading you?我想知道是否(a)这个应用程序和这些片段比您显示的更复杂,或者(b)您在不保证开销的情况下使用 has_many_polymorphs 。
我的意思是:如果这些代码片段类型除了类名和访问器名称之外实际上都是相同的,那么您根本不需要子类:一个通用的 Post 类就可以了。
另一方面,如果 Post/Snippet 类确实根据类型有不同的行为,那么更好的解决方案是使用鸭子类型来获取所需的输出。 (如果我从你的代码中理解它,这实际上可能是 has_many_polymorphs 的全部目的。)例如:每个可片段类型都可以实现一个方法(鸭子类型).to_html(),其中每个类型都会创建一个简单的 html最适合它的演示。然后this就是您在循环内调用的方法。
I'm wondering if either (a) there's more complexity to this app and these snippets than you're showing, or (b) you're using has_many_polymorphs in a situation that doesn't warrant the overhead.
What I mean is: if these snippet types are really all identical except for the class name and accessor name, then you don't need the subclasses at all: one generic Post class will do.
On the other hand, if the Post/Snippet classes do have different behavior depending on type, then a better solution would be to use duck typing to get the output you want. (And this may actually be the entire purpose of has_many_polymorphs if I understand it from your code.) For example: Each snippetable type could implement a method (the duck type) .to_html() in which each one would create a bare-bones html presentation most appropriate to it. And then this is the method you'd call inside your loop.