Skip to content

Commit

Permalink
Move some stuff out of config into matchers, expose just the pickle_ …
Browse files Browse the repository at this point in the history
…methods in Matchers
  • Loading branch information
ianwhite committed Aug 23, 2010
1 parent 88041f1 commit 9620257
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 188 deletions.
15 changes: 2 additions & 13 deletions lib/pickle/config.rb
Expand Up @@ -39,23 +39,16 @@ def predicates
# By default pickle_steps.rb just matches factory names that are a single word (with underscores).
# using #factory_names lets you add extra expressions (for example with spaces instead of underscores)
#
# config.names = ['admin user', 'site owner']
# config.factories = ['admin user', 'site owner']
# # this will mean that #pickle_ref will match 'the admin user', and the resulting factory name
# # will be 'admin_user'
#
# @see #alias
# @return Array String
def factories
@factories ||= []
@factories | aliases.keys
end

# pluralised versions of #names, no setter is available
# @return Array of string
def plural_factories
factories.map(&:pluralize)
end


# alias a bunch of names to another name(s)
#
# config.alias 'admin', 'admin user', :to => 'external_lib_admin_user' # where External::Lib::Admin::User is one of your models
Expand All @@ -75,10 +68,6 @@ class Mapping < Struct.new(:search, :replacement)
def mappings
@mapping ||= []
end

def mapping_searches
mappings.map(&:search)
end

# Usage: map 'me', 'myself', 'I', :to => 'user: "me"'
def map(*args)
Expand Down
72 changes: 40 additions & 32 deletions lib/pickle/parser/matchers.rb
Expand Up @@ -7,22 +7,37 @@ class Parser
module Matchers
attr_accessor :config

delegate :factories, :plural_factories, :predicates, :mapping_searches, :to => :config, :allow_nil => true
delegate :predicates, :to => :config, :allow_nil => true

