houdini 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -1
 - data/Gemfile.lock +97 -88
 - data/README.markdown +31 -27
 - data/app/controllers/houdini/postbacks_controller.rb +7 -9
 - data/config/routes.rb +2 -2
 - data/houdini.gemspec +3 -2
 - data/lib/houdini.rb +35 -7
 - data/lib/houdini/model.rb +14 -49
 - data/lib/houdini/postback_processor.rb +21 -0
 - data/lib/houdini/task.rb +46 -10
 - data/lib/houdini/task_manager.rb +20 -0
 - data/lib/houdini/version.rb +1 -1
 - data/spec/dummy/app/models/article.rb +12 -14
 - data/spec/houdini/model_spec.rb +27 -0
 - data/spec/houdini/postback_processor_spec.rb +44 -0
 - data/spec/houdini/task_manager_spec.rb +26 -0
 - data/spec/houdini/task_spec.rb +136 -0
 - data/spec/houdini_spec.rb +25 -0
 - data/spec/requests/integration_spec.rb +21 -19
 - data/spec/spec_helper.rb +3 -3
 - metadata +76 -118
 - data/lib/houdini/base.rb +0 -35
 - data/spec/controllers/houdini/postbacks_controller_spec.rb +0 -0
 - data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
 - data/spec/dummy/config/initializers/inflections.rb +0 -10
 - data/spec/dummy/config/initializers/mime_types.rb +0 -5
 - data/spec/dummy/public/404.html +0 -26
 - data/spec/dummy/public/422.html +0 -26
 - data/spec/dummy/public/500.html +0 -26
 - data/spec/dummy/public/favicon.ico +0 -0
 - data/spec/dummy/public/javascripts/application.js +0 -2
 - data/spec/dummy/public/javascripts/controls.js +0 -965
 - data/spec/dummy/public/javascripts/dragdrop.js +0 -974
 - data/spec/dummy/public/javascripts/effects.js +0 -1123
 - data/spec/dummy/public/javascripts/prototype.js +0 -6001
 - data/spec/dummy/public/javascripts/rails.js +0 -175
 - data/spec/dummy/public/stylesheets/.gitkeep +0 -0
 - data/spec/houdini_rails_spec.rb +0 -4
 
| 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Houdini
         
     | 
| 
      
 2 
     | 
    
         
            +
              module PostbackProcessor
         
     | 
| 
      
 3 
     | 
    
         
            +
                EnvironmentMismatchError = Class.new RuntimeError
         
     | 
| 
      
 4 
     | 
    
         
            +
                APIKeyMistmatchError     = Class.new RuntimeError
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def self.process(class_name, model_id, params)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  task_manager = params.delete(:task_manager) || TaskManager
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  if params[:environment] != Houdini.environment
         
     | 
| 
      
 10 
     | 
    
         
            +
                    raise EnvironmentMismatchError, "Environment received does not match Houdini.environment"
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            			# # Houdini doesn't send the API key back
         
     | 
| 
      
 14 
     | 
    
         
            +
                  # if params[:api_key] != Houdini.api_key and params[:environment] == "production"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  #   raise APIKeyMistmatchError, "API key received doesn't match our API key."
         
     | 
| 
      
 16 
     | 
    
         
            +
                  # end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  task_manager.process class_name, model_id, params[:blueprint], params[:output], params[:verbose_output]
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/houdini/task.rb
    CHANGED
    
    | 
         @@ -1,15 +1,51 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Houdini
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Task
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                  @ 
     | 
| 
       8 
     | 
    
         
            -
                  @ 
     | 
| 
       9 
     | 
    
         
            -
                  @ 
     | 
| 
       10 
     | 
    
         
            -
                  @ 
     | 
| 
       11 
     | 
    
         
            -
                  @ 
     | 
| 
       12 
     | 
    
         
            -
                  @ 
     | 
| 
      
 3 
     | 
    
         
            +
                attr :options
         
     | 
