muffins 0.0.1

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 ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in muffins.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,33 @@
1
+ Feature: Basic Parsing
2
+ As an XML mapping library
3
+ I'd like to be awesome at mapping
4
+ So I can get hella downloads
5
+
6
+ Background:
7
+ Given the following xml:
8
+ """
9
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
10
+ <books>
11
+ <book>
12
+ <asin>1400079985</asin>
13
+ <title>War and Peace (Vintage Classics)</title>
14
+ </book>
15
+ <book>
16
+ <asin>1143035008</asin>
17
+ <title>Anna Karenina (Oprah's Book Club)</title>
18
+ </book>
19
+ </books>
20
+ """
21
+
22
+ Scenario: I parse the xml
23
+ Given that base_path has been set to 'book'
24
+ And the following mappings have been defined:
25
+ | name |
26
+ | asin |
27
+ | title |
28
+ When I parse the xml
29
+ Then I should have 2 books
30
+ And the following values should be returned:
31
+ | asin | title |
32
+ | 1400079985 | War and Peace (Vintage Classics) |
33
+ | 1143035008 | Anna Karenina (Oprah's Book Club) |
@@ -0,0 +1,37 @@
1
+ Feature: Nested Parsing
2
+ As an XML mapping library
3
+ I'd like to be awesome at mapping
4
+ So I can get hella downloads
5
+
6
+ Background:
7
+ Given the following xml:
8
+ """
9
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
10
+ <books>
11
+ <book>
12
+ <asin>1400079985</asin>
13
+ <itemattributes>
14
+ <title>War and Peace (Vintage Classics)</title>
15
+ </itemattributes>
16
+ </book>
17
+ <book>
18
+ <asin>1143035008</asin>
19
+ <itemattributes>
20
+ <title>Anna Karenina (Oprah's Book Club)</title>
21
+ </itemattributes>
22
+ </book>
23
+ </books>
24
+ """
25
+ Scenario: I parse the xml
26
+ Given that base_path has been set to 'book'
27
+ And the following mappings have been defined:
28
+ | name | within |
29
+ | asin | |
30
+ | title | itemattributes |
31
+ When I parse the xml
32
+ Then I should have 2 books
33
+ And the following values should be returned:
34
+ | asin | title |
35
+ | 1400079985 | War and Peace (Vintage Classics) |
36
+ | 1143035008 | Anna Karenina (Oprah's Book Club) |
37
+
@@ -0,0 +1,36 @@
1
+ Feature: Non-Primitive Typing
2
+ As an XML mapping library
3
+ I'd like to be awesome at mapping
4
+ So I can get hella downloads
5
+
6
+ Background:
7
+ Given the following xml:
8
+ """
9
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
10
+ <books>
11
+ <book>
12
+ <asin>1400079985</asin>
13
+ <title>War and Peace (Vintage Classics)</title>
14
+ <similarproducts>
15
+ <product>
16
+ <asin>1143035008</asin>
17
+ <title>Anna Karenina (Oprah's Book Club)</title>
18
+ </product>
19
+ </similarproducts>
20
+ </book>
21
+ </books>
22
+ """
23
+
24
+ Scenario: I parse the xml
25
+ Given that base_path has been set to 'book'
26
+ And the following mappings have been defined:
27
+ | name | type |
28
+ | asin | |
29
+ | title | |
30
+ | similarproducts | Product |
31
+ When I parse the xml
32
+ Then I should have 1 books
33
+ And the following values should be returned:
34
+ | asin | title |
35
+ | 1400079985 | War and Peace (Vintage Classics) |
36
+ And 'similarproducts' should return 1 instances of Product
@@ -0,0 +1,33 @@
1
+ Feature: Specified Pathnames
2
+ As an XML mapping library
3
+ I'd like to be awesome at mapping
4
+ So I can get hella downloads
5
+
6
+ Background:
7
+ Given the following xml:
8
+ """
9
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
10
+ <BOOKS>
11
+ <BOOK>
12
+ <ASIN>1400079985</ASIN>
13
+ <TITLE>War and Peace (Vintage Classics)</TITLE>
14
+ </BOOK>
15
+ <BOOK>
16
+ <ASIN>1143035008</ASIN>
17
+ <TITLE>Anna Karenina (Oprah's Book Club)</TITLE>
18
+ </BOOK>
19
+ </BOOKS>
20
+ """
21
+ Scenario: I parse the xml
22
+ Given that base_path has been set to 'BOOK'
23
+ And the following mappings have been defined:
24
+ | name | to |
25
+ | asin | ASIN |
26
+ | title | TITLE |
27
+ When I parse the xml
28
+ Then I should have 2 books
29
+ And the following values should be returned:
30
+ | asin | title |
31
+ | 1400079985 | War and Peace (Vintage Classics) |
32
+ | 1143035008 | Anna Karenina (Oprah's Book Club) |
33
+
@@ -0,0 +1,33 @@
1
+ Feature: Specified Typing
2
+ As an XML mapping library
3
+ I'd like to be awesome at mapping
4
+ So I can get hella downloads
5
+
6
+ Background:
7
+ Given the following xml:
8
+ """
9
+ <?xml version=\"1.0\" encoding=\"UTF-8\"?>
10
+ <books>
11
+ <book>
12
+ <asin>1400079985</asin>
13
+ <title>War and Peace (Vintage Classics)</title>
14
+ </book>
15
+ <book>
16
+ <asin>1143035008</asin>
17
+ <title>Anna Karenina (Oprah's Book Club)</title>
18
+ </book>
19
+ </books>
20
+ """
21
+ Scenario: I parse the xml
22
+ Given that base_path has been set to 'book'
23
+ And the following mappings have been defined:
24
+ | name | type |
25
+ | asin | Integer |
26
+ | title | String |
27
+ When I parse the xml
28
+ Then I should have 2 books
29
+ And the following data types should be returned:
30
+ | asin | title |
31
+ | Integer | String |
32
+ | Integer | String |
33
+
@@ -0,0 +1,52 @@
1
+ Given /^the following xml:$/ do |doc|
2
+ @xml = Nokogiri::XML(doc)
3
+ end
4
+
5
+ Given /^that base_path has been set to '(.*?)'$/ do |base_path|
6
+ Book.base_path base_path
7
+ end
8
+
9
+ Given /^the following mappings have been defined:$/ do |table|
10
+ table.hashes.each do |options|
11
+ name = options.delete('name')
12
+ Book.map name, options
13
+ end
14
+ end
15
+
16
+
17
+ When /^I parse the xml$/ do
18
+ @books = Book.parse(@xml)
19
+ end
20
+
21
+ Then /^I should have (\d+) books$/ do |count|
22
+ @books.count.should == count.to_i
23
+ end
24
+
25
+ Then /^the following values should be returned:$/ do |table|
26
+ @books.count.times do |count|
27
+ book = @books[count]
28
+
29
+ table.hashes[count].each_pair do |key, value|
30
+ book.send(key).should == value
31
+ end
32
+ end
33
+ end
34
+
35
+ Then /^the following data types should be returned:$/ do |table|
36
+ @books.count.times do |count|
37
+ book = @books[count]
38
+
39
+ table.hashes[count].each_pair do |key, value|
40
+ type = value.constantize
41
+ book.send(key).should be_a(type)
42
+ end
43
+ end
44
+ end
45
+
46
+ Then /^'(.*?)' should return (\d+) instances of (.*?)$/ do |method, count, type|
47
+ @books.each do |book|
48
+ products = book.send(method)
49
+ products.count.should == count.to_i
50
+ products.each {|p| p.should be_a(type.constantize) }
51
+ end
52
+ end
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'nokogiri'
4
+ require 'activesupport'
5
+ require 'muffins'
6
+
7
+
8
+ class Book
9
+ include Muffins
10
+ end
11
+
12
+ class Product
13
+ include Muffins
14
+
15
+ base_path 'product'
16
+ end
data/lib/muffins.rb ADDED
@@ -0,0 +1,43 @@
1
+ require "muffins/mapping"
2
+ require "muffins/mapping_decorator"
3
+ require "muffins/version"
4
+
5
+ module Muffins
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def base_path(bp = nil)
13
+ @base_path = bp if bp
14
+ @base_path
15
+ end
16
+
17
+ def parse(document, options = {})
18
+ document.css(base_path).collect do |node|
19
+ (new).tap do |object|
20
+
21
+ mappings.each do |mapping|
22
+ object.send("#{mapping.name}=", mapping.map(node))
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
29
+ def within(path, &block)
30
+ yield MappingDecorator.new(path, self)
31
+ end
32
+
33
+ def map(symbol, options = {})
34
+ attr_accessor symbol unless new.respond_to?(symbol)
35
+
36
+ mappings << Mapping.new(symbol, options)
37
+ end
38
+
39
+ def mappings
40
+ @mappings ||= []
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,73 @@
1
+ module Muffins
2
+ class Mapping
3
+
4
+ PRIMITIVE_TYPES = [String, Float, Time, Date, DateTime, Integer]
5
+
6
+ attr_reader :name, :options
7
+
8
+ def initialize(name, options = {})
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def map(document)
14
+ if collection?
15
+ ([]).tap do |items|
16
+ document.css(path).each do |node|
17
+ items << typecast(node)
18
+ end
19
+ end
20
+ else
21
+ typecast document.at_css(path)
22
+ end
23
+ end
24
+
25
+ def path
26
+ path = options[:to].present? ? options[:to] : name
27
+
28
+ unless options[:within].blank?
29
+ path = "#{options[:within]} > #{path}"
30
+ end
31
+
32
+ @path ||= path
33
+ end
34
+
35
+ def collection?
36
+ !!options[:collection]
37
+ end
38
+
39
+ def primitive?
40
+ PRIMITIVE_TYPES.include? options[:type].constantize
41
+ end
42
+
43
+ def typecast(node)
44
+ value, constant = node.try(:text), "#{options[:type]}"
45
+
46
+ return value if value.blank? || constant.blank?
47
+
48
+ constant = constant.constantize
49
+
50
+ if primitive?
51
+ if constant == String
52
+ value.to_s
53
+ elsif constant == Float
54
+ value.to_f
55
+ elsif constant == Time
56
+ Time.parse(value) rescue Time.at(value.to_i)
57
+ elsif constant == Date
58
+ Date.parse(value)
59
+ elsif constant == DateTime
60
+ DateTime.parse(value)
61
+ elsif constant == Integer
62
+ value.to_i
63
+ else
64
+ value
65
+ end
66
+
67
+ else
68
+ constant.parse(node)
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,22 @@
1
+ module Muffins
2
+ class MappingDecorator
3
+
4
+ attr_reader :base_path, :object
5
+
6
+ def initialize(base_path, object)
7
+ @base_path = base_path
8
+ @object = object
9
+ end
10
+
11
+ def map(name, options = {})
12
+ options[:within] =
13
+ if options[:within]
14
+ "#{base_path} > #{options[:within]}"
15
+ else
16
+ base_path
17
+ end
18
+
19
+ object.map(name, options)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Muffins
2
+ VERSION = "0.0.1"
3
+ end
data/muffins.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "muffins/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "muffins"
7
+ s.version = Muffins::VERSION
8
+ s.authors = ["Ryan Closner"]
9
+ s.email = ["ryan.closner@gmail.com"]
10
+ s.homepage = "https://rubygems.org/gems/muffins"
11
+ s.summary = %q{An Object to XML/HTML mapping library using Nokogiri}
12
+ s.description = %q{An Object to XML/HTML mapping library using Nokogiri}
13
+
14
+ s.rubyforge_project = "muffins"
15
+
16
+ {
17
+ 'activesupport' => '~> 2.3.10',
18
+ 'nokogiri' => '~> 1.4'
19
+ }.each do |lib, version|
20
+ s.add_runtime_dependency lib, version
21
+ end
22
+
23
+
24
+ {
25
+ 'bundler' => '~> 1.0',
26
+ 'cucumber' => '~> 0.10',
27
+ 'rspec' => '~> 2.6',
28
+ }.each do |lib, version|
29
+ s.add_development_dependency lib, version
30
+ end
31
+
32
+ s.files = `git ls-files`.split("\n")
33
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
34
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
35
+ s.require_paths = ["lib"]
36
+ end
@@ -0,0 +1,219 @@
1
+ require 'spec_helper'
2
+
3
+ module Muffins
4
+ describe Mapping do
5
+
6
+ let(:name) { :foo }
7
+ let(:options) { {} }
8
+
9
+ let(:document) { mock(Nokogiri::XML::Document) }
10
+
11
+ let(:node) { mock(Nokogiri::XML::Node) }
12
+ let(:nodes) { [node] }
13
+
14
+ let(:value) { 'bar' }
15
+ let(:values) { [value] }
16
+
17
+ subject { Mapping.new(name, options) }
18
+
19
+ describe "#map" do
20
+ before(:each) do
21
+ subject.stub(:typecast).with(node).and_return(value)
22
+ end
23
+
24
+ context "#collection? returns true" do
25
+ before(:each) do
26
+ subject.stub(:collection?).and_return(true)
27
+
28
+ document.stub(:css).and_return(nodes)
29
+ end
30
+
31
+ it "typecasts the parsed values" do
32
+ subject.should_receive(:typecast).with(node).and_return(value)
33
+ subject.map(document)
34
+ end
35
+
36
+ it "returns an array of typecasted values" do
37
+ subject.map(document).should == values
38
+ end
39
+ end
40
+
41
+ context "#collection? returns false" do
42
+ before(:each) do
43
+ subject.stub(:collection?).and_return(false)
44
+
45
+ document.stub(:at_css).and_return(node)
46
+ end
47
+
48
+ it "typecasts the parsed value" do
49
+ subject.should_receive(:typecast).with(node).and_return(value)
50
+ subject.map(document)
51
+ end
52
+
53
+ it "returns the typecasted value" do
54
+ subject.map(document).should == value
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#path" do
60
+ context "no options are passed" do
61
+ it "returns the mapping name" do
62
+ subject.path.should == name
63
+ end
64
+ end
65
+
66
+ context "options[:to] is passed" do
67
+ let(:to) { 'bar' }
68
+ let(:options) { {:to => to} }
69
+
70
+ before(:each) do
71
+ subject.stub(:options).and_return(options)
72
+ end
73
+
74
+ it "returns the passed path name" do
75
+ subject.path.should == to
76
+ end
77
+ end
78
+
79
+ context "options[:within] is passed" do
80
+ let(:within) { 'parent' }
81
+ let(:to) { 'child' }
82
+
83
+ let(:options) { {:within => within, :to => to} }
84
+
85
+ before(:each) do
86
+ subject.stub(:options).and_return(options)
87
+ end
88
+
89
+ it "returns the css selector with parent and child" do
90
+ subject.path.should == "#{within} > #{to}"
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "#collection?" do
96
+ context "options[:collection] is nil" do
97
+ it "returns false" do
98
+ subject.collection?.should be_false
99
+ end
100
+ end
101
+
102
+ context "options[:collection] is false" do
103
+
104
+ let(:options) { {:collection => false} }
105
+
106
+ before(:each) do
107
+ subject.stub(:options).and_return(options)
108
+ end
109
+
110
+ it "returns false" do
111
+ subject.collection?.should be_false
112
+ end
113
+ end
114
+
115
+ context "options[:collection] is true" do
116
+
117
+ let(:options) { {:collection => true} }
118
+
119
+ before(:each) do
120
+ subject.stub(:options).and_return(options)
121
+ end
122
+
123
+ it "returns true" do
124
+ subject.collection?.should be_true
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "#primitive?" do
130
+ end
131
+
132
+ describe "#typecast" do
133
+
134
+ before(:each) do
135
+ node.stub(:try).with(:text).and_return(value)
136
+
137
+ subject.stub(:options).and_return(options)
138
+ end
139
+
140
+ context "#primitive? returns true" do
141
+
142
+ before(:each) do
143
+ subject.stub(:primitive?).and_return(true)
144
+ end
145
+
146
+ context "options[:type] = String" do
147
+ let(:options) { {:type => String} }
148
+
149
+ it "returns an instance of String" do
150
+ subject.typecast(node).should be_a(String)
151
+ end
152
+ end
153
+
154
+ context "options[:type] = Float" do
155
+ let(:options) { {:type => Float} }
156
+ let(:value) { '10.01' }
157
+
158
+ it "returns an instance of Float" do
159
+ subject.typecast(node).should be_a(Float)
160
+ end
161
+ end
162
+
163
+ context "options[:type] = Time" do
164
+ let(:options) { {:type => Time} }
165
+
166
+ let(:value) { '00:00:00 -0700' }
167
+
168
+ it "returns an instance of Time" do
169
+ subject.typecast(node).should be_a(Time)
170
+ end
171
+ end
172
+
173
+ context "options[:type] = Date" do
174
+ let(:options) { {:type => Date} }
175
+
176
+ let(:value) { '2011-01-01' }
177
+
178
+ it "returns an instance of Date" do
179
+ subject.typecast(node).should be_a(Date)
180
+ end
181
+ end
182
+
183
+ context "options[:type] = DateTime" do
184
+ let(:options) { {:type => DateTime} }
185
+
186
+ let(:value) { '2011-01-01 00:00:00 -0700' }
187
+
188
+ it "returns an instance of DateTime" do
189
+ subject.typecast(node).should be_a(DateTime)
190
+ end
191
+ end
192
+
193
+ context "options[:type] = Integer" do
194
+ let(:options) { {:type => Integer} }
195
+
196
+ let(:value) { '12908234' }
197
+
198
+ it "returns an instance of Integer" do
199
+ subject.typecast(node).should be_a(Integer)
200
+ end
201
+ end
202
+ end
203
+
204
+ context "#primitive? returns false" do
205
+ let(:options) { {:type => Book} }
206
+
207
+ before(:each) do
208
+ subject.stub(:primitive?).and_return(false)
209
+ end
210
+
211
+ it "attempts to parse the nested set" do
212
+ Book.should_receive(:parse).with(node)
213
+ subject.typecast(node)
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
219
+
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ module Muffins
4
+ describe MappingDecorator do
5
+
6
+ let(:object) do
7
+ class Book
8
+ include Muffins
9
+ end
10
+ end
11
+
12
+ let(:base_path) { 'foo' }
13
+ let(:name) { 'bar' }
14
+
15
+ let(:decorator_options) { {} }
16
+
17
+ let(:nested_path) { 'foobar' }
18
+
19
+ subject { MappingDecorator.new(base_path, object) }
20
+
21
+ describe "#map" do
22
+ context "options[:within] is nil" do
23
+
24
+ let(:mapping_options) { {:within => base_path } }
25
+
26
+ it "sets options[:within] to the base_path" do
27
+ object.should_receive(:map).with(name, mapping_options)
28
+ subject.map(name, decorator_options)
29
+ end
30
+ end
31
+
32
+ context "options[:within] is not nil" do
33
+
34
+ let(:mapping_options) { {:within => "#{base_path} > #{nested_path}"} }
35
+
36
+ let(:decorator_options) { {:within => nested_path} }
37
+
38
+
39
+ it "sets options[:within] to the 'base_path > nested_path'" do
40
+ object.should_receive(:map).with(name, mapping_options)
41
+ subject.map(name, decorator_options)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe Muffins do
4
+
5
+ context "when included in a class" do
6
+
7
+ subject do
8
+ class Book
9
+ include Muffins
10
+ end
11
+ end
12
+
13
+ let(:book) { mock(Book) }
14
+
15
+ let(:mapping) { mock(Muffins::Mapping) }
16
+ let(:mapping_name) { :foo }
17
+ let(:mapping_options) { {} }
18
+
19
+
20
+ describe ".mappings" do
21
+ it "returns an array" do
22
+ subject.mappings.should be_an(Array)
23
+ end
24
+ end
25
+
26
+ describe ".base_path" do
27
+ context "value is passed" do
28
+ it "sets @base_path to the passed value" do
29
+ subject.base_path('book')
30
+ subject.instance_variable_get(:@base_path).should == 'book'
31
+ end
32
+ end
33
+
34
+ context "no value is passed" do
35
+ it "returns the value of @base_path" do
36
+ subject.instance_variable_set(:@base_path, 'book')
37
+ subject.base_path.should == 'book'
38
+ end
39
+ end
40
+ end
41
+
42
+ describe ".parse" do
43
+ let(:document) { mock(Nokogiri::XML::Document) }
44
+ let(:node) { mock(Nokogiri::XML::Node) }
45
+
46
+ let(:nodes) { [node] }
47
+
48
+ let(:base_path) { 'book' }
49
+ let(:mappings) { [mapping] }
50
+
51
+ let(:mapping_value) { 'bar' }
52
+
53
+ before(:each) do
54
+ subject.stub(:base_path).and_return(base_path)
55
+ subject.stub(:new).and_return(book)
56
+ subject.stub(:mappings).and_return(mappings)
57
+
58
+ book.stub("#{mapping_name}=")
59
+
60
+ document.stub(:css).with(base_path).and_return(nodes)
61
+
62
+ mapping.stub(:name).and_return(mapping_name)
63
+ mapping.stub(:map).with(node).and_return(mapping_value)
64
+ end
65
+
66
+ it "sets klass#method_name to the mapped node value" do
67
+ book.should_receive("#{mapping_name}=").with(mapping_value)
68
+ subject.parse(document)
69
+ end
70
+
71
+ it "returns an array of klasses" do
72
+ subject.parse(document).should == [book]
73
+ end
74
+ end
75
+
76
+ describe ".within" do
77
+ it "yields an instance of Muffins::MappingDecorator" do
78
+ subject.within :foo do |foo|
79
+ foo.should be_a(Muffins::MappingDecorator)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe ".map" do
85
+
86
+ let(:mappings) { [] }
87
+
88
+ before(:each) do
89
+ Muffins::Mapping.stub(:new)
90
+ .with(mapping_name, mapping_options)
91
+ .and_return(mapping)
92
+
93
+
94
+ book.stub(:respond_to?).with(mapping_name)
95
+ subject.stub(:new).and_return(book)
96
+
97
+ subject.stub(:mappings).and_return(mappings)
98
+ end
99
+
100
+ it "adds a new instance of Muffins::Mapping to .mappings" do
101
+ mappings.should_receive(:<<).with(mapping)
102
+ subject.map mapping_name, mapping_options
103
+ end
104
+
105
+ context "the mapping name is not a defined method" do
106
+ before(:each) do
107
+ book.stub(:respond_to?).with(mapping_name).and_return(false)
108
+ end
109
+
110
+ it "defines an attr_accessor for the mapping name" do
111
+ subject.should_receive(:attr_accessor).with(mapping_name)
112
+ subject.map mapping_name
113
+ end
114
+ end
115
+
116
+ context "the mapping name is already a defined method" do
117
+ before(:each) do
118
+ book.stub(:respond_to?).with(mapping_name).and_return(true)
119
+ end
120
+
121
+ it "does not overwrite the existing method" do
122
+ subject.should_not_receive(:attr_accessor).with(mapping_name)
123
+ subject.map mapping_name
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec'
4
+ require 'nokogiri'
5
+ require 'activesupport'
6
+
7
+ require File.expand_path('../../lib/muffins', __FILE__)
8
+
9
+ def fixture_file(filename)
10
+ File.read(File.dirname(__FILE__) + "/fixtures/#{filename}")
11
+ end
12
+
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: muffins
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ryan Closner
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-09 00:00:00.000000000 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ requirement: &15895880 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 2.3.10
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *15895880
26
+ - !ruby/object:Gem::Dependency
27
+ name: nokogiri
28
+ requirement: &15895400 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *15895400
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ requirement: &15894760 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: '1.0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *15894760
48
+ - !ruby/object:Gem::Dependency
49
+ name: cucumber
50
+ requirement: &15894320 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '0.10'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *15894320
59
+ - !ruby/object:Gem::Dependency
60
+ name: rspec
61
+ requirement: &15893880 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ~>
65
+ - !ruby/object:Gem::Version
66
+ version: '2.6'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *15893880
70
+ description: An Object to XML/HTML mapping library using Nokogiri
71
+ email:
72
+ - ryan.closner@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - .gitignore
78
+ - Gemfile
79
+ - Rakefile
80
+ - features/basic_parsing.feature
81
+ - features/nested_parsing.feature
82
+ - features/non_primitive_typing.feature
83
+ - features/specified_pathnames.feature
84
+ - features/specified_typing.feature
85
+ - features/step_definitions/application_steps.rb
86
+ - features/support/env.rb
87
+ - lib/muffins.rb
88
+ - lib/muffins/mapping.rb
89
+ - lib/muffins/mapping_decorator.rb
90
+ - lib/muffins/version.rb
91
+ - muffins.gemspec
92
+ - spec/mapping_spec.rb
93
+ - spec/muffins/mapping_decorator_spec.rb
94
+ - spec/muffins_spec.rb
95
+ - spec/spec_helper.rb
96
+ has_rdoc: true
97
+ homepage: https://rubygems.org/gems/muffins
98
+ licenses: []
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project: muffins
117
+ rubygems_version: 1.6.2
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: An Object to XML/HTML mapping library using Nokogiri
121
+ test_files:
122
+ - features/basic_parsing.feature
123
+ - features/nested_parsing.feature
124
+ - features/non_primitive_typing.feature
125
+ - features/specified_pathnames.feature
126
+ - features/specified_typing.feature
127
+ - features/step_definitions/application_steps.rb
128
+ - features/support/env.rb
129
+ - spec/mapping_spec.rb
130
+ - spec/muffins/mapping_decorator_spec.rb
131
+ - spec/muffins_spec.rb
132
+ - spec/spec_helper.rb