开发者

Is there a (code-design) reason to not embed classes when designing MongoMapper models?

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 namespa开发者_JAVA百科ces). So my code above is also achieving that in Rails.


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:

resource :orders do
  resources :line_items,         :controller => "order/line_items"
end

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