2016-09-28 2 views
1

Я изучаю Ruby's Design Pattern и наткнулся на метод Observer. Я попытался настроить собственный метод наблюдателя, чтобы помочь мне понять его, но он возвращает ошибку. Вот что я придумал:Как обновить два аргумента одновременно с использованием метода Ruby Observer?

class YummyTastyDonut 
    def update(changed_order) 
     puts "Kitchen: Yo, change the order to #{changed_order.order}!" 
     puts "Front: Order for #{changed_order.name}!" 
     puts "Front: The price will now be #{changed_order.order_price} " 
    end 
end 


class Customer 
    attr_reader :name, :order 
    attr_accessor :order_price 

    def initialize(name, order, order_price) 
     @name = name 
     @order = order 
     @order_price = order_price 
     @observers = [] 
    end 

    def order=(new_order, new_price) 
     @order = new_order 
     @order_price = new_price 
     notify_observers 
    end 

    def notify_observers 
     @observers.each do |observer| 
      observer.update(self) 
     end 
    end 

    def add_observer(observer) 
     @observers << observer 
    end 

    def delete_observer(observer) 
     @observers.delete(observer) 
    end 
end 

Если вы читали книгу, я изменил имена классов, но суть та же. Одна вещь, которую я изменил, - это метод order=; теперь он принимает два аргумента вместо одного.

Целью является то, что после создания нового Customer, я хочу, чтобы новый клиент имел возможность изменить мой заказ и уведомить YummyTastyDonut. Тем не менее, я хочу обновить две вещи: order и order_price (очевидно, если я изменю свой заказ, цена также изменится). Я хочу YummyTastyDonut ответить на мои изменения.

igg = Customer.new("Iggy", "Bacon Donut", 10) 
=> #<Customer:0x0056212e48a940 @name="Iggy", @order="Bacon Donut", @order_price=10, @observers=[]> 

donut = YummyTastyDonut.new 
=> #<YummyTastyDonut:0x0056212e4894c8> 

## Updating my order and order_price ## 

    igg.order = ("yummy butter donut", 15) 
#(repl):1: syntax error, unexpected ',', expecting ')' 
#igg.order = ("yummy butter donut", 15) 

Если я использую этот order= метод, который принимает только один аргумент, он работает так же, как ожидалось.

def order=(new_order) 
    @order = new_order 
    notify_observers 
end 

igg.order = "Triple bacon donut explosion" 
Kitchen: Yo, change the order to Triple bacon donut explosion! 
Front: Order for Iggy! 
Front: The price will now be 10 

Что я должен изменить, так что я могу обновить и order и order_price одновременно?

ответ

2

Назначение = предназначен для приема один аргумент, который будет назначен (или такое же количество элементов в качестве переменных в случае параллельного назначения)

.

Вы могли бы сделать это так:

def order=(args) 
    @order = args[0] 
    @order_price = args[1] 
    notify_observers 
end 

Тогда кал л как

igg.order=["yummy butter donut", 15] 

или использовать варианты Hash как @BartekGladys предложенного, но оба решения, кажется ужасным и ошибочным, мягко говоря, и требуют знаний внутренностей методы для того, чтобы использовать его правильно.

Также в настоящее время, даже если этот метод работал, это будет очень запутанным для будущего вас или любого, кто смотрит на вашу базу кода, потому что у вас есть переменная экземпляра @order, поэтому предположение будет order=(val) присвоить эту переменную.

Вам будет лучше с помощью метода change_order, который принимает order и order_price, и это устранит всю путаницу в отношении того, что происходит.

def change_order(new_order, new_price) 
    @order = new_order 
    @order_price = new_price 
    notify_observers 
end 

, а затем его чтение имеет смысл.

igg = Customer.new("Iggy", "Bacon Donut", 10) 
#Currently seems like it is assigning order to an Array maybe? 
igg.order=("yummy butter donut", 15) 
#New much clearer as to the implementation and purpose of changing an order 
igg.change_order("yummy butter donut", 15) 
+0

Такое простое решение! Почему я не подумал об этом? Благодаря!!Кроме того, спасибо, указав, что '=' может принимать только 1 arg. Раньше я этого не знал. Это знание пригодится :) – Iggy

1

Это очень странная ошибка, но я нахожу решение, которое может вам помочь. Вы можете использовать один аргумент и включить туда 2 значения.

def order=(opts={}) 
    @order = opts[:new_order] 
    @order_price = opts[:new_price] 
    notify_observers 
end 

и вызывать эту функцию:

igg.order= {new_order: 'yumyy better donut', new_price: 15 } 
+0

Это имеет смысл! Не думал об использовании хэша раньше. Спасибо! – Iggy

Смежные вопросы