Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  # Creates specially named factory methods for easily instantiating new model
  # objects with a set of preloaded data.  The name of the helper methods
  # are based on the name of the model under test.  model_factory_helper
  # generates several methods that can be used in your specs.
  #
  # model_factory_helper also automatically generates a specification which
  # verifies that your model should be valid when instantiated using the 
  # default_attributes that you supplied.
  #
  # == Calling
  # Currently model_factory_helper must be passed:
  # * A reference to the context that the spec is run (+self+)
  # * The reference to the model class under test
  # * A <tt>:default_attributes</tt> option, which should be a Hash of all the default 
  #   values for the model's attributes.
  #
  # == Generated Methods
  # TODO: Document model_factory_helper generated methods
  #
  # == Example
  # A typical (horribly contrived) spec for a basic model could look like:
  #   model_factory_helper(self, Person, :default_attributes => { :name => "Steve", :vegetarian => false })
  #
  #   describe User do
  #     it_should_require_fields :name
  #
  #     before(:each) do
  #       @user = user_with(:all)
  #     end
  #
  #     it "should allow user to eat_meat by default" do
  #       lambda { @user.eat_meat }.should_not raise_error
  #     end
  #
  #     it "should raise error when vegetarians eat meat" do
  #       lambda { user_with(:vegetarian => true).eat_meat }.should raise_error
  #     end
  #   end
  def model_factory_helper(calling_spec, model_class, options)
    raise "factory_method requires default_attributes" unless options.has_key?(:default_attributes)
    raise "factory_method default_attributes must be a Hash" unless options[:default_attributes].is_a?(Hash)

    proper_class_name = model_class.name
    lowered_class_name = model_class.name.downcase

    calling_spec.instance_eval <<-"end;"
      module #{proper_class_name}HelperFactory
      
        def #{lowered_class_name}_default_attributes(options = {})
          #{options[:default_attributes].inspect}.merge(options)
        end
      
        def #{lowered_class_name}_with(options = {})
          options = {} if options == :all
          #{proper_class_name}.new(#{lowered_class_name}_default_attributes(options))
        end
      
        def #{lowered_class_name}_without(field)
          #{proper_class_name}.new(#{lowered_class_name}_default_attributes(field => nil))
        end
      
        def it_should_require_fields(*fields)
          fields.each do |field|
            it "should be invalid without \#{field} attribute" do
              #{lowered_class_name}_without(field).should_not be_valid
            end
          end
        end
        alias it_should_require_field it_should_require_fields
        
        describe #{proper_class_name}, "instantiated with default attributes" do
          it "should be valid" do
            #{lowered_class_name}_with(:all).should be_valid
          end
        end
      end
  
      include #{proper_class_name}HelperFactory
    end;
  end