2

我要先说我是一个相对初学者,虽然我可能还不太了解,但我非常愿意学习。我希望你能帮助解决这个问题,因为我已经尝试了很长时间,但仍然卡住了。我知道这是一个很长的问题——我不会把它扔在这里,除非我已经花了很多天的时间试图先自己弄清楚。

我正在使用 Mechanize 在我的 Rails 应用程序中运行一个脚本来填写几个网络表单。它在本地完美运行。但是,我需要使用delayed_job 才能在后台运行耗时的脚本。目前,我正在本地开发它(以前在 Heroku 上),直到问题得到解决。

所以我安装了delayed_job_active_record gem,并一直试图解决这个问题。我知道,虽然我的表单成功地接收了所有参数,但没有任何东西被插入到 SQL 表中。它没有获取对象的 ID。它不能识别对象的类(它认为它是 NilClass),所以它甚至认为常规的 Ruby 方法(例如 .strip)是未知的。(显示所有这些的控制台输出位于底部)。

我显然做错了什么。这很可能是一件非常明显的事情——但我还没有能力弄清楚这一点。如果你能帮我弄清楚我在这里做错了什么,我将永远感激你。

首先,这是我的代码:


模型:

require 'digest'
class Jumper < ActiveRecord::Base

after_save do |runscript|
  runscript.delay.scrape
end

validates :myuserid, :presence => true
validates :mypass, :presence => true
validates :mydate, :presence => true, :numericality => true
validates :mymonth, :presence => true, :numericality => true
validates :myyear, :presence => true, :numericality => true
validates :mylist, :presence => true

attr_accessor :myuserid, :mypass, :mydate, :mymonth, :myyear, :mylist

def scrape

 agent = Mechanize.new 

 page = agent.get('http://mywebsite.org/')

 myform = page.form_with(:name => 'signinForm')

 myuserid_field = myform.field_with(:name => "email")
 myuserid_field.value = myuserid  
 mypass_field = myform.field_with(:name => "password")
 mypass_field.value = mypass 

 page = agent.submit(myform, myform.buttons.first)

 mylistarray = mylist.strip.split(/[\s]+/)

 mylistfinal = mylistarray.map{|l| l[0..-5].sub(/(.*)\./,'\1').gsub('.','/')}.uniq

 mylistfinal.each do |doi|
  url ='http://mywebsite=' + doi + '&role=some_info#some_dates' 
  page = agent.get("http://mywebsite.org/submit")
  page = agent.get("#{url}") 

  entryform = page.form_with(:name => 'submit') 

  entryform.field_with(:name => 'month').options[("#{mymonth}").to_i].select
  entryform.field_with(:name => 'day').options[("#{mydate}").to_i].select
  entryform.field_with(:name => 'year').options[("#{myyear}").to_i].select

  page = agent.submit(entryform, entryform.button_with(:name => 'continue'))

    end
  end
end`  

控制器:

def index
  @doilists = Doilist.all

respond_to do |format|
  format.html # index.html.erb
  format.json { render json: @doilists }
 end
end

def show
 @doilist = Doilist.find(params[:id])

 respond_to do |format|
  format.html # show.html.erb
  format.json { render json: @doilist }
 end
end

def new
  @doilist = Doilist.new

 respond_to do |format|
   format.html # new.html.erb
   format.json { render json: @doilist }
 end
end

def create
@jumper = Jumper.new(params[:jumper])

  if @jumper.save
    flash[:notice] = "Sucessfully submitted your information."
    redirect_to @jumper
  else
    render :action => 'new'
  end
 end`

宝石文件:

source 'https://rubygems.org'

gem 'rails'

group :development do
  gem 'sqlite3', '1.3.5'
end

group :assets do
  gem 'sass-rails',   '~> 3.2.5'
  gem 'coffee-rails', '~> 3.2.2'
  gem 'uglifier', '>= 1.2.3'
end

gem 'jquery-rails', '2.0.2'
gem 'mechanize'

group :production do
  gem 'pg', '0.12.2'
end

gem 'delayed_job_active_record'
gem 'daemons'
gem 'thin'`

简介:

web: bundle exec rails server thin -p $PORT -e $RACK_ENV

worker:  bundle exec rake jobs:work`

脚本/延迟作业:

require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment'))
require 'delayed/command'
Delayed::Command.new(ARGV).daemonize

