document_builder 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZWNiNzZjNjY4MzVhMmNiNTZmOGRhMWEyODE4ZWZkZjM1MGVkYWZjZQ==
4
+ ZGFkOWQ4NTM0NDI2ZTFiZDk0ZjczODgwYWQ2OWI4YmI4N2FjZDM0Mg==
5
5
  data.tar.gz: !binary |-
6
- Yjk4MTRiZjdjOTk1ZDQ5YjJjMTA3NzUyM2UyZmNjYmQyYTRkMWRkYg==
6
+ NjkyNGU1MmIwMDZkYTZiZWJhNjg2Njg3MTMxNWVkY2QzOTFiODcxNw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDg0NjMwZjU4ZWYzMThhOTRmMzQ1MmMyODc4MTQ5YTQwMTJkMGI5MmQyNjQy
10
- MmNlNTk1ZTI5N2EzOWEzZWZjOTc0Yjk2YWRkYTg0YjlkODQ4NzM4NjMzMDRi
11
- NTU4MTU1YzRjN2Q3ZjcxYjBmYTUxMTU5MDU2ZDFkN2E4ZTkwOGU=
9
+ NzRkNzY1YTIyZjg1MzQ3NGVmY2ZjMzEyNjFhYmRlNmFlMjU0YWJmZThlYWRk
10
+ YmQ4ZTJiMTgwZDhmYzQ1ODJhMjgzZWJmZjg2ODhkNDM3YzU1ZDMzNWI2M2Nh
11
+ ZjNjMjFiY2IwOWYxNzkxMjgyN2VkNmM3ZTYzNzU4Mzk0ODIyMzc=
12
12
  data.tar.gz: !binary |-
13
- NWJlMjNhYjEwZTdmMTUyYmU4Y2I2N2U1NzAyZTRmNGQ2ZjBlYzVmYjA1MGZm
14
- ZmRmNjkwYWYzYTllYTgxYWFiOTI5ZTljYzBkZjMwNTY5NTJjYmFkNWIwOTg1
15
- OTdkMGZmMGQ2Zjc1MGI4MWE0YjlhN2E1ZGMzN2E0MTk0MTIwNWE=
13
+ N2Y5MGE1M2IzZTQ5ZjdjMWRjMDIyMzU3MThlNTkxOTIzZDAzNzM1NmY1MzM5
14
+ MmVkMzE3YTVhYzI1ZDAxNjU2MmVmMTlkYmEzMTcxYzI2MWIwMjY0OWQ4Yjhm
15
+ NDkyODdmNzMyNGFiNGE2NjI2ZjdmZDZhZGY5M2JiMTE3MWY0ZWE=
data/README.md CHANGED
@@ -27,97 +27,53 @@ Or install it yourself as:
27
27
  following example
28
28
 
29
29
  ```ruby
30
- module Document
31
- class Category
32
- include DocumentBuilder::Model
33
- xpath 'category'
34
- attribute :domain, 'domain', DocumentBuilder::ElementAttribute
35
- attribute :nicename, 'nicename', DocumentBuilder::ElementAttribute
36
- attribute :body, nil, DocumentBuilder::ChildAttribute
37
- end
38
-
39
- class Postmeta
40
- include DocumentBuilder::Model
41
- xpath 'postmeta'
42
- attribute :key, "wp:meta_key"
43
- attribute :value, "wp:meta_value", DocumentBuilder::IntegerAttribute
44
- end
45
-
46
- class PostmetaCollection
47
- include DocumentBuilder::Collection
48
- xpath "item"
49
- collection :postmeta, "//wp:postmeta", Postmeta
50
- end
51
-
52
- class Post
53
- include DocumentBuilder::Model
54
- xpath "item"
55
- attribute :title
56
- attribute :link
57
- attribute :pub_date, "pubDate", DocumentBuilder::TimeAttribute
58
- attribute :creator, "dc:creator"
59
- attribute :content, "content:encoded"
60
- attribute :excerpt, "excerpt:encoded"
61
- attribute :id, "wp:post_id", DocumentBuilder::IntegerAttribute
62
- attribute :published_at, 'wp:post_date_gmt', DocumentBuilder::TimeAttribute
63
- attribute :comment_status, "wp:comment_status"
64
- attribute :ping_status, "wp:ping_status"
65
- attribute :name, 'wp:post_name'
66
- attribute :status, "wp:status"
67
- attribute :parent, "wp:post_parent", DocumentBuilder::IntegerAttribute
68
- attribute :menu_order, "wp:menu_order", DocumentBuilder::IntegerAttribute
69
- attribute :type, "wp:post_type"
70
- attribute :is_sticky, "wp:is_sticky", DocumentBuilder::IntegerAttribute
71
- attribute :category, "category", Category
72
- attribute :postmetas, 'item', PostmetaCollection
73
- end
30
+ class ListItem
31
+ include DocumentBuilder::Model
32
+ property :name, type: TextProperty
74
33
  end
75
34
 
76
- ### Using Model Objects
35
+ class SomeDocument
36
+ include DocumentBuilder::Model
37
+ root "//root"
38
+ collection :collection, selector: "//collection//inner-list-item", type: ListItem
39
+ collection :outer_collection, selector: "outer-list-item", type: ListItem
40
+ property :property, selector: "//property", type: TextProperty
41
+ end
77
42
  ```
