在 Rails 3 中创建哈希
我掌握了一种计算 ISBN 版税的方法。它按销售渠道划分销售额。特许权使用费率由销售总量决定,特许权使用费的计算方法是特许权使用费率(百分比)乘以总收入。因此,结果应该是每个 ISBN 的每个销售渠道的计算版税数字。原谅可能被过度注释的代码。
在 isbns_controller 的 show 方法中:
@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(&: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(&:value)
quantity_total_by_channel = sale_array.sum(&: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
最后一行给我带来了问题。我想要的是生成一个哈希值,其中通道 ID 作为键,计算出的版税作为值。但相反,它只生成一个只有一个键值对的散列,看起来像这样:
{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(&:channel_id)
生成的哈希仅包含一个键值对。所以我的问题仍然存在,但对于我的代码的不同部分:如何在 Sales 模型上执行查找以生成像 {1 =>;销售 1,销售 2},{2 =>销售 1,销售 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(&:channel_id)
返回nil
并且
Sale.find_by_isbn_id(@isbn).group_by(&: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
再次感谢。
I have the makings of a method which calculates royalties for ISBNs. It splits sales by sales channel. The royalty rate is determined by the total quantity sold, and the royalty is calculated by multiplying the royalty rate (a percentage) by the total revenue. So the result should be a calculated royalty figure for each sales channel, for each isbn. Forgive what is probably over-commented code.
In the show method of the 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(&: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(&:value)
quantity_total_by_channel = sale_array.sum(&: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
It's that last line which is giving me a problem. What I want is to produce a hash with the channel ids as the keys, and the calculated royalties as the values. But instead, it's producing a hash with just one key-value pair, in something which looks like this:
{1=>#<BigDecimal:10132a620,'0.875E5',9(36)>}
I suspect there's something wrong with the way I'm creating a new hash at the top of the method, and also with trying to declare the key in the square brackets.
The rule.rate
is a percentage expressed as a decimal, e.g. 0.10. The value is an integer (at the moment, at least). Any thoughts on how to generate this hash?
Secondly, what's the best way to iterate through the resultant hash in the view?
Many thanks in advance.
Update - output of .inspect as requested:
{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>]}
Second update: revision to the question:
Thanks for your thoughts so far. It turns out the method is working fine, because the hash generated by @isbn.sales.group_by(&:channel_id)
only contains one key-value pair. So my question still stands, but for a different bit of my code: how do I perform a find on the Sales model to produce an array of hashes like {1 => sale 1, sale 2}, {2 => sale 1, sale 2}
?
I have tried this horrible thing:
@channelarray = Channel.select(:id).all
@salesbychannelwrong = @channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", @isbn)}
@salesbychannel = @salesbychannelwrong.invert
which gives this:
{[#<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>]}
I have also tried
Sale.find_by_isbn_id(:id).group_by(&:channel_id)
which returns nil
and this
Sale.find_by_isbn_id(@isbn).group_by(&:channel_id)
which returns
undefined method `group_by' for #<Sale:0x0000010122df60>
I have the following models:
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
Thanks again.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Sale.find_by_isbn_id(@isbn).group_by(&:channel_id)
=>;Sale.find_all_by_isbn_id(@isbn).group_by(&:channel_id)
或
Sale.find_by_isbn_id(@isbn).group_by(&:channel_id)
=>Sale.find_all_by_isbn_id(@isbn).group_by(&:channel_id)
or