| 
      
 4 
     | 
    
         
            +
                protected :options
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(klass, blueprint, options={})
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @class_name         = klass.name
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @blueprint          = blueprint.to_s
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @input              = options[:input]
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @after_submit       = options[:after_submit]
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @on_task_completion = options[:on_task_completion]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @finder             = options[:finder] || :find
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @id_method          = options[:id_method] || :id
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def process(object_id, results, verbose_results)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  # we have to re-constantize the class name because Rails reloads the classes in development
         
     | 
| 
      
 18 
     | 
    
         
            +
                  obj = self.class.callable @class_name.constantize, @finder, object_id
         
     | 
| 
      
 19 
     | 
    
         
            +
                  self.class.callable obj, @on_task_completion, results, verbose_results  if @on_task_completion
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def submit!(object, options={})
         
     | 
| 
      
 23 
     | 
    
         
            +
                  get_input   = options[:input_transformer] || self.class.method(:get_input)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  submit_task = options[:submit_task]       || Houdini.method(:submit!)
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  id = self.class.callable object, @id_method
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  submit_task.call @blueprint, object.class.name, id, get_input.call(object, @input)
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  self.class.callable(object, @after_submit) if @after_submit
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def self.get_input(object, input)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  input.inject({}) do |hash, (info_name, model_attribute)|
         
     | 
| 
      
 35 
     | 
    
         
            +
                    hash.merge info_name => callable(object, model_attribute){ model_attribute }
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def self.callable(object, callable, *args)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  if callable.is_a? Symbol
         
     | 
| 
      
 41 
     | 
    
         
            +
                    object.send callable, *args
         
     | 
| 
      
 42 
     | 
    
         
            +
                  elsif callable.respond_to? :call
         
     | 
| 
      
 43 
     | 
    
         
            +
                    object.instance_exec *args, &callable
         
     | 
| 
      
 44 
     | 
    
         
            +
                  elsif block_given?
         
     | 
| 
      
 45 
     | 
    
         
            +
                    yield callable, *args
         
     | 
| 
      
 46 
     | 
    
         
            +
                  else
         
     | 
| 
      
 47 
     | 
    
         
            +
                    raise "#{callable.inspect} is not a Symbol and does not respond to #call"
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
       13 
49 
     | 
    
         
             
                end
         
     | 
| 
       14 
50 
     | 
    
         
             
              end
         
     | 
| 
       15 
51 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Houdini
         
     | 
| 
      
 2 
     | 
    
         
            +
              module TaskManager
         
     | 
| 
      
 3 
     | 
    
         
            +
                def self.register(klass, blueprint, options, task_builder=Task)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @tasks ||= {}
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @tasks[ [klass.name, blueprint.to_sym] ] = task_builder.new(klass, blueprint, options)
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def self.submit!(object, blueprint)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  if @tasks
         
     | 
| 
      
 10 
     | 
    
         
            +
                    task = @tasks[ [object.class.name, blueprint.to_sym] ]
         
     | 
| 
      
 11 
     | 
    
         
            +
                    task.submit! object
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def self.process(class_name, id, blueprint, output, verbose_output)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  task = @tasks[ [class_name, blueprint.to_sym] ]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  task.process id, output, verbose_output
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/houdini/version.rb
    CHANGED
    
    
| 
         @@ -2,24 +2,22 @@ class Article < ActiveRecord::Base 
     | 
|
| 
       2 
2 
     | 
    
         
             
              include Houdini::Model
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
              houdini :edit_for_grammar,
         
     | 
| 
       5 
     | 
    
         
            -
                : 
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                  ' 
     | 
| 
      
 5 
     | 
    
         
            +
                :input => {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  'input1' => :original_text,
         
     | 
| 
      
 7 
     | 
    
         
            +
                  'input2' => proc{ original_text },
         
     | 
| 
      
 8 
     | 
    
         
            +
                  'input3' => "some text"
         
     | 
| 
       8 
9 
     | 
    
         
             
                },
         
     | 