78
43
 
79
44
  ```ruby
80
- # Read an xml file
81
- url = "https://raw.githubusercontent.com/bullfight/wrxer/master/spec/fixtures/wrx.xml"
82
- uri = URI.parse(url)
83
-
84
- uri.open do |file|
85
- document = Nokogiri::XML(file.read).xpath('//channel').at_xpath('item')}
86
- end
87
-
88
- post = Document::Post.call(document)
89
-
90
- => #<Wrxer::Post:0x3fd4799693ac> Attributes: {
91
- "title": "Welcome To Wrxer News.",
92
- "link": "https://wrxernews.wordpress.com/2007/11/17/welcome-to-wrxer-news/",
93
- "pub_date": "2007-11-17 21:30:51 +0000",
94
- "creator": "wrxernews",
95
- "content": "Welcome to <strong>Wrxer News</strong> - The most up-to-date and reliable source for Wrxer news.",
96
- "excerpt": "Excerpt Text",
97
- "id": 3,
98
- "published_at": "2007-11-17 21:30:51 -0800",
99
- "comment_status": "open",
100
- "ping_status": "open",
101
- "name": "welcome-to-wrxer-news",
102
- "status": "publish",
103
- "parent": 0,
104
- "menu_order": 0,
105
- "type": "post",
106
- "is_sticky": 0,
107
- "category": {
108
- "domain": "category",
109
- "nicename": "wrxer-news",
110
- "body": "Wrxer News"
111
- },
112
- "postmetas": {
113
- "data": "#<Enumerator::Lazy:0x007fa8f315a970>"
114
- },
115
- "comments": {
116
- "data": "#<Enumerator::Lazy:0x007fa8f315a3f8>"
117
- }
45
+ require 'document_builder'
46
+ require 'nokogiri'
47
+
48
+ DOCUMENT = <<-XML
49
+ <root>
50
+ <collection>
51
+ <inner-list-item>Inner Item 1</inner-list-item>
52
+ <inner-list-item>Inner Item 2</inner-list-item>
53
+ </collection>
54
+ <outer-list-item>Outer Item 1</outer-list-item>
55
+ <outer-list-item>Outer Item 2</outer-list-item>
56
+ <property>Some Property</property>
57
+ </root>
58
+ XML
59
+
60
+ document = Nokogiri::XML(DOCUMENT)
61
+ some_document = SomeDocument.new(document)
62
+
63
+ => #<SomeDocument:0x3fd4799693ac> Attributes: {
64
+ "collection": [
65
+ { "name": "Inner Item 1" },
66
+ { "name": "Inner Item 2" }
67
+ ],
68
+ "outer_collection": [
69
+ { "name": "Outer Item 1" },
70
+ { "name": "Outer Item 2" }
71
+ ],
72
+ "property": "Some Property"
118
73
  }
119
- post.title
120
- => "Welcome To Wrxer News."
74
+
75
+ some_document.property
76
+ => "Some Property"
121
77
  ```
122
78
 
123
79
  ## Contributing
@@ -4,9 +4,10 @@ require 'active_support/time'
4
4
  require 'json'
5
5
 
6
6
  require 'document_builder/coercion'
7
- require 'document_builder/attribute'
8
- require 'document_builder/model'
7
+ require 'document_builder/property'
9
8
  require 'document_builder/collection'
9
+ require 'document_builder/tag'
10
+ require 'document_builder/model'
10
11
 
11
12
  module DocumentBuilder
12
13
  end
@@ -1,16 +1,7 @@
1
1
  module DocumentBuilder
