2013-06-20 132 views
0

創建範圍,也許是這樣的..計算百分比和顯示虛擬屬性(軌道/活動記錄)

scope :mv, select('*,quantity*market_price as market_value, quantity*market_price/sum(quantity*market_price) as percent') 

創建兩個虛擬屬性,market_value和百分比。我遇到的問題是創建包含sum()的百分比。如果我添加sum(),範圍將返回一條記錄。

我需要計算market_value相對於範圍記錄集的總市場價值的百分比。

例如:

1, market_value: 100, percent: .10 
2, market_value: 100, percent: .10 
3, market_value: 100, percent: .10 
4, market_value: 100, percent: .10 
5, market_value: 100, percent: .10 
6, market_value: 500, percent: .50 
Total is 1000 

但是,如果我是範圍到market_value < 6,我應該看到

1, market_value: 100, percent: .20 
2, market_value: 100, percent: .20 
3, market_value: 100, percent: .20 
4, market_value: 100, percent: .20 
5, market_value: 100, percent: .20 
Total 500 

我怎樣才能做到這一點?

我創建了一個self.pct方法,但self.pct方法的問題在於它需要在所有範圍之後運行。如果rescoped,解決的辦法是錯誤的

到目前爲止,

class Position < ActiveRecord::Base 
    attr_accessible :account_id, :account_type, :market_price, :quantity, :report_date, :symbol 

    scope :long_only, where(:account_type => 'L') 
    scope :short_only, where(:account_type=>"S") 
    scope :equity_only, :conditions => ["symbol <> 'USD'"] 

scope :mv, select('*,quantity*market_price as market_value, quantity*market_price/sum(quantity*market_price) as percent') 

scope :mv1, lambda{|total| select(total) } 

    #the problem with the self.pct method is that it needs to be run after all the scopes. if rescoped, the solution is wrong 

def self.pct 
    string="*,(quantity*market_price) as market_value, (market_price*quantity/#{sum_market_value}) as percent" 
    mv1(string) 
end 


    def market_value 
    self.market_price*self.quantity 
    end 


    def self.sum_market_value 
    sum('quantity*market_price') 
    end 
end 

回答

0

我不知道是否有一種方法在單個查詢做到這一點,但我們可以在兩個查詢得到它:

require 'active_record' 

ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:' 

ActiveRecord::Schema.define do 
    self.verbose = false 
    create_table :positions do |t| 
    t.integer :quantity 
    t.integer :market_price 
    end 
end 

class Position < ActiveRecord::Base 
    def self.with_market_value 
    select "*, 
      quantity*market_price as market_value, 
      quantity*market_price/#{total.to_f} as percent" 
    end 

    def self.total 
    select('sum(quantity*market_price) as sum_of_market_values').first.sum_of_market_values 
    end 
end 

Position.create! quantity: 25, market_price: 4 
Position.create! quantity: 25, market_price: 4 
Position.create! quantity: 25, market_price: 4 
Position.create! quantity: 25, market_price: 4 
Position.create! quantity: 25, market_price: 4 
Position.create! quantity: 25, market_price: 20 

Position.with_market_value.map { |p| [p.market_value, p.percent] } 
# => [[100, 0.1], [100, 0.1], [100, 0.1], [100, 0.1], [100, 0.1], [500, 0.5]] 

Position.where('market_price < 10').with_market_value.map { |p| [p.market_value, p.percent] } 
# => [[100, 0.2], [100, 0.2], [100, 0.2], [100, 0.2], [100, 0.2]] 

# ** NOTE THAT IT EXECUTES EAGERLY ** 
Position.with_market_value.where('market_price < 10').map { |p| [p.market_value, p.percent] } 
# => [[100, 0.1], [100, 0.1], [100, 0.1], [100, 0.1], [100, 0.1]]