在设计 MongoMapper 模型时是否有(代码设计)原因不嵌入类?
这个问题涉及将 Ruby on Rails 3 与 MongoMapper 和 EmbeddedDocument 一起使用。还有,ManyAssociation。
http://mongomapper.com/documentation/embedded-document.html
MongoMapper 示例 (在上面的链接中)显示两个单独的类:
class Order
include MongoMapper::Document
many :line_items
timestamps!
end
class LineItem
include MongoMapper::EmbeddedDocument
key :name, String
key :quantity, Integer
end
但这会污染 LineItem 的全局命名空间。断章取义,LineItem 的用途是什么?如果我想要另一个模型(例如 WishList)也有一个 LineItem 集怎么办?
因此可以将 LineItem 类嵌入到 Order 中,如下所示:
class Order
include MongoMapper::Document
many :line_items, :class_name => "Order::LineItem"
timestamps!
class LineItem
include MongoMapper::EmbeddedDocument
key :name, String
key :quantity, Integer
end
end
虽然这在技术上可能没问题(是吗?),但稍后我会遇到设计问题吗?它只会让代码变得太难看吗?太复杂?
据推测,Ruby 语言中存在此功能意味着有人认为这是一个不错的主意?
我一直喜欢 Django 的一件事是它如何使用“应用程序”对相关模型类进行分组(并分隔命名空间)。所以我上面的代码也在 Rails 中实现了这一点。
This question relates to using Ruby on Rails 3 with MongoMapper and EmbeddedDocument. Also, the ManyAssociation.
http://mongomapper.com/documentation/embedded-document.html
The MongoMapper examples (in the link above) show two separate classes:
class Order
include MongoMapper::Document
many :line_items
timestamps!
end
class LineItem
include MongoMapper::EmbeddedDocument
key :name, String
key :quantity, Integer
end
But this pollutes the global namespace with LineItem. Out of context, LineItem for what? And what if I want another model, say WishList, to also have a LineItem set?
So it is possible to embed the LineItem class inside Order, like this:
class Order
include MongoMapper::Document
many :line_items, :class_name => "Order::LineItem"
timestamps!
class LineItem
include MongoMapper::EmbeddedDocument
key :name, String
key :quantity, Integer
end
end
While this may be technically fine (yes?), will I run into design issues later on? Does it just make the code too ugly? Too complex?
Presumably, the existence of this in the Ruby language means someone thinks it's an ok idea?
One thing I always liked about Django is how it uses "apps" to group related model classes (and separate the namespaces). So my code above is also achieving that in Rails.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为这两种方法都没有任何技术问题。我遇到的问题是,当一个类嵌入到它的父类中并且也在同一个文件中时,我会忘记它的存在。因此,如果您将其命名空间为
Order::LineItem
,您可以在“models”文件夹中创建一个“order”文件夹,并将“line_item.rb”放入其中。另一个麻烦是,如果您想要
Order::LineItem
有一个控制器,您还必须为其命名空间并将其放入文件夹中,并且在路由器中它将如下所示:除非您知道您的应用程序将具有多种类型的 line_items,我建议不要为其命名空间 - 如果这样做,您可能会过度编码。例如,如果您后来需要两种类型的 line_item,您甚至可能会发现您的某些代码可以在模型之间重复使用 - 如果您对第一个 line_item 进行命名空间,您可能会发现自己取消了它的命名空间。
在 Python 中,命名空间被认为是一件很棒的事情,应该有更多。但是当您考虑 Rails 应用程序的全局命名空间时,您会发现它并没有那么混乱。 Gem 作者非常擅长将所有类命名空间保存在一个 gem 模块中,因此在 Rails 应用程序中,您正在使用的每个 gem 都有一个命名空间(Rails 本身有 5 个 gem,不确定有多少个全局 gem)常量),加上 Rails 包含的一堆文件(例如 SecureRandom)。事实证明,让这些文件“就在那里”真是太好了,而且我在实践中发现命名空间冲突很少见,您可以轻松解决它们。我可能只遇到过一次命名空间问题,但有好几次我不小心在模型上定义了“发送”方法——这是一个更常见的问题,具有类似的影响。
I don't see any technical problems to either approach. The problem I've run into is that when a class is embedded in it's parent and is also in the same file, I'll forget it's there. So if your namespaces it as
Order::LineItem
you can make an "order" folder in your "models" folder and put "line_item.rb" in there.The other trouble is if you want to have a controller for
Order::LineItem
, you also have to namespace it and put it in a folder, and in the router it will look like:Unless you know your app is going to have multiple types of line_items, I'd recommend not namespacing it—you could be over-coding if you did. For example, if you were later to need two types of line_items you might even find that some of your code could be re-used between models—and if you namespaced your first line_item you may find yourself de-namespacing it.
In Python, namespaces are considered a great thing that there should be more of. But when you think about the global namespace of your Rails app, it's not that cluttered. Gem authors are pretty good about keeping all of their classes namespaced in their one gem module, so in your Rails app you're going to have one namespace for each gem you're using (Rails itself is 5 gems, not sure how many global constants though), plus and a bunch of files included by Rails (e.g. SecureRandom). It turns out to be really nice to have those files "just there" and I've found in practice that namespace collisions are rare and you can easily work around them. I've only run into a namespace issue maybe once, but several times I've accidentally defined a "send" method on a model—a much more common problem with similar repercussions.