2
2
  module Coercion
3
3
  module ClassMethods
4
- def xpath(value)
5
- @xpath = value
6
- end
7
-
8
- def call(document, params = {})
9
- root = @xpath || params[:xpath]
10
- unless document.name == root
11
- document = document.at_xpath(root)
12
- end
13
-
4
+ def call(document)
14
5
  document.nil? ? nil : self.coerce(document)
15
6
  end
16
7
 
@@ -22,59 +13,35 @@ module DocumentBuilder
22
13
  def self.included(base)
23
14
  base.extend(ClassMethods)
24
15
  end
25
- end
26
-
27
- class TextAttribute
28
- include Coercion
29
- def self.coerce(document)
30
- document.text
31
- end
32
- end
33
-
34
- class IntegerAttribute
35
- include Coercion
36
- def self.coerce(document)
37
- Integer(document.text)
38
- end
39
- end
40
-
41
- class TimeAttribute
42
- include Coercion
43
- def self.coerce(document)
44
- Time.parse(document.text)
45
- end
46
- end
47
16
 
48
- class UtcTimeAttribute
49
- include Coercion
50
- def self.coerce(document)
51
- Time.use_zone("UTC") do
52
- Time.zone.parse(document.text)
17
+ class TextProperty
18
+ include Coercion
19
+ def self.coerce(document)
20
+ document.text
53
21
  end
54
22
  end
55
- end
56
-
57
- class ElementAttribute
58
- include Coercion
59
- def self.call(document, params = {})
60
- element = document.attributes[params[:xpath].to_s]
61
- element.nil? ? nil : self.coerce(element)
62
- end
63
23
 
64
- def self.coerce(document)
65
- document.value
24
+ class IntegerProperty
25
+ include Coercion
26
+ def self.coerce(document)
27
+ Integer(document.text)
28
+ end
66
29
  end
67
- end
68
30
 
69
- class ChildAttribute
70
- include Coercion
71
- def self.call(document, params = {})
72
- child = document.children
73
- child.empty? ? nil : self.coerce(child)
31
+ class TimeProperty
32
+ include Coercion
33
+ def self.coerce(document)
34
+ Time.parse(document.text)
35
+ end
74
36
  end
75
37
 
76
- def self.coerce(document)
77
- document.text
38
+ class UtcTimeProperty
39
+ include Coercion
40
+ def self.coerce(document)
41
+ Time.use_zone("UTC") do
42
+ Time.zone.parse(document.text)
43
+ end
44
+ end
78
45
  end
79
46
  end
80
47
  end
@@ -1,55 +1,40 @@
1
1
  module DocumentBuilder
2
- module Collection
3
- module ClassMethods
4
- def call(document, params = {})
5
- root = @xpath || params[:xpath]
6
- unless document.name == root
7
- document = document.xpath(root)
8
- end
9
-
10
- document.nil? ? nil : self.coerce(document)
11
- end
12
-
13
- def collection(value, xpath, parser)
14
- @collection = Attribute.new(value, xpath, parser)
15
- end
16
-
17
- def inherited(subclass)
18
- subclass.instance_variable_set(:@collection, @collection)
19
- super
20
- end
2
+ class Collection
3
+ include Enumerable
4
+ attr_reader :name, :selector, :type, :node
5
+
6
+ def initialize(name, selector:, type:)
7
+ @name = name
8
+ @selector = selector
9
+ @type = type
21
10
  end
22
11
 
23
- def self.included(base)
24
- base.extend(ClassMethods)
25
- base.class_eval do
26
- include Model
27
- include Enumerable
28
- end
29
- end
30
-
31
- def collection
32
- self.class.instance_variable_get(:@collection)
12
+ def call(document)
13
+ return nil if document.nil?
14
+ @node = document.xpath(selector)
15
+ self
33
16
  end
34
17
 
35
- def each(&block)
36
- document.xpath(collection.xpath).each do |item|
37
- block.call(
38
- collection.call(item)
39
- )
18
+ def each
19
+ @node.each do |element|
20
+ yield type.new(element)
40
21
  end
41
22
  end
42
23
 
43
- def data
44
- lazy
24
+ def to_s(*args)
25
+ JSON.pretty_generate(to_hash)
45
26
  end
46
27
 
47
28
  def inspect
48
- "#<#{self.class}:0x#{self.object_id.to_s(16)}> { data: #{data} } }"
29
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}> Attributes: " + JSON.pretty_generate(to_hash)
30
+ end
31
+
32
+ def to_json(*args)
33
+ JSON.generate(to_hash)
49
34
  end
