following situation (ror 3, ruby 1.9).
i've got a model with some fields.
now i want to grab a json feed (f.e. every hour) compare the content with my stored model objects and put in a new model object if there is a new item in this json feed.
i'm not shure where to put this automated action. i don't think doing this in a models method is the right place, am i right?
where would you do this migration开发者_运维百科 actions? in a controller? not really i think.
thankful for all hints
Ignore controllers completely for this. Models serve as an abstraction layer for accessing data. In your case, you have some locally persisted data in the form of a database, and you have remote data you're retrieving as JSON over HTTP. So you have your regular ActiveRecord models, and you have a model for your JSON data.
Let's assume you have a model called RemoteData that fetches a JSON document and has some methods for you to cleanly get data from it. You also have a StoredData model that keeps retrieved content in your database to be displayed later.
Now, you want to automate the process of calling RemoteData.fetch('url')
and then calling StoredData.create :params
on the returned data. To do that, you would create a "rake task". Here's an example:
# lib/tasks/fetch.rake
desc "Fetch remote data and persist it"
task :fetch => :environment do
RemoteData.fetch('url').each do |json_data|
sd = StoredData.create :url => 'url', :data => json_data
puts "Retrieved 'url' and saved data in record ##{sd.id} at #{DateTime.now}."
end
end
Then you would set your system crontab up to run that as frequent as you would like. The Rake task handles the business logic, and your models handle interacting with the data. Nice and clean.
You should put the business logic in the model and the action login in a rake task, I consider this is the usual strategic for this automated tasks. Your cron should look like:
cd /path/to/web_app && RAILS_ENV=environment /usr/local/bin/rake namespace:task
I would put code of grabbing a json feed in model related with data from feed. You can write tests for grab_feed method and be sure that it works properly. For example if you want to scrap posts I would do something like this:
class Post < ActiveRecord
def self.grab_feed
(...)
end
end
Then you can use whenever: https://github.com/javan/whenever to check this content every hour:
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
runner "Post.grab_feed"
end
You shouldn't use controller, because you want grabbing feed be internal part of application. Also you don't want to have view for that so definitely isn't controller job, but model.
The question here is: do you feel this JSON is a view or just "data representation"? If you consider the former, you need a usual controller; if you feel it's data, then you could write a rake task and call the method (something like: puts Model.scope1.scope2.to_json
)
You should keep batch jobs like data processing and populating from main serving web-app. Write a ruby script/rake script and run it from cron.
Model or controllers are not right places.
Following is some sample code to write scripts which accesses models of a app.
require 'rubygems'
require 'active_record'
$config = YAML.load_file(File.dirname(__FILE__) + '/../green_app/config/'+ 'database.yml')
ActiveRecord::Base.establish_connection( $config[ENV['RAILS_ENV']] )
require File.expand_path File.dirname(__FILE__) + '/../green_app/app/models/post.rb'
and run it as
export RAILS_ENV="production" && ruby /path/to/your/script.rb
change RAILS_ENV value depending on your environment.
Why don't you want to put this in a controller? At last, it is just another action, driven by an automated user in this case (cron). I would do a POST request, triggered every hour to fetch this news feed and create entries if necessary.
精彩评论