Rails 3:使用数组的内容作为 where 方法中的变量
我有三个模型:Isbn、Sale 和 Channel。
目标:在 isbns show.html.erb 视图中获取如下所示的列表:
Isbn: myisbn
myisbn 的总销售额:100
渠道 1 的 Myisbn 销售额:50
渠道 2 的 Myisbn 销售额:25
渠道 3 的 Myisbn 销售额: 25
这是我的模型。 Isbn.rb 模型
has_many :sales
has_many :channels, :through => :sales
Sale.rb 模型(具有属性 sales_channel_id、isbn_id、数量)
has_many :channels
belongs_to :isbn
Channel.rb 模型:
belongs_to :sale
我一直在 isbns 控制器的 show 方法中工作,只是为了让某些东西发挥作用。我想我稍后会重构 - 关于这些东西是否应该放入模型中的建议将是最受欢迎的。
到目前为止,我已经得到了:
@channelisbn = Sale.where("sales_channel_id =?',1).where("isbn_id=?",3)
@channelsalesisbn = 0
@channelisbn.each {|y| @channelsalesisbn =+ y.quantity}
这成功地获取了频道 ID 为 1 且 ISBN id 为 3 的所有销售。但这没有多大用处,因为 ID 是硬编码的。所以我将通道 ID 放入一个数组中:
@channellist = Channel.all
@channel = 0
@channelarray = @channellist.map {|z| @channel = z.id}
这给了我一个可爱的 [1,2,3,4] 数组
,但我不知道如何传递 1,然后是 2,然后是 3,然后是 4到一个块中,该块可用于查找具有该销售渠道 ID 的 ISBN 销售。这就是我尝试过的(仍然对 ISBN id 进行硬编码 - 以为我会一次解决一个问题),它返回一个空数组:
@channelarray.each do |channel|
@channelisbn = []
@channelisbn = Sale.where("sales_channel_id = ?", channel).where("isbn_id = ?",3)
@channelsalesisbn = 0
@result = []
@result << @channelisbn.each {|a| @channelsalesisbn =+ a.quantity}
end
然后我将对数组的内容求和。
任何帮助将不胜感激。这是我的第一篇文章,所以我的零接受率很快就会改变!
更新
为了结束这个问题,这就是我最终的结果,这很棒,并且准备好进行修改:一个数组,很好地分组,按渠道给我提供了 isbn 的销售额。感谢 group_by 的提示!
#in the show action in the isbns controller:
@isbn = Isbn.find(params[:id])
@channelarray = Channel.select(:id).all
@channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", @isbn)}
在控制台中,为了清晰起见,添加了换行符:(
首先偷偷地设置@isbn = 3,因为在控制台中你无法从视图传递参数,所以控制器中定义的@isbn实例在控制台中为零)
ruby-1.9.2-p180 :067 > @channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", @isbn)}
=> {[#<Sale id: 1, isbn_id: 3, quantity: 10000, value: 12000, currency: "GBP", total_quantity: nil, created_at: "2011-05-06 12:30:35", updated_at: "2011-05-07 17:43:13", customer: "Waterstone's", retail_price: nil, discount: nil, invoice_date: "2011-05-24">, #<Sale id: 2, isbn_id: 3, quantity: 1000, value: 500, currency: "GBP", total_quantity: nil, created_at: "2011-05-07 09:37:53", updated_at: "2011-05-07 19:14:52", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-02-05">]=>[#<Channel id: 1>],
[#<Sale id: 3, isbn_id: 3, quantity: 500, value: 1500, currency: "", total_quantity: nil, created_at: "2011-05-07 09:38:11", updated_at: "2011-05-07 19:15:07", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-12-05">, #<Sale id: 4, isbn_id: 3, quantity: 45, value: 300, currency: "", total_quantity: nil, created_at: "2011-05-07 09:38:38", updated_at: "2011-05-07 19:15:36", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-06-05">]=>[#<Channel id: 2>],
[]=>[#<Channel id: 3>],
[]=>[#<Channel id: 4>]}
更新2
哈,我生成的散列的键值对是错误的。包含销售数据的数组是键 - 它应该是值。 Rubydocs 挽救了局面:
@salesbychannel = @salesbychannelwrong.invert
invert
方法切换键值对。甜的。
I have three models: Isbn, Sale and Channel.
Aim: to get a list in the isbns show.html.erb view which looks something like this:
Isbn: myisbn
Total sales for myisbn: 100
Myisbn sales for channel 1: 50
Myisbn sales for channel 2: 25
Myisbn sales for channel 3: 25
Here are my models.
Isbn.rb model
has_many :sales
has_many :channels, :through => :sales
Sale.rb model (has attributes sales_channel_id, isbn_id, quantity)
has_many :channels
belongs_to :isbn
Channel.rb model:
belongs_to :sale
I've been working in the isbns controller, in the show method, just to get something to work. I thought I'd refactor later - advice on whether any of this stuff should go in the model would be most welcome.
So far I've got this:
@channelisbn = Sale.where("sales_channel_id =?',1).where("isbn_id=?",3)
@channelsalesisbn = 0
@channelisbn.each {|y| @channelsalesisbn =+ y.quantity}
This successfully gets all the sales where Channel ID is 1 and ISBN id is 3. But it's not much use, as the IDs are hard coded. So I got the Channel IDs into an array:
@channellist = Channel.all
@channel = 0
@channelarray = @channellist.map {|z| @channel = z.id}
which gives me a lovely array of [1,2,3,4]
But I can't figure out how to pass the 1, then the 2, then the 3 and then the 4 into a block which can be used to look up an ISBN's sales which have that sales channel id. This is what I tried (still hardcoding the ISBN id - thought I'd tackle one problem at a time), which returned an empty array:
@channelarray.each do |channel|
@channelisbn = []
@channelisbn = Sale.where("sales_channel_id = ?", channel).where("isbn_id = ?",3)
@channelsalesisbn = 0
@result = []
@result << @channelisbn.each {|a| @channelsalesisbn =+ a.quantity}
end
I was then going to sum the contents of the array.
Any help would be gratefully received. This is my first post, so my zero acceptance rate will change soon!
UPDATE
Just to finish this question off, here's where I've ended up, which is great, and ready for tinkering with: an array, nicely grouped, giving me sales by isbn by channel. Thanks for the group_by tip off!
#in the show action in the isbns controller:
@isbn = Isbn.find(params[:id])
@channelarray = Channel.select(:id).all
@channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", @isbn)}
From the console, line breaks added for clarity:
(sneakily set @isbn = 3 first of all, since in the console you can't pass params from a view, so the @isbn instance defined in the controller is nil in the console)
ruby-1.9.2-p180 :067 > @channelarray.group_by {|i| Sale.where("channel_id = ?",i).where("isbn_id =?", @isbn)}
=> {[#<Sale id: 1, isbn_id: 3, quantity: 10000, value: 12000, currency: "GBP", total_quantity: nil, created_at: "2011-05-06 12:30:35", updated_at: "2011-05-07 17:43:13", customer: "Waterstone's", retail_price: nil, discount: nil, invoice_date: "2011-05-24">, #<Sale id: 2, isbn_id: 3, quantity: 1000, value: 500, currency: "GBP", total_quantity: nil, created_at: "2011-05-07 09:37:53", updated_at: "2011-05-07 19:14:52", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-02-05">]=>[#<Channel id: 1>],
[#<Sale id: 3, isbn_id: 3, quantity: 500, value: 1500, currency: "", total_quantity: nil, created_at: "2011-05-07 09:38:11", updated_at: "2011-05-07 19:15:07", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-12-05">, #<Sale id: 4, isbn_id: 3, quantity: 45, value: 300, currency: "", total_quantity: nil, created_at: "2011-05-07 09:38:38", updated_at: "2011-05-07 19:15:36", customer: "Borders", retail_price: nil, discount: nil, invoice_date: "2011-06-05">]=>[#<Channel id: 2>],
[]=>[#<Channel id: 3>],
[]=>[#<Channel id: 4>]}
UPDATE 2
Ha, the hash I generated had the key value pairs the wrong way round. The array containing the sales data was the key - it should have been the value. Rubydocs saved the day:
@salesbychannel = @salesbychannelwrong.invert
The invert
method switches the key-value pairs. Sweet.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您正在寻找的是将数组传递给 ARel#where(),如下所示:
这应该执行 IN 查询。如果这不起作用,您可以随时将数组传递给 ActiveRecord#find,如下所示:
希望这有帮助
What you're looking for is passing an array to a ARel#where(), like this:
This should execute an IN query. If that's not working, you can always pass the array to ActiveRecord#find, like this:
Hope this helps