hal-interpretation 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 307909b10b6823175a275e546f52f1b2451db046
4
+ data.tar.gz: bb0969dc221c78829b4fec9f0f1029395a3875f1
5
+ SHA512:
6
+ metadata.gz: c3cb5970235c8d729f3d7f4eaba0637cfce427fbefeb51f647cfc3f236df8c34e53046c17f3cbc778dacd13fac36a10f36d4783086ebd3282469f17631fb6bf9
7
+ data.tar.gz: 345c2f5de8ac2cad5f1fce84fd62848db9f8526bb762df1474fa8a957ad178d96ad4667c723ef3dbdcbe490081fe6bf55f1dfacec51e00f484f3cb7b93d8b9ad
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "2.1.1"
6
+ - jruby-19mode # JRuby in 1.9 mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hal-interpretation.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Peter Williams
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ [![Build Status](https://travis-ci.org/pezra/hal-interpretation.png?branch=master)](https://travis-ci.org/pezra/hal-interpretation)
2
+ [![Code Climate](https://codeclimate.com/github/pezra/hal-interpretation.png)](https://codeclimate.com/github/pezra/hal-interpretation)
3
+
4
+ # HalInterpretation
5
+
6
+ Build ActiveModels from HAL documents with good error messages
7
+ for validity issues.
8
+
9
+ ## Usage
10
+
11
+ `HalInterpretation` provides a DSL for declaring how to build one or
12
+ more `ActiveModel` objects from a HAL document.
13
+
14
+ ```ruby
15
+ class UserHalInterpreter
16
+ include HalInterpretation
17
+
18
+ item_class User
19
+
20
+ extract :name
21
+ extract :address_line, from: "address/line1"
22
+ end
23
+ ```
24
+
25
+ To interpret a HAL document simply create a new interpreter from the
26
+ JSON document to interpret and then call its `#items` method.
27
+
28
+ ```ruby
29
+ class Users < ApplicationController
30
+ def create
31
+ @users = UserHalInterpreter.new_from_json(request.raw_post).items
32
+
33
+ rescue HalInterpretation::InvalidRepresentationError => err
34
+ render template: "shared/error", status: 422, locals: { problems: err.problems }
35
+ end
36
+ end
37
+ ```
38
+
39
+ The `items` method returns an `Enumerable` of valid `item_class` objects.
40
+
41
+ ### Errors
42
+
43
+ If the JSON being interpreted is invalid or malformed
44
+ `HalInterpretation` provides a list of the problems encountered
45
+ through the `#problems` method. Each problem message includes a
46
+ [JSON pointer][] to the exact location in the original document that
47
+ caused the problem. This is true even when interpreting
48
+ [collections][] for example if name of the third user in a collection
49
+ is null the problem message would be
50
+
51
+ /_embedded/item/2/name cannot be blank
52
+
53
+ Validity is determined using the `#valid?` method of the models being
54
+ built.
55
+
56
+
57
+ ## Installation
58
+
59
+ Add this line to your application's Gemfile:
60
+
61
+ gem 'hal-interpretation'
62
+
63
+ And then execute:
64
+
65
+ $ bundle
66
+
67
+ Or install it yourself as:
68
+
69
+ $ gem install hal-interpretation
70
+
71
+ ## Contributing
72
+
73
+ 1. Fork it ( http://github.com/pezra/hal-interpretation/fork )
74
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
75
+ 3. Make your improvement
76
+ 4. Update the version following [semver][] rules
77
+ 5. Commit your changes (`git commit -am 'Add some feature'`)
78
+ 6. Push to the branch (`git push origin my-new-feature`)
79
+ 7. Create new Pull Request
80
+
81
+
82
+ [semver]: http://semver.org/
83
+ [json pointer]: http://tools.ietf.org/html/rfc6901
84
+ [collections]: https://tools.ietf.org/html/rfc6573
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hal_interpretation/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hal-interpretation"
8
+ spec.version = HalInterpretation::VERSION
9
+ spec.authors = ["Peter Williams"]
10
+ spec.email = ["pezra@barelyenough.org"]
11
+ spec.summary = %q{Build models from HAL documents.}
12
+ spec.description = %q{Declarative creation of ActiveModels from HAL documents.}
13
+ spec.homepage = "https://github.com/pezra/hal-interpretation"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = ">=1.9.3"
22
+
23
+ spec.add_dependency "hal-client", "~>2.2"
24
+ spec.add_dependency "hana", "~>1.2"
25
+ spec.add_dependency "multi_json", "~>1.9"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.5"
28
+ spec.add_development_dependency "rake", "~>10.1"
29
+ spec.add_development_dependency "rspec", "~>3.0.0.beta"
30
+ spec.add_development_dependency "rspec-collection_matchers", "~>0.0.3"
31
+ spec.add_development_dependency "activemodel", "~>4.0"
32
+ spec.add_development_dependency "activesupport", "~>4.0"
33
+ end
@@ -0,0 +1 @@
1
+ require "hal_interpretation"
@@ -0,0 +1,22 @@
1
+ module HalInterpretation
2
+ module Dsl
3
+ # Declare the class of models this interpreter builds.
4
+ def item_class(klass)
5
+ define_method(:item_class) do
6
+ klass
7
+ end
8
+ end
9
+
10
+ # Declare that an attribute should be extract from the HAL
11
+ # document.
12
+ #
13
+ # attr_name - name of attribute on model to extract
14
+ # opts - hash of named arguments to method
15
+ # :from - JSON path from which to get the value for
16
+ # attribute. Default: "/#{attr_name}"
17
+ def extract(attr_name, opts={})
18
+ from = opts.fetch(:from) { "/#{attr_name}" }
19
+ extractors << Extractor.new(attr: attr_name, location: from)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module HalInterpretation
2
+ Error = Class.new(StandardError)
3
+
4
+ class InvalidRepresentationError < Error
5
+ # Initializes a new instance of this error
6
+ #
7
+ # problems - list of problems detected with the representation.
8
+ def initialize(problems)
9
+ @problems = problems = Array(problems)
10
+
11
+ msg = problems.first
12
+ msg += " and #{problems.count - 1} more problems" if problems.count > 1
13
+
14
+ super msg
15
+ end
16
+
17
+ attr_reader :problems
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ require 'hana'
2
+
3
+ module HalInterpretation
4
+ class Extractor
5
+ # opts - named args
6
+ # :attr - name of attribute this object will extact.
7
+ # :location - JSON path from which to get the value.
8
+ def initialize(opts) #attr:, location: "/#{attr}")
9
+ @attr = opts.fetch(:attr) { fail ArgumentError, "attr is required" }
10
+ @location = opts.fetch(:location) { "/#{attr}" }
11
+ @pointer = Hana::Pointer.new(location)
12
+ end
13
+
14
+ # opts - named args
15
+ # :from - The HalRepresentation from which to extract attribute.
16
+ # :to - The model that we are extracting
17
+ #
18
+ # Returns any problems encountered.
19
+ def extract(opts)
20
+ from = opts.fetch(:from) { fail ArgumentError, "from is required" }
21
+ to = opts.fetch(:to) { fail ArgumentError, "to is required" }
22
+ to.send "#{attr}=", pointer.eval(from)
23
+
24
+ []
25
+ rescue => err
26
+ [err.message]
27
+ end
28
+
29
+ attr_reader :attr, :location
30
+
31
+ protected
32
+ attr_reader :pointer
33
+ end
34
+ end
@@ -0,0 +1,74 @@
1
+ module HalInterpretation
2
+ class ItemInterpreter
3
+ # opts - named args
4
+ # :location -
5
+ # :interpreter -
6
+ def initialize(a_representation, opts)
7
+ @repr = a_representation
8
+ @location = opts.fetch(:location) { fail ArgumentError, "location is required" }
9
+ @problems = []
10
+ @interpreter = opts.fetch(:interpreter) { fail ArgumentError, "interpreter is required" }
11
+ end
12
+
13
+ def items
14
+ interpret unless done?
15
+
16
+ (raise InvalidRepresentationError.new problems) if problems.any?
17
+
18
+ @items
19
+ end
20
+
21
+ def problems
22
+ interpret unless done?
23
+
24
+ @problems
25
+ end
26
+
27
+ protected
28
+
29
+ extend Forwardable
30
+
31
+ def_delegators :interpreter, :extractors, :extractor_for, :item_class
32
+
33
+ attr_reader :repr, :location, :interpreter
34
+
35
+ def done?
36
+ !@items.nil? || @problems.any?
37
+ end
38
+
39
+ def interpret
40
+ new_item = item_class.new do |it|
41
+ e = extractors
42
+ e.each do |an_extractor|
43
+ @problems += an_extractor.extract(from: repr, to: it)
44
+ .map {|msg| "#{json_path_for an_extractor.attr} #{msg}" }
45
+ end
46
+ end
47
+
48
+ apply_validations(new_item)
49
+
50
+ return if @problems.any?
51
+
52
+ @items = [new_item]
53
+ end
54
+
55
+ def apply_validations(an_item)
56
+ an_item.valid?
57
+ an_item.errors.each do |attr, msg|
58
+ @problems << "#{json_path_for attr} #{msg}"
59
+ end
60
+ end
61
+
62
+ def json_path_for(attr)
63
+ json_pointer_join(location, extractor_for(attr).location)
64
+ end
65
+
66
+ def json_pointer_join(head, tail)
67
+ head = head[0..-2] if head.end_with?("/")
68
+ tail = tail[1..-1] if tail.start_with?("/")
69
+
70
+ head + "/" + tail
71
+ end
72
+ end
73
+
74
+ end
@@ -0,0 +1,3 @@
1
+ module HalInterpretation
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,105 @@
1
+ require "forwardable"
2
+ require "multi_json"
3
+ require "hal-client"
4
+
5
+ # Declarative interpretation of HAL documents into ActiveModel style
6
+ # objects.
7
+ module HalInterpretation
8
+
9
+ # Returns array of models created from the HAL representation we are
10
+ # interpreting.
11
+ #
12
+ # Raises InvalidRepresentationError if any of the models are invalid
13
+ # or the representation is not a HAL document.
14
+ def items
15
+ (fail InvalidRepresentationError.new(problems)) if problems.any?
16
+
17
+ @observations ||= interpreters.flat_map(&:items)
18
+ end
19
+
20
+ # Returns array of problems messages, or empty array if there are
21
+ # none. This will do a complete interpretation of the representation
22
+ # if it has not already been done.
23
+ def problems
24
+ @problems ||= interpreters.flat_map(&:problems)
25
+ end
26
+
27
+ extend Forwardable
28
+ def_delegators "self.class", :extractors, :extractor_for
29
+
30
+ protected
31
+
32
+ # opts
33
+ # :location - The json path of `a_representation` in the
34
+ # complete document
35
+ def initialize(a_representation, opts)
36
+ @repr = a_representation
37
+ @location = opts.fetch(:location) { raise ArgumentError, "location is required" }
38
+ end
39
+
40
+ attr_reader :repr, :location
41
+
42
+ def interpreters
43
+ @interpreters ||=
44
+ begin
45
+ if repr.has_related? 'item'
46
+ repr
47
+ .related('item')
48
+ .each_with_index
49
+ .map{ |item_repr, idx|
50
+ ItemInterpreter.new(item_repr,
51
+ location: location + "_embedded/item/#{idx}/",
52
+ interpreter: self) }
53
+ else
54
+ [ItemInterpreter.new(repr, location: location, interpreter: self)]
55
+ end
56
+ end
57
+ end
58
+
59
+ # Back stop method to be overridden by individual interpreters.
60
+ def item_class
61
+ fail NotImplementedError, "interpreter classes must call `item_class <model class>` in the class defintion"
62
+ end
63
+
64
+ module ClassMethods
65
+ # Returns new interpreter for the provided JSON document.
66
+ #
67
+ # Raises HalInterpretation::InvalidRepresentationError if the
68
+ # provided JSON document is not parseable
69
+ def new_from_json(json)
70
+ self.new HalClient::Representation.new(parsed_json: MultiJson.load(json)),
71
+ location: "/"
72
+
73
+ rescue MultiJson::ParseError => err
74
+ fail InvalidRepresentationError, "Parse error: " + err.message
75
+ end
76
+
77
+ # internal stuff
78
+
79
+ # Returns collection of attribute extractors.
80
+ def extractors
81
+ @extractors ||= []
82
+ end
83
+
84
+ # Returns the attribute extractor for the specified attribute.
85
+ def extractor_for(attr_name)
86
+ extractors.find {|it| it.attr == attr_name }
87
+ end
88
+ end
89
+
90
+
91
+ def self.included(klass)
92
+ klass.extend ClassMethods
93
+ klass.extend Dsl
94
+ end
95
+
96
+
97
+ autoload :Dsl, "hal_interpretation/dsl"
98
+ autoload :ItemInterpreter, "hal_interpretation/item_interpreter"
99
+ autoload :Extractor, "hal_interpretation/extractor"
100
+ autoload :Error, "hal_interpretation/errors"
101
+ autoload :InvalidRepresentationError, "hal_interpretation/errors"
102
+
103
+ end
104
+
105
+ require "hal_interpretation/version"
@@ -0,0 +1,150 @@
1
+ require_relative "spec_helper"
2
+ require "active_support"
3
+ require "active_model"
4
+ require "rspec/collection_matchers"
5
+
6
+ describe HalInterpretation do
7
+ subject(:interpreter_class) {
8
+ test_item_class = self.test_item_class
9
+ Class.new do
10
+ include HalInterpretation
11
+ item_class test_item_class
12
+ extract :name
13
+ extract :latitude, from: "/geo/latitude"
14
+ end }
15
+
16
+ context "valid single item" do
17
+ let(:json_doc) { <<-JSON }
18
+ { "name": "foo"
19
+ ,"geo": {
20
+ "latitude": 39.1
21
+ }
22
+ }
23
+ JSON
24
+
25
+ specify { expect(interpreter.items).to have(1).item }
26
+ specify { expect(interpreter.items.first.name).to eq "foo" }
27
+ specify { expect(interpreter.items.first.latitude).to eq 39.1 }
28
+ specify { expect(interpreter.problems).to be_empty }
29
+ end
30
+
31
+ context "valid collection" do
32
+ let(:json_doc) { <<-JSON }
33
+ { "_embedded": {
34
+ "item": [{ "name": "foo"
35
+ ,"geo": {
36
+ "latitude": 39.1
37
+ }
38
+ }
39
+ ,{ "name": "bar"
40
+ ,"geo": {
41
+ "latitude": 39.2
42
+ }
43
+ }]
44
+ }
45
+ }
46
+ JSON
47
+
48
+ specify { expect(interpreter.problems).to be_empty }
49
+ specify { expect(interpreter.items).to have(2).items }
50
+ specify { expect(interpreter.items).to include item_named "foo" }
51
+ specify { expect(interpreter.items).to include item_named "bar" }
52
+
53
+ matcher :item_named do |expected_name|
54
+ match do |obj|
55
+ obj.name == expected_name
56
+ end
57
+ end
58
+ end
59
+
60
+ context "invalid attributes" do
61
+ let(:json_doc) { <<-JSON }
62
+ { "geo": {
63
+ "latitude": "hello"
64
+ }
65
+ }
66
+ JSON
67
+
68
+ specify { expect{interpreter.items}
69
+ .to raise_exception HalInterpretation::InvalidRepresentationError }
70
+ context "raised error" do
71
+ subject(:error) { interpreter.items rescue $! }
72
+
73
+ specify { expect(error.problems)
74
+ .to include matching matching(%r(/geo/latitude\b)).and(match(/\binvalid value\b/i)) }
75
+ specify { expect(error.problems)
76
+ .to include matching(%r(/name\b)).and(match(/\bblank\b/i)) }
77
+ end
78
+ specify { expect(interpreter.problems)
79
+ .to include matching(%r(/name\b)).and(match(/\bblank\b/i)) }
80
+ specify { expect(interpreter.problems)
81
+ .to include matching(%r(/geo/latitude\b)).and(match(/\binvalid value\b/i)) }
82
+ end
83
+
84
+ context "collection w/ invalid attributes" do
85
+ let(:json_doc) { <<-JSON }
86
+ { "_embedded": {
87
+ "item": [{ "geo": {
88
+ "latitude": "hello"
89
+ }
90
+ }]
91
+ }
92
+ }
93
+ JSON
94
+
95
+ specify { expect{interpreter.items}
96
+ .to raise_exception HalInterpretation::InvalidRepresentationError }
97
+ specify { expect(interpreter.problems)
98
+ .to include matching(%r(/_embedded/item/0/name\b)).and(match(/\bblank\b/i)) }
99
+ specify { expect(interpreter.problems)
100
+ .to include matching(%r(/_embedded/item/0/geo/latitude\b))
101
+ .and(match(/\binvalid value\b/i)) }
102
+
103
+ end
104
+
105
+ context "missing compound member" do
106
+ let(:json_doc) { <<-JSON }
107
+ { "name": "nowhere" }
108
+ JSON
109
+
110
+ specify { expect{interpreter.items}
111
+ .to raise_exception HalInterpretation::InvalidRepresentationError}
112
+ specify { expect(interpreter.problems)
113
+ .to include matching(%r(/geo/latitude\b)).and(match(/\bblank\b/i)) }
114
+ end
115
+
116
+
117
+ context "non-json doc" do
118
+ let(:non_json_doc) { "what's json" }
119
+
120
+ specify { expect{interpreter_class.new_from_json(non_json_doc)}
121
+ .to raise_exception HalInterpretation::InvalidRepresentationError, /\bparse\b/i }
122
+ end
123
+
124
+ let(:interpreter) { interpreter_class.new_from_json(json_doc) }
125
+
126
+ let(:test_item_class) { Class.new do
127
+ include ActiveModel::Validations
128
+
129
+ attr_accessor :name, :latitude
130
+
131
+ def initialize
132
+ yield self
133
+ end
134
+
135
+ def latitude=(lat)
136
+ @latitude = if !lat.nil?
137
+ Float(lat)
138
+ else
139
+ nil
140
+ end
141
+ end
142
+
143
+ def self.model_name
144
+ ActiveModel::Name.new(self, nil, "temp")
145
+ end
146
+
147
+ validates :name, presence: true
148
+ validates :latitude, presence: true
149
+ end }
150
+ end
@@ -0,0 +1 @@
1
+ require "hal-interpretation"
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hal-interpretation
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hal-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: hana
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: multi_json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.9'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '10.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '10.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 3.0.0.beta
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 3.0.0.beta
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-collection_matchers
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 0.0.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: activemodel
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '4.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: '4.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: activesupport
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: '4.0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: '4.0'
139
+ description: Declarative creation of ActiveModels from HAL documents.
140
+ email:
141
+ - pezra@barelyenough.org
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - .gitignore
147
+ - .travis.yml
148
+ - Gemfile
149
+ - LICENSE.txt
150
+ - README.md
151
+ - Rakefile
152
+ - hal-interpretation.gemspec
153
+ - lib/hal-interpretation.rb
154
+ - lib/hal_interpretation.rb
155
+ - lib/hal_interpretation/dsl.rb
156
+ - lib/hal_interpretation/errors.rb
157
+ - lib/hal_interpretation/extractor.rb
158
+ - lib/hal_interpretation/item_interpreter.rb
159
+ - lib/hal_interpretation/version.rb
160
+ - spec/hal_interpretation_spec.rb
161
+ - spec/spec_helper.rb
162
+ homepage: https://github.com/pezra/hal-interpretation
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - '>='
173
+ - !ruby/object:Gem::Version
174
+ version: 1.9.3
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - '>='
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project:
182
+ rubygems_version: 2.0.3
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: Build models from HAL documents.
186
+ test_files:
187
+ - spec/hal_interpretation_spec.rb
188
+ - spec/spec_helper.rb