mongoid模型的棘手扩展

时间:2016-04-02 19:35:41

标签: ruby-on-rails mongoid

有两种车型:Car(例如Audi,Mercedes)和Option(ABS,Laser Headlights,Night Vision ......)。汽车habtm选项。

假设奥迪和梅赛德斯"夜视"选项可用。 但要在梅赛德斯拥有它,你需要为这个选项支付一些额外的钱。因此,我猜我需要以某种方式扩展我的选项模型,以存储某些汽车的选项额外价格。我认为车型也应该进行修改。但无法想象如何。

我的目标是实现这样的行为:

Audi.options.night_vision.extra_price =>零

Mercedes.options.night_vision.extra_price => 300

当然,我不想复制"夜视"每辆车的选项集中的选项。

感谢。

1 个答案:

答案 0 :(得分:0)

这既不是最简单的,也不是最优雅的,只是基于对如何实施选项的假设而有效的想法。如果您需要更多帮助,请回复我。

要实现audi.options.night_vision.extra_price我假设您有以下模型:

class car
   include Mongoid::Document
   field :name, type: String
   has_and_belongs_to_many :options do
     def night_vision
       @target.find_by(name:'night_vision')
     end
   end
end

class option
   include Mongoid::Document
   field :name, type: String
   field :extra_price, type: Float
   has_and_belongs_to_many :cars
end

这将使您能够:

audi = Car.find_by(name:'audi')
audi.options.night_vision.extra_price

如果上述假设是正确的,你应该可以像这样修改你的类:

class option
   include Mongoid::Document
   attr_accessor :extra_price
   field :name, type: String
   has_and_belongs_to_many :cars
   embeds_many :extras 
end

class extra
   include Mongoid::Document
   field :car_id, type: String
   field :price, type: String
   embedded_in :option
end

class car
   include Mongoid::Document
   field :name, type: String
   has_and_belongs_to_many :options do
     def night_vision
       extra = @target.find_by(name:'night_vision')
       extra_price = extra.prices.find_by(car_id: @target._id.to_s) if extra
       extra.extra_price = extra_price.price if extra && extra_price
       return extra
     end
     def find_or_create_option(args)
         extra = @target.find_or_create_by(name:args)
         price = extra.extras.find_or_create_by(car_id:@target._id.to_s)
         price.set(price: args.price
     end
   end
end

然后,您应该可以填写以下选项:

audi.options.find_or_create_option({name:'night_vision', price:2310.30})
bmw.options.find_or_create_option({name:'night_vision', price:1840.99})

audi.options.night_vision.extra_price
=> 2310.30
bmw.options.night_vision.extra_price
=> 1840.99

如果你试图在没有night_vision的汽车上找到night_vision,你会得到:

skoda.options.night_vision
=> nil
skoda.options.night_vision.extra_price
=> NoMethodError (undefined method 'extra_price' for nil:NilClass)