Есть ли (код-дизайн) причина не встраивать классы при разработке моделей MongoMapper? - PullRequest
1 голос
/ 26 августа 2011

Этот вопрос относится к использованию Ruby on Rails 3 с MongoMapper и EmbeddedDocument. Также много ассоциаций.

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.

1 Ответ

3 голосов
/ 29 августа 2011

Я не вижу каких-либо технических проблем для любого подхода. Проблема, с которой я столкнулся, заключается в том, что когда класс встроен в его родительский объект и также находится в том же файле, я забуду, что он там есть. Поэтому, если ваше пространство имен называется Order::LineItem, вы можете создать папку «order» в папке «models» и поместить туда «line_item.rb».

Другая проблема в том, что если вы хотите иметь контроллер для Order::LineItem, вы также должны указать пространство имен и поместить его в папку, и в маршрутизаторе он будет выглядеть так:

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

Если вы не знаете , что ваше приложение будет иметь несколько типов line_items, я бы не рекомендовал использовать пространство имен - вы могли бы перезаписать код, если бы сделали это. Например, если позже вам понадобятся два типа line_items, вы можете даже обнаружить, что часть вашего кода может быть повторно использована между моделями, и если вы поместите пространство имен в свой первый line_item, вы можете оказаться де-пространством между ними.

В Python пространства имен считаются отличной вещью, которой должно быть больше. Но когда вы думаете о глобальном пространстве имен вашего Rails-приложения, оно не так загромождено. Авторы драгоценных камней довольно хорошо хранят пространство имен всех своих классов в одном модуле гемов, поэтому в вашем приложении на Rails у вас будет по одному пространству имен для каждого используемого вами гема (сам Rails - 5 гемов, не уверен, сколько глобальных константы, хотя), плюс и куча файлов, включенных в Rails (например, SecureRandom). Оказывается, очень приятно иметь эти файлы «просто там», и на практике я обнаружил, что коллизии пространства имен редки, и вы легко можете их обойти. Возможно, я столкнулся с проблемой пространства имен только один раз, но несколько раз я случайно определял метод «отправки» в модели - гораздо более распространенная проблема с подобными последствиями.

...