2012-01-30 66 views
1

我正在编写一个ruby应用程序,可以代表用户向远程博客发表评论。我的问题是,我有在控制器的POST方法使用相同的页面,保持会话活着&填写验证码:通过请求边界保持机械化页面

应用程序/控制器/ comment_controller.rb

require 'mechanize' 
class CommentController < ApplicationController 
    def new 
     agent = Mechanize.new 
     @page = agent.get('http://blog.example.com') 
     @captcha_src = @page.search("//div[@id='recaptcha_image']").search("//img")[1].attribute("src") 
     #etc. 
    end 

    def post_comment 
     # insert captcha, username, password + text into the form 
     agent.submit(@page.form[0], @page.form[0].buttons.submitbutton) # Problem: page instance variable doesn't exist anymore 
    end 
end 

我已经尝试在Rails.cache中保存页面实例变量,但不能将机械化页面编组为字符串。

+0

这是一个轨道控制器吗?为什么你会认为@page会在请求之间持续存在?或代理人的事情?有一个'新'方法似乎是一个好主意?我认为你在这里错过了对ruby和/或rails的基本理解。 – pguardiario 2012-01-30 16:16:53

+0

@pguardiario:我不认为'@page'在请求之间持续存在,请参阅agent.submit行注释,这就是问题的核心。新方法是轨道生成(脚手架)。 – wintersolutions 2012-01-30 18:07:58

回答

0

我写了一个工作解决方案。它将隐藏变量和cookie保存在base64编码的字符串中,这些字符串在隐藏字段中的请求之间传输。下面继承代码:

require 'mechanize' 
require 'stringio' 
require 'base64' 

class MechanizeWrapper 
    attr_reader :page, :agent 

    def initialize(url, useproxy = true) 
    @agent = Mechanize.new 
    @page = @agent.get(url) 
    end 

    def get_state() 
    hidden_fields = {} 
    cookie_jar = StringIO.new 

    @page.search("//input[@type='hidden']").each do |hidden| 
     hidden_fields[hidden.path]=hidden.attribute('value').to_s 
    end 

    @agent.cookie_jar.dump_cookiestxt(cookie_jar); 

    state = {:hidden_fields => hidden_fields.inspect, :cookie_jar => cookie_jar.string} 
    Base64.encode64(state.inspect) 
    end 

    def put_state(state_enc) 
    state = eval(Base64.decode64(state_enc)) 
    eval(state[:hidden_fields]).each do |path,value| 
     @page.search(path).first['value'] = value 
    end  

    cookie_jar = StringIO.new(state[:cookie_jar]) 
    @agent.cookie_jar.load_cookiestxt(cookie_jar) 
    end 
end