muffins 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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