50
35
 
51
36
  def to_hash
52
- { data: data }
37
+ entries.map(&:to_hash)
53
38
  end
54
39
  end
55
40
  end
@@ -1,23 +1,42 @@
1
1
  module DocumentBuilder
2
2
  module Model
3
3
  module ClassMethods
4
- def attribute(name, xpath = nil, coercion = TextAttribute)
5
- @attributes ||= []
6
- @attributes << Attribute.new(name, xpath || name.to_s, coercion)
4
+ def add_attribute(name, attribute)
5
+ @attributes ||= {}
6
+ @attributes[name.to_sym] = attribute
7
+ end
8
+
9
+ def property(name, selector: nil, type: nil)
10
+ add_attribute name, Property.new(name, selector: selector, type: type)
11
+ end
12
+
13
+ def tag(name, selector: nil, type: nil)
14
+ add_attribute name, Tag.new(name, selector: selector, type: type)
15
+ end
16
+
17
+ def collection(name, selector: nil, type: nil)
18
+ add_attribute name, Collection.new(name, selector: selector, type: type)
19
+ end
20
+
21
+ def root(selector)
22
+ @root = selector
7
23
  end
8
24
 
9
25
  def inherited(subclass)
10
26
  subclass.instance_variable_set(:@attributes, @attributes)
27
+ subclass.instance_variable_set(:@root, @root)
11
28
  super
12
29
  end
30
+
31
+ def call(document)
32
+ self.new(document)
33
+ end
13
34
  end
14
35
 
15
36
  def self.included(base)
16
37
  base.extend(ClassMethods)
17
38
  base.class_eval do
18
39
  include Coercion
19
-
20
- attr_reader :document
21
40
  end
22
41
  end
23
42
 
@@ -25,16 +44,40 @@ module DocumentBuilder
25
44
  @document = document
26
45
  end
27
46
 
47
+ def document
48
+ if root && @document.name != root
49
+ @document.at_xpath(root)
50
+ else
51
+ @document
52
+ end
53
+ end
54
+
55
+ def root
56
+ self.class.instance_variable_get(:@root)
57
+ end
58
+
28
59
  def attributes
29
60
  self.class.instance_variable_get(:@attributes)
30
61
  end
31
62
 
63
+ def get_attribute(name)
64
+ if respond_to?(name)
65
+ public_send(name)
66
+ else
67
+ attributes[name].call(document)
68
+ end
69
+ end
70
+
71
+ def add_attribute(name, attribute)
72
+ self.class.add_attribute(name, attribute)
73
+ end
74
+
32
75
  def [](key)
33
- attributes.select { |item| item.name == key.to_sym}.first.call(document)
76
+ get_attribute(key)
34
77
  end
35
78
 
36
79
  def method_missing(name, *args)
37
- attributes.select { |item| item.name == name }.first.call(document)
80
+ get_attribute(name)
38
81
  rescue NoMethodError => e
39
82
  raise NoMethodError.new("undefined method '#{name}' for #{self.class}")
40
83
  end
@@ -53,8 +96,8 @@ module DocumentBuilder
53
96
 
54
97
  def to_hash
55
98
  attributes.inject({}) do |acc, (key, value)|
56
- value = key.call(document)
57
- acc[key.name] = value.respond_to?(:to_hash) ? value.to_hash : value
99
+ obj = get_attribute(key)
100
+ acc[key] = obj.respond_to?(:to_hash) ? obj.to_hash : obj
58
101
  acc
59
102
  end
60
103
  end
