Создание хэша в Rails 3

#ruby-on-rails #ruby-on-rails-3 #hash #controller #iteration

#ruby-on-rails #ruby-on-rails-3 #хэш #контроллер #итерация

Вопрос:

У меня есть задатки метода, который вычисляет лицензионные платежи для ISBN. Это разделяет продажи по каналам продаж. Ставка роялти определяется общим количеством проданных товаров, а роялти рассчитывается путем умножения ставки роялти (в процентах) на общий доход. Таким образом, результатом должно быть рассчитанное значение роялти для каждого канала продаж, для каждого isbn. Простите за то, что, вероятно, является чрезмерно прокомментированным кодом.

В методе show isbns_controller:

 @isbn = Isbn.find(params[:id])

def royalty(isbn)
  @royaltiesbychannel = Hash.new()     
  # Returns all sales for the current isbn, and groups them by channel_id in a hash 
  # {1 => sale 1, sale 2}, {2 => sale 1, sale 2}
  # Then loops through each key-value pair.    
  @isbn.sales.group_by(amp;:channel_id).each do |ch_id, sale_array|
    # Takes the sales grouped by channel, and totals the quantities and values into two separate variables. 
    value_total_by_channel = sale_array.sum(amp;:value)  
    quantity_total_by_channel = sale_array.sum(amp;:quantity)  
     # Gets all the rules for the isbn
     @isbn.rules.each do |rule|
       # Jumps to the next sales hash unless the channel ids match
       next unless rule.channel_id == ch_id
       if Range.new(rule.lower,rule.upper).include?(quantity_total_by_channel)
         @royaltiesbychannel[ch_id] = value_total_by_channel * rule.rate
       end
     end
   end
 end
  

Это та последняя строка, которая вызывает у меня проблему. Что я хочу, так это создать хэш с идентификаторами каналов в качестве ключей и рассчитанными гонорарами в качестве значений. Но вместо этого он создает хэш только с одной парой ключ-значение, в чем-то, что выглядит следующим образом:

 {1=>#<BigDecimal:10132a620,'0.875E5',9(36)>}
  

Я подозреваю, что что-то не так с тем, как я создаю новый хэш в верхней части метода, а также с попыткой объявить ключ в квадратных скобках.

rule.rate — это процент, выраженный в виде десятичной дроби, например 0,10. Значение является целым числом (по крайней мере, на данный момент). Есть мысли о том, как сгенерировать этот хэш?

Во-вторых, каков наилучший способ перебора результирующего хэша в представлении?

Заранее большое спасибо.

Обновление — вывод .inspect в соответствии с запросом:

 {1=>[#<Sale id: 1, isbn_id: 2, quantity: 3000, value: 122000, currency: "", total_quantity: nil, created_at: "2011-05-16 19:52:36", updated_at: "2011-05-22 14:28:33", customer: "WHS", retail_price: nil, discount: nil, channel_id: 1, invoice_date: "2011-02-01", rule_id: nil>, #<Sale id: 2, isbn_id: 2, quantity: 500, value: 3000, currency: "", total_quantity: nil, created_at: "2011-05-19 09:55:00", updated_at: "2011-05-19 09:55:00", customer: "Borders", retail_price: nil, discount: nil, channel_id: 1, invoice_date: nil, rule_id: nil>], 2=>[#<Sale id: 6, isbn_id: 2, quantity: 10, value: 2000, currency: "", total_quantity: nil, created_at: "2011-05-19 10:34:34", updated_at: "2011-05-19 11:21:07", customer: "Bookshop a", retail_price: nil, discount: nil, channel_id: 2, invoice_date: nil, rule_id: nil>, #<Sale id: 7, isbn_id: 2, quantity: 2000, value: 4000, currency: "", total_quantity: nil, created_at: "2011-05-19 10:34:49", updated_at: "2011-05-19 10:34:49", customer: "Bookshop b", retail_price: nil, discount: nil, channel_id: 2, invoice_date: nil, rule_id: nil>]}
  

Второе обновление: пересмотр вопроса:

Спасибо за ваши мысли на данный момент. Оказывается, метод работает нормально, потому что хэш, сгенерированный @isbn.sales.group_by(amp;:channel_id) , содержит только одну пару ключ-значение. Итак, мой вопрос все еще остается в силе, но для другой части моего кода: как мне выполнить поиск в модели продаж, чтобы создать массив хэшей, подобных {1 => sale 1, sale 2}, {2 => sale 1, sale 2} ?

Я пробовал эту ужасную вещь:

 @channelarray = Channel.select(:id).all  
@salesbychannelwrong = @channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", @isbn)}   
@salesbychannel = @salesbychannelwrong.invert
  

что дает это:

 {[#<Channel id: 1>]=>[#<Sale id: 1, isbn_id: 2, quantity: 3000, value: 122000, currency: "", total_quantity: nil, created_at: "2011-05-16 19:52:36", updated_at: "2011-05-22 14:28:33", customer: "WHS", retail_price: nil, discount: nil, channel_id: 1, invoice_date: "2011-02-01", rule_id: nil>, #<Sale id: 2, isbn_id: 2, quantity: 500, value: 3000, currency: "", total_quantity: nil, created_at: "2011-05-19 09:55:00", updated_at: "2011-05-19 09:55:00", customer: "Borders", retail_price: nil, discount: nil, channel_id: 1, invoice_date: nil, rule_id: nil>], [#<Channel id: 2>]=>[#<Sale id: 6, isbn_id: 2, quantity: 10, value: 2000, currency: "", total_quantity: nil, created_at: "2011-05-19 10:34:34", updated_at: "2011-05-19 11:21:07", customer: "Bookshop a", retail_price: nil, discount: nil, channel_id: 2, invoice_date: nil, rule_id: nil>, #<Sale id: 7, isbn_id: 2, quantity: 2000, value: 4000, currency: "", total_quantity: nil, created_at: "2011-05-19 10:34:49", updated_at: "2011-05-19 10:34:49", customer: "Bookshop b", retail_price: nil, discount: nil, channel_id: 2, invoice_date: nil, rule_id: nil>]}
  

Я также пытался

 Sale.find_by_isbn_id(:id).group_by(amp;:channel_id)
  

который возвращает nil

и это

 Sale.find_by_isbn_id(@isbn).group_by(amp;:channel_id)
  

который возвращает

 undefined method `group_by' for #<Sale:0x0000010122df60>
  

У меня есть следующие модели:

 class Sale
  belongs_to :isbn
  belongs_to :channel
  ...
end

class Isbn
  has_many :rules
  has_many :sales
  has_many :channels, :through => :sales
  ...
end

class Channel
  has_many :sales
  has_many :rules
  ...
end

class Rule
  belongs_to :isbn
  belongs_to :channel
  has_many :sales, :through => :isbn
  ...
end
  

Еще раз спасибо.

Комментарии:

1. Что возвращает @isbn.sales.group_by(amp;:channel_id).size?

2. Привет, Энди — он возвращает 2, когда я помещаю его в переменную экземпляра и в файл views> isbns> show.html.erb. Спасибо, что нашли время…

3. Можете ли вы вывести @isbn.sales.group_by(amp;:channel_id).проверить в представлении и вставить его сюда?

4. Спасибо, @dmarkow, за то, что разобрался с форматированием.

5. Ваш подход кажется нормальным, но я подозреваю, что @isbn.sales возвращает не то, что вы думаете.

Ответ №1:

Sale.find_by_isbn_id(@isbn).group_by(amp;:channel_id) => Sale.find_all_by_isbn_id(@isbn).group_by(amp;:channel_id)

или

 Sale.where(:ibn_id => @isbn.id).group_by(amp;:channel_id)
  

Комментарии:

1. Большое спасибо, но каждый из них по-прежнему выдает это: {1=>[#<Sale id: 1, isbn_id: 2, quantity: 3000, rule_id: nil>], 2=>[#<Sale id: 6, isbn_id: 2, quantity: 10, value: 2000, rule_id: nil>]} вместо желаемого: {1=>[#<Sale id: 1, isbn_id: 2, quantity: 3000, rule_id: nil>]}, {2=>[#<Sale id: 6, isbn_id: 2, quantity: 10, value: 2000, rule_id: nil>]}

2. Вы никогда не получите этого в Ruby {1=>[#<Sale id: 1, isbn_id: 2, quantity: 3000, rule_id: nil>]}, {2=>[#<Sale id: 6, isbn_id: 2, quantity: 10, value: 2000, rule_id: nil>]} . Вы можете вернуть массив хэшей, например: [{1=>[#<Sale id: 1, isbn_id: 2, quantity: 3000, rule_id: nil>]}, {2=>[#<Sale id: 6, isbn_id: 2, quantity: 10, value: 2000, rule_id: nil>]}] .

3. Спасибо, @fl00r. Не могли бы вы помочь мне вернуть массив хэшей, как вы правильно указали?

4. Я вернусь, когда перечитаю эту большую стопку книг, вот. Еще раз спасибо за вашу помощь!