开发者

Does system "...&" still work on Heroku Cedar / Rails 3.1?

I have a couple of rake tasks run in the background using RyanB's technique from Railscast 127, which work fine locally and on Rails 3, but not on 3.1 in production on Heroku's cedar stack. Before I rip them out and replace them with delayed_job, should this method of forking a process still work?

  def call_rake(task, options = {})
    options[:rails_env] ||= Rails开发者_JAVA技巧.env
    args = options.map { |n, v| "#{n.to_s.upcase}='#{v}'" }
    system "rake #{task} #{args.join(' ')} --trace 2>&1 >> #{Rails.root}/log/rake.log &"
  end


Answering this myself, after digging around: the system bit does but not the &. Delayed_job is the way to go on this. FWIW here's my working code to run a rake task in a rails 3.1 app using delayed_job on Heroku's Cedar stack, to generate an XML file, save it to temp then upload to S3. The XML output file is large, hence the need to handle it asynchronously.

app/classes/callrake.rb:

class Callrake
  def call_rake(task, options = {})
      options[:rails_env] ||= Rails.env
      args = options.map { |n, v| "#{n.to_s.upcase}='#{v}'" }
      system "rake #{task} #{args.join(' ')} --trace 2>&1 >> #{Rails.root}/log/rake.log"

    end
  handle_asynchronously :call_rake
end

isbns controller:

def onixtwo 
#using Ransack, successor to Metasearch
  @q = Isbn.where(:client_id => current_user.client_id).search(params[:q])
   @isbns = @q.result(:distinct => true)
  if @q.nil? 
     @isbns = Isbn.where(:client_id => current_user.client_id)
  end
  #I have an array to pass so this is a bit hacky - make an array, pass it as a string then turn it back into an array using eval()
  is = []
  @isbns_to_pass = @isbns.each {|isbn| is << isbn.id }
  @client = current_user.client_id   
  @user = current_user.id
  callrake = Callrake.new
  callrake.call_rake(:onixtwo, :isbns => is, :client => @client, :user => @user)
  redirect_to isbns_path, :flash => { :notice => t(:isbnonixtwo).html_safe }

end

slightly off-topic config/locales/en.yml for completeness:

en:
  isbnonixtwo: "Onix 2.1 message is generating. When it's done, you can download it from the <a href='/onixarchives'>Onix Archive</a> list."

rake task:

desc "Generate an onix 2.1 xml file"
task :onixtwo => :environment do |t|


  client_id = ENV["CLIENT"]
  user_id = ENV["USER"]
  isbns_passed = ENV["ISBNS"]
  isbnsarray = eval(isbns_passed)
  filename = "#{Rails.root}/public/#{Client.find_by_id(client_id).client_name}-#{Date.today}-#{Time.now}-onix-21.xml"    
  isbns = Isbn.find_all_by_id(isbnsarray)

 File.open(filename, "w") do |file|

    xml = Builder::XmlMarkup.new(:target => file, :indent => 2)
    xml.instruct!(:xml, :version => "1.0", :encoding => "utf-8")
    xml.declare! :DOCTYPE, :ONIXMessage, :SYSTEM, "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
    xml.ONIXMessage do
      xml.Header do 
#masses of code

  end  #of file 
  xmlfile = File.open(filename, "r")
  onx = Onixarchive.new(:client_id => client_id, :user_id => user_id) 
  onx.xml = xmlfile
  onx.save!
  end #of task

Then Onixarchive has a regular paperclip attachment set-up in the model.

Note the Rails.root.public in the filepath - I kept getting a "does not exist" when I tried to write to app/tmp, because, sure enough when I looked using heroku's console, there is no tmp folder. I suppose I could have created one, but this app is on cedar, which has an ephemeral filesystem so you can write anywhere for the duration of the session.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