@@ -0,0 +1,23 @@
1
+ module DocumentBuilder
2
+ class Property
3
+ attr_reader :name, :selector, :type, :node
4
+
5
+ def initialize(name, type: nil, selector: nil)
6
+ @name = name
7
+ @selector = selector
8
+ @type = type || Coercion::TextProperty
9
+ end
10
+
11
+ def call(document)
12
+ return nil if document.nil?
13
+
14
+ if selector.nil? || document.name == selector
15
+ @node = document
16
+ else
17
+ @node = document.at_xpath(selector)
18
+ end
19
+
20
+ type.call(@node)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ module DocumentBuilder
2
+ class Tag
3
+ attr_reader :name, :selector, :type, :node
4
+
5
+ def initialize(name, type: nil, selector: nil)
6
+ @name = name
7
+ @selector = selector
8
+ @type = type || Coercion::TextProperty
9
+ end
10
+
11
+ def call(document)
12
+ return nil if document.nil?
13
+
14
+ @node = selector.nil? ? document : document.attributes[selector]
15
+ type.call(@node)
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module DocumentBuilder
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+ require 'nokogiri'
3
+
4
+ RSpec.describe DocumentBuilder::Model do
5
+ DOCUMENT = <<-XML
6
+ <root>
7
+ <collection>
8
+ <inner-list-item>Inner Item 1</inner-list-item>
9
+ <inner-list-item>Inner Item 2</inner-list-item>
10
+ </collection>
11
+ <outer-list-item>Outer Item 1</outer-list-item>
12
+ <outer-list-item>Outer Item 2</outer-list-item>
13
+ <property>Some Property</property>
14
+ </root>
15
+ XML
16
+
17
+ let(:document) { Nokogiri::XML(DOCUMENT) }
18
+
19
+ class ListItem
20
+ include DocumentBuilder::Model
21
+ property :name, type: TextProperty
22
+ end
23
+
24
+ class SomeDocument
25
+ include DocumentBuilder::Model
26
+ root "//root"
27
+ collection :collection, selector: "//collection//inner-list-item", type: ListItem
28
+ collection :outer_collection, selector: "outer-list-item", type: ListItem
29
+ property :property, selector: "//property", type: TextProperty
30
+ end
31
+
32
+ subject { SomeDocument.new(document) }
33
+
34
+ it 'returns the root' do
35
+ expect(subject.root).to eq "//root"
36
+ end
37
+
38
+ it 'returns an innner collection' do
39
+ expect(subject.collection).to be_a DocumentBuilder::Collection
40
+ expect(subject.collection.first).to be_a ListItem
41
+ expect(subject.collection.first.name).to eq "Inner Item 1"
42
+ end
43
+
44
+ it 'returns an outer collection' do
45
+ expect(subject.outer_collection).to be_a DocumentBuilder::Collection
46
+ expect(subject.outer_collection.first).to be_a ListItem
47
+ expect(subject.outer_collection.first.name).to eq "Outer Item 1"
48
+ end
49
+
50
+ it 'returns a property' do
51
+ expect(subject.property).to eq "Some Property"
52
+ end
53
+ end
@@ -1,46 +1,38 @@
1
1
  module Document
2
2
  class Category
3
3
  include DocumentBuilder::Model
4
- xpath 'category'
5
- attribute :domain, 'domain', DocumentBuilder::ElementAttribute
6
- attribute :nicename, 'nicename', DocumentBuilder::ElementAttribute
7
- attribute :body, nil, DocumentBuilder::ChildAttribute
4
+ tag :domain, selector: 'domain'
5
+ tag :nicename, selector: 'nicename'
6
+ property :body, selector: 'category'
8
7
  end
9
8
 
10
9
  class Postmeta
11
10
  include DocumentBuilder::Model
12
- xpath 'postmeta'
13
- attribute :key, "wp:meta_key"
14
- attribute :value, "wp:meta_value", DocumentBuilder::IntegerAttribute
15
- end
16
-
17
- class PostmetaCollection
18
- include DocumentBuilder::Collection
19
- xpath "item"
20
- collection :postmeta, "//wp:postmeta", Postmeta
11
+ property :key, selector: "wp:meta_key"
12
+ property :value, selector: "wp:meta_value", type: IntegerProperty
21
13
  end
22
14
 
23
15
  class Post
24
16
  include DocumentBuilder::Model
