3

I am looking to run a specific method inside my controller.rb file every minute. I am looking at using the whenever gem for rails but I am a bit confused on how to do this.

Currently in schedule.rb I have:

every 1.minutes do 
runner "Server.update_all_servers"
end

I am unsure exactly what the runner command does. Could someone explain what this command exactly does? From my understanding it calls a Model.ModelMethod but I need to call a method in application_controller.rb called update_all_servers(). Is it possible to do this? Or would I have to move whatever is inside my application_controller.rb to a model file (such as the one located in /models/server.rb)?

Rahul
  • 454
  • 1
  • 6
  • 18

2 Answers2

5

You can create a Server class in /lib:

class ServerUpdater
    attr_accessor :servers

    def initialize(servers = nil)
        @servers = servers || Server.all
    end

    def update_all
        servers.find_each { |server| server.update_info }
    end
end

Then you can call ServerUpdater.new(@servers).update_all in your controller.

In your cron job, you would call ServerUpdater.new(Server.all).update_all

And you would need an update_info method in your model that would contain the logic.

Robin
  • 21,667
  • 10
  • 62
  • 85
  • So created a Server.rb file, placed it into /lib, and created my method update_all_servers. Will this file be able to have access to the mysql database (ie. can I go: @servers.each do |server| Server.find(server.id).update_attributes(:hostname => hostname) end And then in my schedule.rb I put, every 1.minutes do runner "Server.update_all_servers" end This setup doesn't seem to be working for me. Am I doing something wrong? – Rahul Sep 06 '12 at 19:39
  • Yeah, you can access the database the same way you access it in your controllers, via your models. First, make sure your cron job really runs every minute, if it does, then check your logs to see if there are errors. (what's @servers?) – Robin Sep 06 '12 at 19:56
  • The log file isnt showing anything. The whenever gem is placing the following in the crontab: `* * * * * /bin/bash -l -c 'cd /home/ubuntu/statusboard && script/rails runner -e production '\''Server.update_all_servers'\'''` – Rahul Sep 06 '12 at 20:13
  • `@servers` was in my servers_controller.rb as `@servers = Server.all` – Rahul Sep 06 '12 at 20:16
  • What do you want to do in your update_all_servers method exactly? Where does the `hostname` come from? You can't use @servers in your class if you set it in your controller. You would have to initialize your class with the servers: Server.new(@servers).update_all_servers... – Robin Sep 06 '12 at 20:22
  • Basically update_all_servers will go to a specific website hosted by a specific server. It will retrieve certain attributes from that server's webpage such as the product version it is running, how many users it has, etc. Once it retrieves all this information, I need it to update the database. So basically it parses a webpage and then updates the database in the background. I need it to do this every few minutes so I can update the screen periodically with new server information. – Rahul Sep 06 '12 at 20:30
1

I had the same question and I solved it straight forward and didn't have to add anything in lib so I wanted to share:

In your case you want to call a controller action, all you do is have all your logic in the model method and that's best practice anyway. The runner can then simply call the model method:

every 1.minutes do 
  runner "Server.update_all_servers"
end

Server.update_all_servers has to be a method in your Server model and not a controller action.

Maher Manoubi
  • 585
  • 1
  • 6
  • 18