[如果我们考虑一家杂货店有一套库存。我想知道是否还有一种更惯用的方法?
首先,我有一个可爱的货架班:
# The Shelves class holds the items in the market
class Shelves
attr_reader :item_price
def initialize(item_name, item_price, item_promo_group, item_quantity)
@item_name = item_name
@item_price = item_price
@item_promogroup = item_promo_group
@item_quantity = item_quantity
end
end
我的意图是致电Market.new并创建一组初始库存。目前,我正在实例化多个Shelves实例,如下所示:
class Market
attr_reader :initial_stock
def initialize
@initial_stock = [Shelves.new('item1', 1.00, 'A', 10),
Shelves.new('item2', 1.50, 'B', 9),
Shelves.new('item3', 2.00, 'C', 8),
Shelves.new('item4', 2.50, 'A', 7),
Shelves.new('item5', 3.00, 'B', 6),
Shelves.new('item6', 4.50, 'C', 5),
Shelves.new('item7', 5.00, 'A', 4),
Shelves.new('item8', 1.00, 'B', 3),
Shelves.new('item9', 1.50, 'C', 2),
Shelves.new('item10', 2.00, 'A', 1)]
end
end
它在一个数组中,因为...主要是我用它来求和所有价格的总和,以获得总股价。我想到了另一种方式,例如使用实例变量,但这也感觉太冗长,例如:
@apple = Shelves.new('apple', 1.00, 'A', 10)
@banana = Shelves.new('banana', 1.00, 'A', 10)
@pear = Shelves.new('pear', 1.00, 'A', 10)
基本上我是在问,做与上面类似的事情的最惯用的方法是什么?
建模业务域对象并非易事。为了进行可靠的实际库存管理,您可能希望使用真实的数据库而不是“普通的旧Ruby对象”(PORO)来管理CRUD操作和数据规范化,但是您当然可以使用以下方法来model问题域一些相当基本的PORO,例如Array和Struct。
我可能会误解您的问题,但是似乎问题更多的是关于如何正确建模域的问题。您确实需要一个完全标准化的数据库,该数据库应具有描述库存中的项目(以及可能的每个项目的位置数据,如过道和货架)的模式,而不是复杂的Ruby对象。
也就是说,如果您只是想找到一种方法来用纯Ruby表示当前数据集,则可以考虑以下方法:
require 'singleton'
class Inventory
include Singleton
attr_accessor :items
def initialize
@items = []
end
end
class Item < Struct.new(:name, :price, :quantity, :promo_group)
end
inventory = Inventory.instance
inventory.items.append(
Item.new('apple', 0.99, 5, 'A'),
Item.new('orange', 1.50, 7, 'B'),
)
[基本上,这个想法是创建一个singleton库存对象,其中包含一个Item对象的数组。每个Item对象都是一个Struct,其中包含您可能需要的任何数据。您可以通过Inventory#items的getter和setter方法操作库存,或通过其Struct的类似于Enumerable的行为来引用库存中单个项目的属性。例如:
inventory.items
#=> [#<struct Item name="apple", price=0.99, quantity=5, promo_group="A">, #<struct Item name="orange", price=1.5, quantity=7, promo_group="B">]
inventory.items.map &:name
#=> ["apple", "orange"]
inventory.items.select { _1.promo_group == ?A }
#=> [#<struct Item name="apple", price=0.99, quantity=5, promo_group="A">]
inventory.items.filter { _1.name == 'apple' }.count
#=> 1
inventory.items.filter { _1.name == 'apple' }.map &:to_h
#=> [{:name=>"apple", :price=>0.99, :quantity=>5, :promo_group=>"A"}]
这解决了您所问的问题,但是您必须为基本操作(例如搜索,添加,删除或更新特定库存项目)构建自己的方法。具有object-relational mapping的真实数据库(例如,在SQL或NoSQL数据库之上的ActiveRecord,Sequel或类似的ORM接口)对于真实世界的应用程序确实是更好的解决方案。