| 
       9 
     | 
    
         
            -
                : 
     | 
| 
       10 
     | 
    
         
            -
                : 
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
              def moderate_image
         
     | 
| 
       15 
     | 
    
         
            -
                Houdini.perform!(:edit_for_grammar, self)
         
     | 
| 
       16 
     | 
    
         
            -
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
                :on                 => :after_create,
         
     | 
| 
      
 11 
     | 
    
         
            +
                :after_submit       => :update_houdini_attributes,
         
     | 
| 
      
 12 
     | 
    
         
            +
                :on_task_completion => :process_houdini_edited_text,
         
     | 
| 
      
 13 
     | 
    
         
            +
                :finder             => lambda{|id| last },
         
     | 
| 
      
 14 
     | 
    
         
            +
                :id_method          => lambda{ 'model-slug' }
         
     | 
| 
       17 
15 
     | 
    
         | 
| 
       18 
16 
     | 
    
         
             
              def update_houdini_attributes
         
     | 
| 
       19 
     | 
    
         
            -
                update_attribute(:houdini_request_sent_at,  
     | 
| 
      
 17 
     | 
    
         
            +
                update_attribute(:houdini_request_sent_at, Date.today.to_time)
         
     | 
| 
       20 
18 
     | 
    
         
             
              end
         
     | 
| 
       21 
19 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
              def process_houdini_edited_text( 
     | 
| 
       23 
     | 
    
         
            -
                update_attribute(:edited_text,  
     | 
| 
      
 20 
     | 
    
         
            +
              def process_houdini_edited_text(output, verbose_output)
         
     | 
| 
      
 21 
     | 
    
         
            +
                update_attribute(:edited_text, output[:edited_text])
         
     | 
| 
       24 
22 
     | 
    
         
             
              end
         
     | 
| 
       25 
23 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Houdini::Model do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let :test_model do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Class.new do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include Houdini::Model
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              describe ".houdini" do
         
     | 
| 
      
 11 
     | 
    
         
            +
                it "should define a method that submits the task" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  task_manager = double :task_manager
         
     | 
| 
      
 13 
     | 
    
         
            +
                  task_manager.should_receive(:register).with(test_model, :blueprint_name, :other_options => {})
         
     | 
| 
      
 14 
     | 
    
         
            +
                  test_model.houdini :blueprint_name, :task_manager => task_manager, :other_options => {}
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  test_model_instance = test_model.new
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  task_manager.should_receive(:submit!).with(test_model_instance, :blueprint_name)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  test_model_instance.houdini_submit_blueprint_name!
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                it "should attach callback methods" do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  test_model.should_receive(:after_create).with(:houdini_submit_blueprint_name!)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  test_model.houdini :blueprint_name, :on => :after_create
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Houdini::PostbackProcessor, ".process!" do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:houdini_settings) do
         
     | 
| 
      
 5 
     | 
    
         
            +
                { :environment => "production", :api_key => "MY_KEY", :app_url => "http://localhost:3000" }
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
              context "when the environments dont match" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                before do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  Houdini.setup "production", houdini_settings
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                it "should raise an EnvironmentMismatchError" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  lambda{
         
     | 
| 
      
 14 
     | 
    
         
            +
                    Houdini::PostbackProcessor.process 'Class', 42, :environment => "sandbox"
         
     | 
| 
      
 15 
     | 
    
         
            +
                  }.should raise_error(Houdini::PostbackProcessor::EnvironmentMismatchError)
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              context "when in production and given API key doesn't match" do
         
     | 
| 
      
 20 
     | 
    
         
            +
                it "should raise an APIKeyMistmatchError" do
         
     | 
| 
      
 21 
     | 
    
         
            +
            			pending "Houdini doesn't send the API key back."
         
     | 
| 
      
 22 
     | 
    
         
            +
                  lambda{
         
     | 
| 
      
 23 
     | 
    
         
            +
                    Houdini::PostbackProcessor.process 'Class', 42, :environment => "production", :api_key => "ANOTHER_KEY"
         
     | 
| 
      
 24 
     | 
    
         
            +
                  }.should raise_error(Houdini::PostbackProcessor::APIKeyMistmatchError)
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              context "given a classname and id" do
         
     | 
| 
      
 29 
     | 
    
         
            +
                it "should load the object, and have it process the postback, and return the result" do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  task_manager   = double :task_manager
         
     | 
| 
      
 31 
     | 
    
         
            +
                  output         = double :output
         
     | 
| 
      
 32 
     | 
    
         
            +
                  verbose_output = double :verbose_output
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  task_manager.should_receive(:process).with('MyClass', 42, 'blueprint_name', output, verbose_output)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  Houdini::PostbackProcessor.process 'MyClass', 42, houdini_settings.merge(
         
     | 
| 
      
 37 
     | 
    
         
            +
                    :blueprint      => 'blueprint_name',
         
     | 
| 
      
 38 
     | 
    
         
            +
                    :output         => output,
         
     | 
| 
      
 39 
     | 
    
         
            +
                    :verbose_output => verbose_output,
         
     | 
| 
      
 40 
     | 
    
         
            +
                    :task_manager   => task_manager
         
     | 
| 
      
 41 
     | 
    
         
            +
                  )
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Houdini::TaskManager do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe ".register, .submit!, and .process" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                class MyClass; end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                it "should save it and let us call it again, when we give the right blueprint and class" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                  options                = double :options
         
     | 
| 
      
 9 
     | 
    
         
            +
                  task_builder           = double :task_builder
         
     | 
| 
      
 10 
     | 
    
         
            +
                  task                   = double :task
         
     | 
| 
      
 11 
     | 
    
         
            +
                  obj                    = MyClass.new
         
     | 
| 
      
 12 
     | 
    
         
            +
                  houdini_output         = double :houdini_output
         
     | 
| 
      
 13 
     | 
    
         
            +
                  verbose_houdini_output = double :verbose_houdini_output
         
     | 
| 
      
 14 
     | 
    
         
            +
                  processing_result      = double :processing_result
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  task_builder.should_receive(:new).with(MyClass, :blueprint_name, options).and_return(task)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Houdini::TaskManager.register(MyClass, :blueprint_name, options, task_builder)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  task.should_receive(:submit!).with(obj)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Houdini::TaskManager.submit!(obj, :blueprint_name)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  task.should_receive(:process).with(42, houdini_output, verbose_houdini_output).and_return(processing_result)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  Houdini::TaskManager.process('MyClass', 42, 'blueprint_name', houdini_output, verbose_houdini_output).should == processing_result
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,136 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Houdini::Task do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe "submit!(obj)" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                class TestModel
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def id; 42; end
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                let(:model_object){ TestModel.new }
         
     | 
| 
      
 10 
     | 
    
         
            +
                let(:input){ double :input }
         
     | 
| 
      
 11 
     | 
    
         
            +
                it "should use the input transformer and submit it to houdini" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  task = Houdini::Task.new TestModel, :blueprint
         
     | 
| 
      
 13 
     | 
    
         
            +
                  submit_task = double(:callable)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  submit_task.should_receive(:call).with('blueprint', "TestModel", 42, input)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  task.submit! model_object, :input_transformer => proc{ input }, :submit_task => submit_task
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                it "should call the after_submit callback, when given a symbol" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  task = Houdini::Task.new TestModel, :blueprint, :after_submit => :after_submit
         
     | 
| 
      
 20 
     | 
    
         
            +
                  model_object.should_receive :after_submit
         
     | 
| 
      
 21 
     | 
    
         
            +
                  task.submit! model_object, :input_transformer => proc{}, :submit_task => proc{}
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                it "should call the after_submit callback, when given a block" do
         
     | 
| 
      
 25 
     | 
    
         
            +
                  task = Houdini::Task.new TestModel, :blueprint, :after_submit => proc{ after_submit }
         
     | 
| 
      
 26 
     | 
    
         
            +
                  model_object.should_receive :after_submit
         
     | 
| 
      
 27 
     | 
    
         
            +
                  task.submit! model_object, :input_transformer => proc{}, :submit_task => proc{}
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                it "should call the :id you provided to get the id" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  task = Houdini::Task.new TestModel, :blueprint, :id_method => lambda{ 'model-id' }
         
     | 
| 
      
 32 
     | 
    
         
            +
                  submit_task = double(:callable)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  submit_task.should_receive(:call).with('blueprint', "TestModel", 'model-id', nil)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  task.submit! model_object, :input_transformer => proc{}, :submit_task => submit_task
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              describe ".callable" do
         
     | 
| 
      
 39 
     | 
    
         
            +
                let(:obj){ double :obj, :some_method => result }
         
     | 
| 
      
 40 
     | 
    
         
            +
                subject{ Houdini::Task.callable(obj, callable, *args) }
         
     | 
| 
      
 41 
     | 
    
         
            +
                let(:result){ double :result }
         
     | 
| 
      
 42 
     | 
    
         
            +
                let(:args){ [double(:arg1), double(:arg2)] }
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                context "given a symbol" do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  let(:callable){ :some_method }
         
     | 
| 
      
 46 
     | 
    
         
            +
                  before{ obj.should_receive(:some_method).with(*args) }
         
     | 
| 
      
 47 
     | 
    
         
            +
                  it{ should == result }
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                context "given a proc" do
         
     | 
| 
      
 51 
     | 
    
         
            +
                  let(:callable){ lambda{|*args| some_method(*args) } }
         
     | 
| 
      
 52 
     | 
    
         
            +
                  before{ obj.should_receive(:some_method).with(*args) }
         
     | 
| 
      
 53 
     | 
    
         
            +
                  it{ should == result }
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                context "given something else" do
         
     | 
| 
      
 57 
     | 
    
         
            +
                  let(:callable){ 42 }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  it "should raise an error" do
         
     | 
| 
      
 59 
     | 
    
         
            +
                    lambda{
         
     | 
| 
      
 60 
     | 
    
         
            +
                      Houdini::Task.callable(obj, callable)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    }.should raise_error
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  context "and also given a block" do
         
     | 
| 
      
 65 
     | 
    
         
            +
                    it "should call the block with the callable and return the result" do
         
     | 
| 
      
 66 
     | 
    
         
            +
                      Houdini::Task.callable(double, 42){|c| c * 2 }.should == 84
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              describe ".get_input" do
         
     | 
| 
      
 73 
     | 
    
         
            +
                subject{ Houdini::Task.get_input(input_object, input_hash) }
         
     | 
| 
      
 74 
     | 
    
         
            +
                let(:input_object){ double :obj, :some_method => "some input", :some_method2 => "some more input" }
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                context "given an object and an instance hash" do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  let(:input_hash){  { :input1 => :some_method, :input2 => :some_method2 }  }
         
     | 
| 
      
 78 
     | 
    
         
            +
                  it "should build a hash based on the one given, and the values in the object" do
         
     | 
| 
      
 79 
     | 
    
         
            +
                    should == { :input1 => "some input", :input2 => "some more input" }
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
                context "given symbols" do
         
     | 
| 
      
 83 
     | 
    
         
            +
                  let(:input_hash){ { :input1=>:some_method } }
         
     | 
| 
      
 84 
     | 
    
         
            +
                  it "should get call the corresponding methods" do
         
     | 
| 
      
 85 
     | 
    
         
            +
                    should == { :input1 => "some input" }
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
                context "given lambdas" do
         
     | 
| 
      
 89 
     | 
    
         
            +
                  let(:input_hash){ { :input1=>lambda{some_method} }  }
         
     | 
| 
      
 90 
     | 
    
         
            +
                  it "should use evaluate procs in the context of the given object" do
         
     | 
| 
      
 91 
     | 
    
         
            +
                    should == { :input1 => "some input" }
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
                context "given procs" do
         
     | 
| 
      
 95 
     | 
    
         
            +
                  let(:input_hash){ { :input1=>proc{some_method} }  }
         
     | 
| 
      
 96 
     | 
    
         
            +
                  it "should use evaluate procs in the context of the given object" do
         
     | 
| 
      
 97 
     | 
    
         
            +
                    should == { :input1 => "some input" }
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
                context "given other values" do
         
     | 
| 
      
 101 
     | 
    
         
            +
                  let(:input_hash){ { :input1=>"some input", :input2=>42 } }
         
     | 
| 
      
 102 
     | 
    
         
            +
                  it "should return the value, if it's not callable" do
         
     | 
| 
      
 103 
     | 
    
         
            +
                    should == input_hash
         
     | 
| 
      
 104 
     | 
    
         
            +
                  end
         
     | 
| 
      
 105 
     | 
    
         
            +
                end
         
     | 
| 
      
 106 
     | 
    
         
            +
              end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
              describe "#process" do
         
     | 
| 
      
 109 
     | 
    
         
            +
            		class TestClass
         
     | 
| 
      
 110 
     | 
    
         
            +
            		end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                it "should call the callback on the object, giving it the houdini output, and verbose output, and return the result" do
         
     | 
| 
      
 113 
     | 
    
         
            +
                  obj = double :obj
         
     | 
| 
      
 114 
     | 
    
         
            +
                  houdini_output         = double :houdini_output
         
     | 
| 
      
 115 
     | 
    
         
            +
                  verbose_houdini_output = double :verbose_houdini_output
         
     | 
| 
      
 116 
     | 
    
         
            +
                  process_result         = double :process_result
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  task = Houdini::Task.new TestClass, :blueprint_name, :on_task_completion => :after_houdini_completion, :finder => :custom_finder
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                  TestClass.should_receive(:custom_finder).with(42).and_return(obj)
         
     | 
| 
      
 121 
     | 
    
         
            +
                  obj.should_receive(:after_houdini_completion).with(houdini_output, verbose_houdini_output).and_return(process_result)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                  task.process 42, houdini_output, verbose_houdini_output
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                it "should reload the class from it's name, so that this can work in Rails dev mode" do
         
     | 
| 
      
 127 
     | 
    
         
            +
            			klass = double :klass, :name => 'TestClass'
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  task = Houdini::Task.new klass, :blueprint_name
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  TestClass.should_receive(:find)
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  task.process 42, double, double
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Houdini, ".submit!" do
         
     | 
| 
      
 4 
     | 
    
         
            +
              it "should call .request with the right paramers" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Houdini.setup "some_environment", :api_key =>"SOME-API-KEY", :app_url => "http://localhost:3000"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                expected_params = {
         
     | 
| 
      
 8 
     | 
    
         
            +
                  :environment  => "some_environment",
         
     | 
| 
      
 9 
     | 
    
         
            +
                  :api_key      => "SOME-API-KEY",
         
     | 
| 
      
 10 
     | 
    
         
            +
                  :blueprint    => :blueprint_name,
         
     | 
| 
      
 11 
     | 
    
         
            +
                  :postback_url => "http://localhost:3000/houdini/ClassName/42/postbacks",
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :input        => { :input1 => 1, :input2 => 'two' }
         
     | 
| 
      
 13 
     | 
    
         
            +
                }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                Houdini.should_receive(:request).with(expected_params)
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                Houdini.submit! :blueprint_name, "ClassName", 42, :input1 => 1, :input2 => 'two'
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            	it "should not send requests if environment is 'test'" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                Houdini.setup "test", :api_key => "SOME-API-KEY", :app_url => "http://localhost:3000"
         
     | 
| 
      
 22 
     | 
    
         
            +
                Houdini.should_receive(:request).never
         
     | 
| 
      
 23 
     | 
    
         
            +
                Houdini.submit! :blueprint_name, "ClassName", 42, :input1 => 1, :input2 => 'two'
         
     | 
| 
      
 24 
     | 
    
         
            +
            	end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,35 +1,37 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'spec_helper'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            describe " 
     | 
| 
      
 3 
     | 
    
         
            +
            describe "End-to-end" do
         
     | 
| 
       4 
4 
     | 
    
         
             
              before do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Houdini.setup 'production', :app_url => "http://my-app:3333/"
         
     | 
| 
       5 
6 
     | 
    
         
             
                Article.delete_all
         
     | 
| 
       6 
     | 
    
         
            -
                Houdini::Base.stub!(:request).and_return(["200", "{response:success}"]) # TODO: VCR
         
     | 
| 
       7 
7 
     | 
    
         
             
              end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
              it "should send task to Houdini and properly receive the postback" do
         
     | 
| 
       10 
     | 
    
         
            -
                 
     | 
| 
       11 
     | 
    
         
            -
                p.stub!(:id).and_return(1)
         
     | 
| 
      
 10 
     | 
    
         
            +
                article = Article.new :original_text => 'This is incorect.'
         
     | 
| 
       12 
11 
     | 
    
         | 
| 
       13 
12 
     | 
    
         
             
                params = {
         
     | 
| 
       14 
     | 
    
         
            -
                  "api_key" 
     | 
| 
       15 
     | 
    
         
            -
                  "environment" 
     | 
| 
       16 
     | 
    
         
            -
                  "postback_url" => "http:// 
     | 
| 
       17 
     | 
    
         
            -
                  " 
     | 
| 
       18 
     | 
    
         
            -
                  " 
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                    " 
     | 
| 
      
 13 
     | 
    
         
            +
                  "api_key"      => Houdini.api_key,
         
     | 
| 
      
 14 
     | 
    
         
            +
                  "environment"  => Houdini.environment,
         
     | 
| 
      
 15 
     | 
    
         
            +
                  "postback_url" => "http://my-app:3333/houdini/Article/model-slug/postbacks",
         
     | 
| 
      
 16 
     | 
    
         
            +
                  "blueprint"    => "edit_for_grammar",
         
     | 
| 
      
 17 
     | 
    
         
            +
                  "input"    => {
         
     | 
| 
      
 18 
     | 
    
         
            +
                    "input1" => "This is incorect.",
         
     | 
| 
      
 19 
     | 
    
         
            +
                    "input2" => "This is incorect.",
         
     | 
| 
      
 20 
     | 
    
         
            +
                    "input3" => "some text"
         
     | 
| 
       21 
21 
     | 
    
         
             
                  }
         
     | 
| 
       22 
22 
     | 
    
         
             
                }.symbolize_keys
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                Houdini 
     | 
| 
      
 24 
     | 
    
         
            +
                Houdini.should_receive(:request).with(params)
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                 
     | 
| 
       27 
     | 
    
         
            -
                 
     | 
| 
       28 
     | 
    
         
            -
                 
     | 
| 
      
 26 
     | 
    
         
            +
                article.save!
         
     | 
| 
      
 27 
     | 
    
         
            +
                article.reload
         
     | 
| 
      
 28 
     | 
    
         
            +
                article.houdini_request_sent_at.should == Date.today.to_time
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                 
     | 
| 
      
 30 
     | 
    
         
            +
                output_params = {"edited_text"=>"This is incorrect."}
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
     | 
    
         
            -
                 
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
      
 32 
     | 
    
         
            +
                post "houdini/Article/model-slug/postbacks", params.merge("id" => "000000000000", "status"=>"complete", "output" => output_params, "verbose_output"=> output_params).to_json
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                article.reload
         
     | 
| 
      
 35 
     | 
    
         
            +
                article.edited_text.should == "This is incorrect."
         
     | 
| 
       34 
36 
     | 
    
         
             
              end
         
     | 
| 
       35 
     | 
    
         
            -
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     |