def match_disjunction(*strings)
/(?:#{strings.compact.join('|')})/
# generate an expression to capture a reference to a model
# @arguments to restrict the expression to the given factory names
# @return Regexp
def pickle_ref(*restrict_to)
/(#{match_pickle_ref(*restrict_to).source})/
end

def capture_disjunction(*strings)
/(#{strings.compact.join('|')})/
# generate an expression to capture a plural factory name, such as 'users', 'admin users'
def pickle_plural
/(#{match_plural_factory.source})/
end

def match_quoted
/(?:"[^\"]*")/
# generate an expression to capture a fields string suitable for pickle
def pickle_fields
/(#{match_fields.source})/
end

def capture_quoted
/(?:"([^\"]*)")/
# generate an expression to capture a predicate, suitable for passing to Pickle::MakeMatcher#make_matcher
def pickle_predicate
/(#{match_predicate.source})/
end

protected
def match_disjunction(*strings)
/(?:#{strings.compact.join('|')})/
end

def match_quoted
/(?:"[^\"]*")/
end

def match_factory
Expand Down Expand Up @@ -58,39 +73,32 @@ def match_fields
end

def match_predicate
predicates ? match_disjunction(*(predicates + [match_quoted.source])) : match_quoted
end

def match_model
/(?:(?:#{match_index.source} |#{match_prefix.source} )?#{match_factory.source}(?:(?: |: )#{match_quoted.source})?)/
end

def match_pickle_ref
/(?:#{mapping_searches ? match_disjunction(mapping_searches).source + '|' : ''}#{match_quoted.source}|#{match_model.source})/
predicates ? match_disjunction(*(predicates + [match_quoted])) : match_quoted
end

def capture_index
/(?:(?:the )?(#{match_index_word.source}))/
def match_model(*restrict_to)
factory = restrict_to.any? ? match_disjunction(*restrict_to) : match_factory
/(?:(?:#{match_index.source} |#{match_prefix.source} )?#{factory.source}(?:(?: |: )#{match_quoted.source})?)/
end

def capture_factory
/(?:\b(\w\w+)\b)/
def match_pickle_ref(*restrict_to)
if mappings && restrict_to.empty?
/(?:#{match_disjunction(mappings).source}|#{match_quoted.source}|#{match_model.source})/
else
/(?:#{match_quoted.source}|#{match_model(*restrict_to).source})/
end
end

def capture_plural_factory
capture_name
end

def capture_fields
/(?: (\w+\: .*))/
def mappings
config && config.mappings.map(&:search)
end

def capture_model
/(#{match_model.source})/
def factories
config && (config.factories | config.aliases.keys)
end

def capture_predicate
predicates ? capture_disjunction(*(predicates + [match_quoted.source])) : /(#{match_quoted.source})/
def plural_factories
config && factories.map(&:pluralize)
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/pickle/ref.rb
Expand Up @@ -28,19 +28,19 @@ def parse_ref(orig)
# parse and remove the index from the given string
# @return the index or nil
def parse_index!(string)
remove_from_and_return_1st_capture!(string, /^#{capture_index} /)
remove_from_and_return_1st_capture!(string, /^(?:the )?(#{match_index_word}) /)
end

# parse the factory name from the given string, remove the factory name and optional prefix
# @return factory_name or nil
def parse_factory!(string)
remove_from_and_return_1st_capture!(string, /^(?:#{match_prefix} )?#{capture_factory}/)
remove_from_and_return_1st_capture!(string, /^(?:#{match_prefix} )?(#{match_factory})/)
end

# parse the label, removing it if found
# @return the label or nil
def parse_label!(string)
remove_from_and_return_1st_capture!(string, /^(?: |: )?#{capture_quoted}/)
remove_from_and_return_1st_capture!(string, /^(?: |: )?(#{match_quoted})/).try(:gsub, '"', '')
end

def remove_from_and_return_1st_capture!(string, regexp)
Expand Down
103 changes: 24 additions & 79 deletions spec/pickle/config_spec.rb
@@ -1,87 +1,34 @@
require 'spec_helper'

describe Pickle::Config do
before do
@config = Pickle::Config.new
subject { Pickle::Config.new }

describe "new" do
its(:adapters) { should == [:machinist, :factory_girl, :orm] }
its(:adapter_classes) { should == [Pickle::Adapter::Machinist, Pickle::Adapter::FactoryGirl, Pickle::Adapter::Orm] }
its(:predicates) { should be_empty }
its(:mappings) { should be_empty }
its(:factories) { should be_empty }
its(:plural_factories) { should be_empty }
its(:aliases) { should be_empty }
its(:labels) { should be_empty }
end

it "#adapters should default to :machinist, :factory_girl, :orm" do
@config.adapters.should == [:machinist, :factory_girl, :orm]
end

it "#adapter_classes should default to Adapter::Machinist, Adapter::FactoryGirl, Adapter::Orm" do
@config.adapter_classes.should == [Pickle::Adapter::Machinist, Pickle::Adapter::FactoryGirl, Pickle::Adapter::Orm]
end

describe "setting adapters to [:machinist, SomeAdapter]" do
class SomeAdapter; end

before do
@config.adapters = [:machinist, SomeAdapter]
end
describe "setting adapters to [:machinist, <adapter_class>]" do
let(:adapter_class) { Class.new(Object) }

it "#adapter_classes should be Adapter::Machinist, SomeAdapter" do
@config.adapter_classes.should == [Pickle::Adapter::Machinist, SomeAdapter]
end
end

describe "#factories" do
it "should call adaptor.factories for each adaptor" do
Pickle::Adapter::Machinist.should_receive(:factories).and_return([])
Pickle::Adapter::FactoryGirl.should_receive(:factories).and_return([])
Pickle::Adapter::Orm.should_receive(:factories).and_return([])
@config.factories
end

it "should aggregate factories into a hash using factory name as key" do
Pickle::Adapter::Machinist.should_receive(:factories).and_return([@machinist = mock('machinist', :name => 'machinist')])
Pickle::Adapter::FactoryGirl.should_receive(:factories).and_return([@factory_girl = mock('factory_girl', :name => 'factory_girl')])
Pickle::Adapter::Orm.should_receive(:factories).and_return([@orm = mock('orm', :name => 'orm')])
@config.factories.should == {'machinist' => @machinist, 'factory_girl' => @factory_girl, 'orm' => @orm}
end

it "should give preference to adaptors first in the list" do
Pickle::Adapter::Machinist.should_receive(:factories).and_return([@machinist_one = mock('one', :name => 'one')])
Pickle::Adapter::FactoryGirl.should_receive(:factories).and_return([@factory_girl_one = mock('one', :name => 'one'), @factory_girl_two = mock('two', :name => 'two')])
Pickle::Adapter::Orm.should_receive(:factories).and_return([@orm_two = mock('two', :name => 'two'), @orm_three = mock('three', :name => 'three')])
@config.factories.should == {'one' => @machinist_one, 'two' => @factory_girl_two, 'three' => @orm_three}
end
end

it "#mappings should default to []" do
@config.mappings.should == []
end

describe '#predicates' do
it "should be list of all non object ? public instance methods + columns methods of Adapter.model_classes" do
class1 = mock('Class1',
:public_instance_methods => ['nope', 'foo?', 'bar?'],
:column_names => ['one', 'two'],
:const_get => ::ActiveRecord::Base::PickleAdapter
)
class2 = mock('Class2',
:public_instance_methods => ['not', 'foo?', 'faz?'],
:column_names => ['two', 'three'],
:const_get => ::ActiveRecord::Base::PickleAdapter
)
Pickle::Adapter.stub!(:model_classes).and_return([class1, class2])

@config.predicates.to_set.should == ['foo?', 'faz?', 'bar?', 'one', 'two', 'three'].to_set
end

it "should be overridable" do
@config.predicates = %w(lame?)
@config.predicates.should == %w(lame?)
before { subject.adapters = [:machinist, adapter_class] }

it "should have :adapter_classes [Pickle::Adapter::Machinist, <adapter_class>]" do
subject.adapter_classes.should == [Pickle::Adapter::Machinist, adapter_class]
end
end

describe "#map 'foo', :to => 'faz'" do
before do
@config.map 'foo', :to => 'faz'
end
before { subject.map 'foo', :to => 'faz' }

it "should create Mapping('foo', 'faz') mapping" do
@config.mappings.first.tap do |mapping|
subject.mappings.first.tap do |mapping|
mapping.should be_kind_of Pickle::Config::Mapping
mapping.search.should == 'foo'
mapping.replacement.should == 'faz'
Expand All @@ -90,19 +37,17 @@ class SomeAdapter; end
end

describe "#map 'foo', 'bar' :to => 'faz'" do
before do
@config.map 'foo', 'bar', :to => 'faz'
end
before { subject.map 'foo', 'bar', :to => 'faz' }

it "should create 2 mappings" do
@config.mappings.first.should == Pickle::Config::Mapping.new('foo', 'faz')
@config.mappings.last.should == Pickle::Config::Mapping.new('bar', 'faz')
subject.mappings.first.should == Pickle::Config::Mapping.new('foo', 'faz')
subject.mappings.last.should == Pickle::Config::Mapping.new('bar', 'faz')
end
end

it "#configure(&block) should execiute on self" do
@config.should_receive(:foo).with(:bar)
@config.configure do |c|
subject.should_receive(:foo).with(:bar)
subject.configure do |c|
c.foo :bar
end
end
Expand Down

0 comments on commit 9620257

Please sign in to comment.