简体   繁体   中英

Rails namespace class same as existing active_record model

I'm having a bit trouble with the namespaces in Rails 4.

I have ActiveRecord models Shop , Order , and OrderItem

# model/shop.rb
class Shop < ActiveRecord::Base

# model/order.rb
class Order < ActiveRecord::Base
  has_many :order_items

# model/order_item.rb
class OrderItem < ActiveRecord::Base
  belongs_to :orderable, polymorphic: true
  belongs_to :order

I'm replicating the relationship between Order and OrderItem in a namespace like this

# model/shop/order.rb
class Shop::Order
  attr_accessor :order_items
  def initialize
    self.order_items = []
    self.order_items << Shop::OrderItem.new
  end

# model/shop/order_item.rb
class Shop::OrderItem
  attr_accessor :orderable_type, :orderable_id

  def initialize(params = {})
    if params
      self.orderable_type = params['orderable_type'] if params['orderable_type']
      self.orderable_id = params['orderable_id'] if params['orderable_id']
    end
  end

  def price
    orderable.price
  end

  def orderable
    orderable_type.constantize.find_by(id: orderable_id)
  end

  def to_h
    Hash[
      orderable_type: self.orderable_type,
      orderable_id: self.orderable_id,
      price: self.price
    ]
  end

end

So my problem is that when I initialize Shop::Order.new , sometimes its order_items is an array of OrderItem s instead of Shop::OrderItem s, and when I test it in the controller, if I type Shop::OrderItem , it will return OrderItem .

I'm wondering if Shop::OrderItem wasn't initialized before OrderItem and cause the issue?

You are running into a namespace collision. Depending on where the code is executing, Shop could be the ActiveRecord model that you've defined in models/shop.rb , or it could be the module namespace that you've defined under models/shops/*.rb . Not only will this cause unpredictable execution, it's also confusing to read.

I recommend using a module namespace other than "Shop". Even calling it "MyShop" would be an improvement. However you'll probably still run into naming collisions between Shop and MyShop::Shop . You should probably rename the Shop class under the MyShop module to avoid this:

For example:

# model/my_shop/my_order.rb
class MyShop::MyOrder
  # ...
end
# model/my_shop/my_order_item.rb
class MyShop::MyOrderItem
  # ...
end

Having said all that, I feel like you're setting yourself up for a world of hurt. This problem might be better solved using service objects. Google up "Rails Service Objects" for some really good examples.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM