1

Im writing a ruby application that can post comments on behalf of the user to a remote blog. My problem is that i have to use the same page in the post method of the controller, to keep the session alive & to fill out a captcha:

app/controller/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

I've already tried to save the page-instance-variable in Rails.cache but mechanized pages can't be marshalled to string.

wintersolutions
  • 5,173
  • 5
  • 30
  • 51
  • Is this a rails controller? Why would you think @page would persist between requests? or agent for that matter? Does it seem like a good idea to have a 'new' method? I think you're missing some fundamental understanding of ruby and/or rails here. – pguardiario Jan 30 '12 at 16:16
  • @pguardiario: I don't think that '@page' persists between requests, see the agent.submit line-comment, thats the core of the problem. The new-Method is rails generated (scaffolding). – wintersolutions Jan 30 '12 at 18:07

1 Answers1

0

I wrote a working solution. It saves the hidden-variables and the cookies in a base64 encoded string which iam transferring between requests in a hidden field. Heres the code to build upon:

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
wintersolutions
  • 5,173
  • 5
  • 30
  • 51