Reputation: 297
I have an app where users can bet each other and when the result are loaded into the app I use a Rake task to settle the bets. I'm running on Heroku so I'm using their Schedule service for this Rake task every half hour.
This works fine, but I would much more like to run the Rake job when the results are saved/updated in the database.
How do I convert the Rake task so I can run it from my model, which could look like the below. It could also be nice if I could run it from the controllers, since I might have several situations where a settlement process is needed.
class Spotprice < ActiveRecord::Base
belongs_to :spotarea
belongs_to :product
after_save :settlement
end
My Rake task looks like this right now:
task :settlement => :environment do
puts "Settlement in progress..."
puts "-------------------------"
puts " "
puts " "
puts "BETS:"
puts "-------------------------"
# Bet settlement
@bets = Bet.where(:settled => false)
@bets.find_each do |bet|
if not bet.choice.spotprice.nil?
case
when bet.choice.spotprice.value > bet.choice.value && bet.buy == true
profitloss = 10
puts "#{bet.id}: Win (1)"
when bet.choice.spotprice.value < bet.choice.value && bet.buy == false
profitloss = 10
puts "#{bet.id}: Win (2)"
when bet.choice.spotprice.value > bet.choice.value && bet.buy == false
profitloss = -10
puts "#{bet.id}: Loose (3)"
when bet.choice.spotprice.value < bet.choice.value && bet.buy == true
profitloss = -10
puts "#{bet.id}: Loose (4)"
when bet.choice.spotprice.value == bet.choice.value
profitloss = -10
puts "#{bet.id}: Loose (5)"
end
if profitloss
bet.settled = true
bet.profitloss = profitloss
bet.save
end
end
if bet.choice.settled == true
bet.choice.settled = false
bet.choice.save
end
end
# Pusher update
Pusher["actives"].trigger("updated", {:message => "Settlement completed"}.to_json)
end
Upvotes: 1
Views: 379
Reputation: 11647
Just putting my comments from the original question in to an answer.
I had a similar situation where I had a rake task that I wanted to call from outside of rake. What you want to do is move the code from the rake task in to a ruby class, the best place for this would be in lib
. Your class would look something like this:
# lib/settlement.rb
class Settlement
def self.settle_bets
# all the code that used to be in the rake task
end
end
Then in code you can do something like this (random example):
# app/controllers/bets_controller.rb
#...
def settle_bets
require "settlement"
Settlement.settle_bets
end
# ...
Or (another random example):
# app/models/bet.rb
class Bet ...
after_update: update_some_bets
# ... more code here
private
def update_some_bets
require "settlement"
Settlement.settle_bets
end
And you could still use the rake task if you wanted:
# lib/tasks/settlement.task
require "settlement"
# require "#{Rails.root}/lib/settlement.rb" # use this if the above won't work
task :settlement => :environment do
Settlement.settle_bets
end
Upvotes: 1
Reputation: 14068
If you want the results calculated when you update (or save), why not move most of the code from your rake task into a method of your Bet model, then call it which you call with an after_update
callback
in bet.rb
# class method that settles the given bet
def self.settle(bet)
message = nil
if not bet.choice.spotprice.nil?
case
when bet.choice.spotprice.value > bet.choice.value && bet.buy == true
profitloss = 10
message = "#{bet.id}: Win (1)"
when bet.choice.spotprice.value < bet.choice.value && bet.buy == false
profitloss = 10
message = "#{bet.id}: Win (2)"
when bet.choice.spotprice.value > bet.choice.value && bet.buy == false
profitloss = -10
message = "#{bet.id}: Lose (3)"
when bet.choice.spotprice.value < bet.choice.value && bet.buy == true
profitloss = -10
message = "#{bet.id}: Lose (4)"
when bet.choice.spotprice.value == bet.choice.value
profitloss = -10
message = "#{bet.id}: Lose (5)"
end
if profitloss
bet.settled = true
bet.profitloss = profitloss
bet.save
end
end
if bet.choice.settled == true
bet.choice.settled = false
bet.choice.save
end
# return message
message
end
in spot_price.rb
class SpotPrice
after_update Bet.settle(self)
after_save Bet.settle(self)
....
end
This doesn't handle the Pusher stuff our other output (which is saved and returned in the message
variable). Also, couldn't help myself, but I assumed you mean "Lose", not "Loose".
Is this what you're looking for?
Upvotes: 0