case
оператора в Ruby.
Регулярни изрази
watchr watch.rb
.
watch.rb
файл:watch('solution.rb') do
system 'rspec --require ./solution sample_spec.rb'
end
solution.rb
.
watch.rb
, който да пуска тестовете при промяната му.
skeptic
извикване.
—fail-fast
, която спира изпълнението на първия неуспешен тест.
until spec_passing?
write_code
save
look_at :watchr_output
end
Преди това:
Какви проблеми срещнахте?
Следва моето решение, на части.
class Inventory
def initialize
@products = []
@coupons = []
end
# ...
end
def register(name, price, options = {})
price = price.to_d
promotion = Promotions.for options
@products << Product.new(name, price, promotion)
end
price.to_d
) и ги подава на Product.new
.
options
на Promotions
.
Promotions
.class Inventory
def new_cart
ShoppingCart.new self
end
end
class Product
def initialize(name, price, promotion)
raise "Name should be at most 40 characters" unless name.length <= 40
raise "Only prices between 0.01 and 999.99 allowed" unless 0 < price and price < 1000
@name = name
@price = price
@promotion = promotion
end
# ...
end
discount_for(count)
.class ShoppingCart
attr_reader :items, :coupon
def initialize(inventory)
@inventory = inventory
@items = [] # инстанции на LineItem
@coupon = # засега няма купон
end
def add(product_name, count = 1)
product = @inventory[product_name]
item = @items.detect { |item| item.product == product }
if item
item.count += count
else
@items << LineItem.new(product, count)
end
end
Inventory#[]
.
LineItem
и; после или инкрементираме, или създаваме нов.
if item = @items.detect {}
.def [](name)
@products.detect { |product| product.name == name } or raise 'Unexisting product'
end
Нищо сложно.
class LineItem
attr_reader :product
attr_accessor :count
def initialize(product, count)
@product = product
@count = 0
increase count
end
end
class LineItem
def increase(count)
raise 'You have to add at least one item' if count <= 0
raise 'Maximum 99 items of each product can be bought' if count + @count > 99
@count += count
end
end
Не е най-интересния метод.
class ShoppingCart
def total
items_price - coupon_discount
end
def items_price
@items.map(&:price).inject(&:+)
end
# ...
end
LineItem#price
изчислява отстъпката.
coupon_discount
пък изчислява отстъпката от купона.
class LineItem
def price()
price_without_discount - discount
end
def price_without_discount
product.price * count
end
def discount
product.discount_for(count)
end
end
class LineItem
def price() price_without_discount - discount end
def price_without_discount() product.price * count end
def discount() product.discount_for(count) end
end # Пример за лошо подравняване
price
е изразен чрез два други метода.
product.discount_for(count)
def discount_for(count)
if @promotion
@promotion.discount(count, @price)
else
0
end
end
GetOneFree
, PackageDiscount
и ThresholdDiscount
.
Discount
.
#discount(count, price)
връща отстъпката като BigDecimal
.
#name
връща името за касовата бележка.class GetOneFree
def initialize(nth_item_free)
@nth_item_free = nth_item_free
end
def discount(count, price)
(count / @nth_item_free) * price
end
def name
"buy #{@nth_item_free - 1}, get 1 free"
end
end
Да се върнем на if
-a:
def discount_for(count)
if @promotion
@promotion.discount(count, @price)
else
0
end
end
Просто създайте клас NoPromotion
.
class NoPromotion
def discount(count, price)
0
end
def name
''
end
end
В Ruby има "switch". Казва се case
.
def quote(name)
case name
when 'Yoda'
puts 'Do or do not. There is no try.'
when 'Darth Vader'
puts 'The Force is strong with this one.'
when 'R2-D2'
puts 'Beep. Beep. Beep.'
else
puts 'Dunno what to say'
end
end
break
.
when
не мине, изпълнява се else
.
when
не мине, и няма else
, не става нищо.
case
е израз, което значи, че връща стойност.case
не сравнява с ==
. Може да напишете следното.
def qualify(age)
case age
when 0..12
'still very young'
when 13..19
'a teenager! oh no!'
when 33
'the age of jesus'
when 90..200
'wow. that is old!'
else
'not very interesting'
end
case
сравнява с ===
. Няколко класа го имплементират.
def qualify(thing)
case thing
when Integer then 'this is a number'
when String then 'it is a string'
when Array then thing.map { |item| qualify item }
else 'huh?'
end
end