25
- xpath "item"
26
- attribute :title
27
- attribute :link
28
- attribute :pub_date, "pubDate", DocumentBuilder::UtcTimeAttribute
29
- attribute :creator, "dc:creator"
30
- attribute :content, "content:encoded"
31
- attribute :excerpt, "excerpt:encoded"
32
- attribute :id, "wp:post_id", DocumentBuilder::IntegerAttribute
33
- attribute :post_date, 'wp:post_date', DocumentBuilder::TimeAttribute
34
- attribute :post_date_gmt, 'wp:post_date_gmt', DocumentBuilder::UtcTimeAttribute
35
- attribute :comment_status, "wp:comment_status"
36
- attribute :ping_status, "wp:ping_status"
37
- attribute :name, 'wp:post_name'
38
- attribute :status, "wp:status"
39
- attribute :parent, "wp:post_parent", DocumentBuilder::IntegerAttribute
40
- attribute :menu_order, "wp:menu_order", DocumentBuilder::IntegerAttribute
41
- attribute :type, "wp:post_type"
42
- attribute :is_sticky, "wp:is_sticky", DocumentBuilder::IntegerAttribute
43
- attribute :category, "category", Category
44
- attribute :postmetas, 'item', PostmetaCollection
17
+ root "//item"
18
+ property :title, selector: "title"
19
+ property :link, selector: "link"
20
+ property :pub_date, selector: "pubDate", type: UtcTimeProperty
21
+ property :creator, selector: "dc:creator"
22
+ property :content, selector: "content:encoded"
23
+ property :excerpt, selector: "excerpt:encoded"
24
+ property :id, selector: "wp:post_id", type: IntegerProperty
25
+ property :post_date, selector: 'wp:post_date', type: TimeProperty
26
+ property :post_date_gmt, selector: 'wp:post_date_gmt', type: UtcTimeProperty
27
+ property :comment_status, selector: "wp:comment_status"
28
+ property :ping_status, selector: "wp:ping_status"
29
+ property :name, selector: 'wp:post_name'
30
+ property :status, selector: "wp:status"
31
+ property :parent, selector: "wp:post_parent", type: IntegerProperty
32
+ property :menu_order, selector: "wp:menu_order", type: IntegerProperty
33
+ property :type, selector: "wp:post_type"
34
+ property :is_sticky, selector: "wp:is_sticky", type: IntegerProperty
35
+ property :category, selector: "//category", type: Category
36
+ collection :postmetas, selector: '//wp:postmeta', type: Postmeta
45
37
  end
46
38
  end
@@ -45,6 +45,8 @@ describe Document::Post do
45
45
 
46
46
  it 'has a category' do
47
47
  expect(subject.category).to be_a Document::Category
48
+ expect(subject.category.domain).to eq "category"
49
+ expect(subject.category.body).to eq "Wrxer News"
48
50
  end
49
51
 
50
52
  it 'has is_sticky' do
@@ -53,6 +55,7 @@ describe Document::Post do
53
55
 
54
56
  it 'has postmetas' do
55
57
  expect(subject.postmetas.first).to be_a Document::Postmeta
58
+ expect(subject.postmetas.first.key).to_not eq nil
56
59
  end
57
60
 
58
61
  it 'does not have a not foo' do
@@ -61,7 +64,7 @@ describe Document::Post do
61
64
  end
62
65
  end
63
66
 
64
- context "nil attribute case" do
67
+ context "nil property case" do
65
68
  let(:filename) { fixture('missing_fields.xml') }
66
69
  let(:document) { Nokogiri::XML(filename.read).xpath('//channel').at_xpath('item')}
67
70
  subject { described_class.call(document) }
@@ -85,7 +88,7 @@ describe Document::Post do
85
88
  subject { described_class.new(document) }
86
89
 
87
90
  it 'returns nil for category' do
88
- expect(subject.category).to eq nil
91
+ expect(subject.category).to be_a Document::Category
89
92
  end
90
93
  end
91
94
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: document_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Schmitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-09 00:00:00.000000000 Z
11
+ date: 2015-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -111,11 +111,13 @@ files:
111
111
  - Rakefile
112
112
  - document_builder.gemspec
113
113
  - lib/document_builder.rb
114
- - lib/document_builder/attribute.rb
115
114
  - lib/document_builder/coercion.rb
116
115
  - lib/document_builder/collection.rb
117
116
  - lib/document_builder/model.rb
117
+ - lib/document_builder/property.rb
118
+ - lib/document_builder/tag.rb
118
119
  - lib/document_builder/version.rb
120
+ - spec/document_builder/model_spec.rb
119
121
  - spec/document_builder_spec.rb
120
122
  - spec/fixtures/document.rb
121
123
  - spec/fixtures/missing_fields.xml
@@ -147,6 +149,7 @@ signing_key:
147
149
  specification_version: 4
148
150
  summary: A document builder for nokogiri documents.
149
151
  test_files:
152
+ - spec/document_builder/model_spec.rb
150
153
  - spec/document_builder_spec.rb
151
154
  - spec/fixtures/document.rb
152
155
  - spec/fixtures/missing_fields.xml
@@ -1,7 +0,0 @@
1
- module DocumentBuilder
2
- class Attribute < Struct.new(:name, :xpath, :coercion)
3
- def call(document, params = {})
4
- coercion.call(document, { xpath: xpath })
5
- end
6
- end
7
- end