RAILS_ENV=production script/delayed_job start --exit-on-complete`

这是我在终端中运行 Foreman 时的输出:

11:33:30 web.1    | Started POST "/MyJumper" for 127.0.0.1 at 2013-05-02 11:33:29 -0400
11:33:30 web.1    |   Delayed::Backend::ActiveRecord::Job Load (1.2ms)  SELECT "delayed_jobs".* FROM "delayed_jobs" WHERE ((run_at <= '2013-05-02 15:33:30.437882' AND (locked_at IS NULL OR locked_at < '2013-05-02 11:33:30.438065') OR locked_by = 'delayed_job host:myroot pid:7081') AND failed_at IS NULL) ORDER BY priority ASC, run_at ASC LIMIT 5
1:33:30 web.1    | Processing by JumpersController#create as HTML
11:33:30 web.1    |   Parameters: {"utf8"=>"✓", "jumper"=>{"myuserid"=>"email@gmail.com", "mypass"=>"mypassword123”, "mylist"=>"listitem", "mymonth"=>"4", "mydate"=>"30", "myyear"=>"1"}, "commit"=>"Submit Your Entry"}
11:33:30 web.1    |    (0.1ms)  begin transaction
11:33:30 web.1    |   SQL (21.4ms)  INSERT INTO "jumpers" ("created_at", "mydate", "mylist", "mymonth", "mypass", "myuserid", "myyear", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["created_at", Thu, 02 May 2013 15:33:30 UTC +00:00], ["mydate", nil], ["mylist", nil], ["mymonth", nil], ["mypass", nil], ["myuserid", nil], ["myyear", nil], ["updated_at", Thu, 02 May 2013 15:33:30 UTC +00:00]]
11:33:30 web.1    |   SQL (0.5ms)  INSERT INTO "delayed_jobs" ("attempts", "created_at", "failed_at", "handler", "last_error", "locked_at", "locked_by", "priority", "queue", "run_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)  [["attempts", 0], ["created_at", Thu, 02 May 2013 15:33:30 UTC +00:00], ["failed_at", nil], ["handler", "--- !ruby/object:Delayed::PerformableMethod\nobject: !ruby/ActiveRecord:Jumper\n  attributes:\n    id: 68\n    mylist: \n    created_at: 2013-05-02 15:33:30.920857000 Z\n    updated_at: 2013-05-02 
15:33:30.920857000 Z\n    myuserid: \n    mypass: \n    mymonth: \n    mydate: \n    myyear: \nmethod_name: :scrape\nargs:\n- :jumper\n"], ["last_error", nil], ["locked_at", nil], ["locked_by", nil], ["priority", 0], ["queue", nil], ["run_at", Thu, 02 May 2013 15:33:30 UTC +00:00], ["updated_at", Thu, 02 May 2013 15:33:30 UTC +00:00]]
11:33:30 web.1    |    (10.7ms)  commit transaction
11:33:30 web.1    | Redirected to `http://mylocalhost:5000/MyJumper/68`
11:33:30 web.1    | Completed 302 Found in 74ms (ActiveRecord: 33.1ms)
11:33:31 web.1    | Started GET "/show/68" for 127.0.0.1 at 2013-05-02 11:33:30 -0400
11:33:31 web.1    | Processing by JumpersController#show as HTML
11:33:31 web.1    |   Parameters: {"id"=>"68"}
11:33:31 web.1    |   Jumper Load (0.3ms)  SELECT "jumpers".* FROM "jumpers" WHERE "jumpers"."id" = ? LIMIT 1  [["id", "68"]]
11:33:34 worker.1 | [Worker(host:myroot pid:10470)] Jumper#scrape failed with NoMethodError: undefined method `strip' for nil:NilClass - 0 failed attempts
11:33:34 worker.1 | [Worker(host:myroot pid:10470)] 1 jobs processed at 0.8520 j/s, 1 failed ...
4

2 回答 2

0

看起来你有一些未定义的。例如,在哪里 mymonth

当我在这里时,我想给你一个简化代码的提示:

代替:

myuserid_field = myform.field_with(:name => "MSTRServlet.email")
myuserid_field.value = myuserid  

试试:

myform['MSTRServlet.email'] = myuserid  

这不太可能解决你的问题,但也许它会让你更接近一些简单到可以解决的问题。

最后,我知道 Heroku 是当前媒体的宠儿,但您应该考虑到它可能不是最适合您的特定项目的。

于 2013-05-03T09:54:42.473 回答
0

感谢您的建议。我最终想出了如何自己解决这个问题。问题显然是 Delayed_Jobattr_accessor在 Rails 3 中存在重大问题。

这里有更多信息: delayed_job:从rails 2升级后,属性访问器值不存储在rails 3中的delayed_jobs表中

在这里: YAML,delayed_job:Psych vs Syck。如何让 pysch 读取 ruby​​ 对象的 attr_accessors

此处解释了此问题的解决方法: https ://gist.github.com/jrafanie/3011499

简单地删除attr_accessor我的模型的一部分后,一切正常。终于解脱了!

另外:在我的控制器保存我的对象之后,我after_save从我的模型中删除了代码并简单地添加到我的控制器中。@jumper.delay.scrape这可能不是必需的,但它与文档更一致:

if @jumper.save
    @jumper.delay.scrape 
    flash[:notice] = "Currently sending your info"
    redirect_to start_index_path 

随着我进入生产阶段,我将进一步检查解决方法并查看我的项目的最佳方法,以便我可以在我的模型中使用 attr_accessor。但是现在,很高兴有这个工作!

于 2013-05-06T19:08:56.340 回答