views:

66

answers:

2

I would like to get machinist, machinist_mongo, mongo_mapper, cucumber and pickle to play nice together.

Currently I have machinist with all my blueprints configured and am using cucumber to do BDD. So far so good. My problem is I am having to write custom cucumber steps for all of my machinist blueprints. It is not really a problem per se, since it is not stopping me in my tracks, but as a .NET dev checking out rails, it feels really dirty to have to write a step for each blueprint whereas in .NET I could probably use reflection.

Is there any way I can get pickle's built in capture_model, capture_plural_factory, etc, to recognize my machinist blueprints?

I am pretty confident I have machinist configured and set up correctly, because when I use blueprintname.make, in a custom cucumber step, everything works out correctly.

Gem versions:
rails 2.3.8
cucumber 0.8.3
cucumber-rails 0.3.2
mongo 1.0.5
mongo_mapper 0.8.2
pickle 0.3.0
machinist 1.0.6
machinist_mongo 1.1.1


features/support/pickle.rb:
require 'pickle/world'
Pickle.configure do |config|
  config.adapters = [:machinist]
end

I tried using config.adapters = [:machinist, Machinist::MongoMapperAdapter] but I get an error stating that there is no method factories for Machinist::MongoMapperAdapter.

undefined method `factories' for Machinist::MongoMapperAdapter:Class (NoMethodError) /usr/local/lib/ruby/gems/1.8/gems/pickle-0.3.0/lib/pickle/config.rb:25:in `factories'

features/support/machinist.rb:
require 'machinist'
require 'machinist/mongo_mapper'
require "#{Rails.root}/spec/blueprints"
require 'database_cleaner'
Before { Sham.reset } # reset Shams in between scenarios
spec/blueprints.rb (truncated for clarity)
require 'sham'
require 'faker'

Sham.code { Faker::Lorem.words 1 }

AccessCode.blueprint do
  code
end
app/models/access_code.rb
class AccessCode
  include MongoMapper::Document

  key :code, String, :required => true
end
A: 

After days of beating my head against the wall, I have everything mostly working (I say mostly working because I'm not sure if there is something wrong that I haven't discovered yet). The fix was actually pretty simple once I figured it out.

To resolve the issue, and get my cucumber steps working with pickle, I changed MongoMapper::Document to include Pickle::Adapter::Base. I used lib/pickle/adapters/active_record.rb and data_mapper.rb (same path as active_record.rb) that come with pickle as an example. I did still need machinist_mongo, presumably to hook up pickle to my machinist blueprints.

I can't take credit for the code in def self.model_classes - it is stolen from tjtuom's pickle fork.

PS. If this is the completely wrong way to do it, please feel free to criticize or give suggestions, I am a complete ruby noob.

module MongoMapper::Document
  module PickleAdapter
    include Pickle::Adapter::Base

    def self.model_classes
      @@model_classes ||= ::MongoMapper::Document.descendants.to_a +
        ::MongoMapper::Document.descendants.map { |klass| klass.subclasses }.flatten
    end

    # get a list of column names for a given class
    def self.column_names(klass)
      klass.column_names
    end

    # Get an instance by id of the model
    def self.get_model(klass, id)
      klass.find(id)
    end

    # Find the first instance matching conditions
    def self.find_first_model(klass, conditions)
      klass.find(:first, :conditions => conditions)
    end

    # Find all models matching conditions
    def self.find_all_models(klass, conditions)
      klass.find(:all, :conditions => conditions)
    end
  end
end

Set up pickle for machinist:

Pickle.configure do |config|
  config.adapters = [:machinist]
end

To configure database_cleaner for mongo:

require 'database_cleaner'
require 'database_cleaner/cucumber'

DatabaseCleaner.orm = 'mongo_mapper'
DatabaseCleaner.strategy = :truncation
Nate Pinchot
A: 

I'm using something like this.

# MongoID adapter for Pickle
require 'mongoid'

module Mongoid #:nodoc:
  module Document
    module PickleAdapter
      include Pickle::Adapter::Base

      # Do not consider these to be part of the class list
      def self.except_classes
        @@except_classes ||= []
      end

      # Gets a list of the available models for this adapter
      def self.model_classes
        @@model_classes ||= ObjectSpace.each_object(Class).select {|klass| klass.ancestors.include?(Mongoid::Document)}
      end

      # get a list of column names for a given class
      def self.column_names(klass)
        #klass.column_names
        klass.fields.keys
      end

      # Get an instance by id of the model
      def self.get_model(klass, id)
        klass.find(id)
      end

      # Find the first instance matching conditions
      def self.find_first_model(klass, conditions)
        klass.find(:first, :conditions => conditions)
      end

      # Find all models matching conditions
      def self.find_all_models(klass, conditions)
        klass.find(:all, :conditions => conditions)
      end
    end
  end
end

But while I started cucumber test it didn't see pickle step. For sample:

# create models from a table
Given(/^the following #{capture_plural_factory} exists?:?$/) do |plural_factory, table|
  create_models_from_table(plural_factory, table)
end

Am I doing something wrong? Any Ideas.

kshil
If you are using machinist or factory girl, are they all set up? Double check that pickle is configured to use whichever one you are using? Sorry not really sure what else, I've only been using ruby/rails a couple weeks :)
Nate Pinchot