2012-11-20 3 views
1

J'ai une application où les utilisateurs peuvent parier entre eux et lorsque les résultats sont chargés dans l'application, j'utilise une tâche Rake pour régler les paris. Je cours sur Heroku alors j'utilise leur service Schedule pour cette tâche Rake toutes les demi-heures.Exécuter Rake Tâche sans utiliser Rake

Cela fonctionne très bien, mais j'aimerais beaucoup exécuter le travail Rake lorsque les résultats sont enregistrés/mis à jour dans la base de données.

Comment puis-je convertir la tâche Rake afin que je puisse l'exécuter à partir de mon modèle, ce qui pourrait ressembler à ce qui suit. Cela pourrait aussi être bien si je pouvais l'exécuter depuis les contrôleurs, car je pourrais avoir plusieurs situations où un processus de règlement est nécessaire.

class Spotprice < ActiveRecord::Base 
    belongs_to :spotarea 
    belongs_to :product 

    after_save :settlement 
end 

Ma tâche Rake ressemble à ce moment:

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 
+0

Vous pouvez simplement le mettre dans un fichier dans 'lib' et l'appeler quand vous en aurez besoin. Vous pourriez faire des choses délicates comme mettre en place des observateurs pour voir quand les modèles sont sauvegardés, et réagir en conséquence. Vous pouvez également utiliser PrivatePub pour envoyer des méthodes asynchrones à votre vue, par exemple pour alerter les utilisateurs. – MrDanA

+0

Salut .. J'ai juste l'impression que ce n'est pas la meilleure pratique pour exécuter Rake Tasks à partir de modèles, de contrôleurs etc .. qu'ils devraient seulement être appelés à partir d'une sorte de Cron. Ai-je eu la mauvaise impression :) – Twiddr

+0

Oh désolé, je ne me suis pas très bien expliqué. C'était ma faute. Ce que je voulais dire, c'est que vous pouviez retirer le code de la tâche rake et le placer dans une classe dans 'lib'. Vous n'auriez plus de tâche de rake.Le code serait juste une méthode ruby ​​régulière (loge juste dans 'lib' puisque ce n'est pas un modèle ou quoi que ce soit) et ensuite l'appelle depuis n'importe où. – MrDanA

Répondre

1

Il suffit de mettre mes commentaires de la question initiale dans une réponse.

J'ai eu une situation similaire où j'avais une tâche de rake que je voulais appeler de l'extérieur de rake. Ce que vous voulez faire est de déplacer le code de la tâche rake vers une classe ruby, le meilleur endroit pour cela serait lib. Votre classe ressemblerait à quelque chose comme ceci:

# lib/settlement.rb 
class Settlement 
    def self.settle_bets 
    # all the code that used to be in the rake task 
    end 
end 

Ensuite, dans le code que vous pouvez faire quelque chose comme ceci (exemple au hasard):

# app/controllers/bets_controller.rb 
#... 
    def settle_bets 
    require "settlement" 
    Settlement.settle_bets 
    end 
# ... 

Ou (un autre exemple au hasard):

# 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 

Et vous pouvez toujours utiliser la tâche de commission si vous le souhaitez:

# 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 
+0

Maintenant, cela ressemble à la façon de faire .. Je vais essayer et voir si je peux le faire fonctionner et obtenir retour à vous :) Merci! – Twiddr

+0

Parfait .. fonctionne exactement comme je le voulais .. merci beaucoup :) Passez une bonne journée! – Twiddr

+0

De rien! Et merci! – MrDanA

0

Si vous voulez que les résultats sont calculés lorsque vous mettez à jour (ou enregistrer), pourquoi ne pas déplacer la plupart du code de votre tâche de râteau dans un méthode de votre modèle Bet, puis appeler que vous appelez avec un rappel after_update

dans 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 

dans spot_price.rb

class SpotPrice 
    after_update Bet.settle(self) 
    after_save Bet.settle(self) 

    .... 
end 

Cela ne gère pas les choses Pusher notre autre sortie (qui est enregistré et est retourné dans la variable message). Aussi, je ne pouvais pas m'en empêcher, mais je supposais que vous vouliez dire "perdre", pas "perdre".

Est-ce ce que vous cherchez?

+0

Ca a du bon sens, mais j'ai plus d'une classe qui doit être réglée en une seule fois et je cours aussi une tâche qui classe les utilisateurs en fonction de leurs gains. Je voudrais garder le code recueilli en un seul endroit .. Merci pour la faute de frappe au fait :) – Twiddr

Questions connexes