dm-grape-hypertext_application_language 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9622d1a9adcd27fa3afe257b96b72cf42747d8ff
4
+ data.tar.gz: aaff528b3cbf07283f78f82bf1443cb679ae3c3f
5
+ SHA512:
6
+ metadata.gz: 9fbfbdb83df6dba07a37dc2d8a75f2116c1d39f42a555a37a0d7663cc1c343598082b88be903ac0df7d966ad49a583eff68d76f22aad8ff10c2870c6224ffede
7
+ data.tar.gz: 060dd2664ac27bb5bb14cf6b7a0d817e6fa3e2a3072d75ec2fa73a5461e6b3dd3b36d6dd4c7368a69d762cf2983df2a61af36fccb88835070214e962d79d061f
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ # Ignore everything beneath the +pkg+ folder. The Bundler +build+ task places
2
+ # +*.gem+ packages in this folder.
3
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ # %w(dm grape).each do |ext|
6
+ # name = ext + '-hypertext_application_language'
7
+ # path File.join(File.dirname(__FILE__), '..', name) do
8
+ # gem name
9
+ # end
10
+ # end
data/Gemfile.lock ADDED
@@ -0,0 +1,125 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dm-grape-hypertext_application_language (0.0.0)
5
+ data_mapper
6
+ grape-hypertext_application_language
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (4.2.4)
12
+ i18n (~> 0.7)
13
+ json (~> 1.7, >= 1.7.7)
14
+ minitest (~> 5.1)
15
+ thread_safe (~> 0.3, >= 0.3.4)
16
+ tzinfo (~> 1.1)
17
+ addressable (2.3.8)
18
+ axiom-types (0.1.1)
19
+ descendants_tracker (~> 0.0.4)
20
+ ice_nine (~> 0.11.0)
21
+ thread_safe (~> 0.3, >= 0.3.1)
22
+ bcrypt (3.1.10)
23
+ bcrypt (3.1.10-java)
24
+ bcrypt-ruby (3.1.5)
25
+ bcrypt (>= 3.1.3)
26
+ bcrypt-ruby (3.1.5-java)
27
+ bcrypt (>= 3.1.3)
28
+ builder (3.2.2)
29
+ coercible (1.0.0)
30
+ descendants_tracker (~> 0.0.1)
31
+ data_mapper (1.2.0)
32
+ dm-aggregates (~> 1.2.0)
33
+ dm-constraints (~> 1.2.0)
34
+ dm-core (~> 1.2.0)
35
+ dm-migrations (~> 1.2.0)
36
+ dm-serializer (~> 1.2.0)
37
+ dm-timestamps (~> 1.2.0)
38
+ dm-transactions (~> 1.2.0)
39
+ dm-types (~> 1.2.0)
40
+ dm-validations (~> 1.2.0)
41
+ descendants_tracker (0.0.4)
42
+ thread_safe (~> 0.3, >= 0.3.1)
43
+ dm-aggregates (1.2.0)
44
+ dm-core (~> 1.2.0)
45
+ dm-constraints (1.2.0)
46
+ dm-core (~> 1.2.0)
47
+ dm-core (1.2.1)
48
+ addressable (~> 2.3)
49
+ dm-migrations (1.2.0)
50
+ dm-core (~> 1.2.0)
51
+ dm-serializer (1.2.2)
52
+ dm-core (~> 1.2.0)
53
+ fastercsv (~> 1.5)
54
+ json (~> 1.6)
55
+ json_pure (~> 1.6)
56
+ multi_json (~> 1.0)
57
+ dm-timestamps (1.2.0)
58
+ dm-core (~> 1.2.0)
59
+ dm-transactions (1.2.0)
60
+ dm-core (~> 1.2.0)
61
+ dm-types (1.2.2)
62
+ bcrypt-ruby (~> 3.0)
63
+ dm-core (~> 1.2.0)
64
+ fastercsv (~> 1.5)
65
+ json (~> 1.6)
66
+ multi_json (~> 1.0)
67
+ stringex (~> 1.4)
68
+ uuidtools (~> 2.1)
69
+ dm-validations (1.2.0)
70
+ dm-core (~> 1.2.0)
71
+ equalizer (0.0.11)
72
+ fastercsv (1.5.5)
73
+ grape (0.13.0)
74
+ activesupport
75
+ builder
76
+ hashie (>= 2.1.0)
77
+ multi_json (>= 1.3.2)
78
+ multi_xml (>= 0.5.2)
79
+ rack (>= 1.3.0)
80
+ rack-accept
81
+ rack-mount
82
+ virtus (>= 1.0.0)
83
+ grape-hypertext_application_language (0.0.0)
84
+ addressable
85
+ grape
86
+ hypertext_application_language
87
+ hashie (3.4.3)
88
+ hypertext_application_language (0.0.1)
89
+ i18n (0.7.0)
90
+ ice_nine (0.11.1)
91
+ json (1.8.3)
92
+ json (1.8.3-java)
93
+ json_pure (1.8.3)
94
+ minitest (5.8.2)
95
+ multi_json (1.11.2)
96
+ multi_xml (0.5.5)
97
+ rack (1.6.4)
98
+ rack-accept (0.4.5)
99
+ rack (>= 0.4)
100
+ rack-mount (0.8.3)
101
+ rack (>= 1.0.0)
102
+ rake (10.4.2)
103
+ stringex (1.5.1)
104
+ thread_safe (0.3.5)
105
+ thread_safe (0.3.5-java)
106
+ tzinfo (1.2.2)
107
+ thread_safe (~> 0.1)
108
+ uuidtools (2.1.5)
109
+ virtus (1.0.5)
110
+ axiom-types (~> 0.1)
111
+ coercible (~> 1.0)
112
+ descendants_tracker (~> 0.0, >= 0.0.3)
113
+ equalizer (~> 0.0, >= 0.0.9)
114
+
115
+ PLATFORMS
116
+ java
117
+ ruby
118
+
119
+ DEPENDENCIES
120
+ bundler
121
+ dm-grape-hypertext_application_language!
122
+ rake
123
+
124
+ BUNDLED WITH
125
+ 1.10.6
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'dm-grape-hypertext_application_language'
3
+ spec.version = '0.0.0'
4
+ spec.summary = %q{Data Mapper and Grape extensions for Hypertext Application Language}
5
+ spec.description = %q{}
6
+ spec.homepage = 'http://stateless.co/hal_specification.html'
7
+ spec.authors = ['Roy Ratcliffe']
8
+ spec.email = ['roy@pioneeringsoftware.co.uk']
9
+ spec.files = `git ls-files -z`.split("\x0")
10
+ spec.license = 'MIT'
11
+
12
+ spec.add_dependency 'data_mapper'
13
+ spec.add_dependency 'grape-hypertext_application_language'
14
+
15
+ spec.add_development_dependency 'bundler'
16
+ spec.add_development_dependency 'rake'
17
+ end
@@ -0,0 +1 @@
1
+ require 'hypertext_application_language/data_mapper/grape/api'
@@ -0,0 +1,98 @@
1
+ require 'data_mapper'
2
+ require 'hypertext_application_language'
3
+
4
+ module DataMapper
5
+ module Serializer
6
+ # Converts a Data Mapper resource to a hypertext application language (HAL)
7
+ # representation.
8
+ #
9
+ # The resulting representation contains links for each relationship. There
10
+ # are two main kinds of Data Mapper relationships: to-one and to-many. For
11
+ # to-many relationships, the links contain a reference to a sub-path for
12
+ # accessing or creating sub-resources based on the name of the
13
+ # relationship. If the relationship is to-one, then the link depends on
14
+ # whether or not the to-one association exists. If it does already exist,
15
+ # then the link references a root-level hypertext path to the resource by
16
+ # its relationship name and its unique identifier; assuming that path
17
+ # +relationship/identifier+ resolves to the existing resources
18
+ # representation.
19
+ def to_hal(*args)
20
+ representation = HypertextApplicationLanguage::Representation.new
21
+
22
+ rel = model.to_s.tableize
23
+ representation.with_link(HypertextApplicationLanguage::Link::SELF_REL, "#{rel}/#{id}")
24
+
25
+ model.relationships.each do |relationship|
26
+ association = __send__(relationship.name)
27
+ href = if association == nil || association.is_a?(DataMapper::Collection)
28
+ "#{representation.link.href}/#{relationship.name}"
29
+ else
30
+ "#{association.model.to_s.tableize}/#{association.id}"
31
+ end
32
+ representation.with_link(relationship.name, href)
33
+ end
34
+
35
+ exclude = model.properties(repository.name).map(&:name).select do |name|
36
+ name.to_s.end_with?('_id')
37
+ end + %i(id)
38
+
39
+ properties_to_serialize(exclude: exclude).map(&:name).each do |name|
40
+ value = __send__(name)
41
+ representation.with_property(name, value)
42
+ end
43
+
44
+ representation
45
+ end
46
+ end
47
+
48
+ class Collection
49
+ # Converts a collection to HAL. Represents a collection by constructing a
50
+ # set of embedded representations associated with a relation. The name of
51
+ # the relation is the table name of the collection's underlying model. The
52
+ # collection representation includes other useful pieces of information: the
53
+ # offset, limit and chunk size, useful for paging.
54
+ #
55
+ # Sends +each+ to the collection to access the individual
56
+ # resources. Converts each one to HAL then embeds the results within the
57
+ # resulting collection representation. The resulting collection
58
+ # representation both embeds the resources and includes links to the same
59
+ # resources.
60
+ #
61
+ # Only adds a link to self if the arguments include a Rack environment and
62
+ # the rack environment specifies the request path. This assumes that the
63
+ # request path is either an absolute path because it begins with a slash, or
64
+ # a relative path because higher-level Rack formatters will make the
65
+ # reference absolute by adding the base URL and script name.
66
+ #
67
+ # @return [HypertextApplicationLanguage::Representation]
68
+ # Representation of a collection of resources.
69
+ def to_hal(*args)
70
+ keyword_args = args.last.is_a?(Hash) ? args.pop : {}
71
+ representation = HypertextApplicationLanguage::Representation.new
72
+
73
+ if (env = keyword_args[:env]) && (href = env['REQUEST_PATH'])
74
+ representation.with_link(HypertextApplicationLanguage::Link::SELF_REL, href)
75
+ end
76
+
77
+ rel = model.to_s.tableize
78
+
79
+ each do |resource|
80
+ resource_representation = resource.to_hal(*args)
81
+ representation.with_link(rel, resource_representation.link.href)
82
+ representation.with_representation(rel, resource_representation)
83
+ end
84
+
85
+ %w(size).each do |name|
86
+ representation.with_property(name, __send__(name))
87
+ end
88
+ %w(offset limit).each do |name|
89
+ representation.with_property(name, query.__send__(name))
90
+ end
91
+ %w(count).each do |name|
92
+ representation.with_property(name, model.__send__(name, conditions: query.conditions))
93
+ end
94
+
95
+ representation
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,163 @@
1
+ require 'grape'
2
+ require 'data_mapper'
3
+ require 'active_support/core_ext/hash'
4
+
5
+ module HypertextApplicationLanguage
6
+ module DataMapper
7
+ module Grape
8
+ class API < ::Grape::API
9
+ route_param :model do
10
+ helpers do
11
+ # Takes the model name from the route path. Takes a string and
12
+ # answers a string, but the result is upper camel-case and singular.
13
+ # @return [String] Answers the name of the model based on the route
14
+ # parameter.
15
+ def model_name
16
+ params[:model].classify
17
+ end
18
+
19
+ def model
20
+ ::DataMapper::Model.descendants.select do |model|
21
+ model.name == model_name
22
+ end.first
23
+ end
24
+
25
+ # @return [Array<Symbol>] Answers the names of the model properties.
26
+ def property_names(model=model)
27
+ model.properties.map(&:name)
28
+ end
29
+
30
+ def attribute_names(property_names=property_names)
31
+ property_names.map(&:to_s).select do |name|
32
+ !name.end_with?('_id')
33
+ end - %w(id)
34
+ end
35
+
36
+ def attributes
37
+ params.slice(*attribute_names)
38
+ end
39
+
40
+ # The order parameter is an array of Data Mapper query
41
+ # directions. Each direction specifies a target property and a
42
+ # vector, ascending or descending, space delimited (or plus
43
+ # delimited after URL encoding). However, Grape cannot coerce the
44
+ # directions because directions need access to the model properties
45
+ # in order to construct the direction. The model comes from the
46
+ # helpers who only become available after parameter coercion and
47
+ # validation of parameters. Note that Grape _does_ coerce the order
48
+ # to an array even if the parameters do not specify an array.
49
+ def query(model=model)
50
+ query = declared(params, include_missing: true)
51
+ if query.order
52
+ query.order.map! do |direction|
53
+ target, operator = direction.split(' ', 2)
54
+ property = model.properties[target]
55
+ error! "no property named #{target}" unless property
56
+ ::DataMapper::Query::Direction.new(property, operator || 'asc')
57
+ end
58
+ end
59
+ query.to_h.symbolize_keys
60
+ end
61
+ end
62
+
63
+ params do
64
+ optional :offset, type: Integer, default: 0
65
+ optional :limit, type: Integer, default: 30
66
+ optional :order, type: [String]
67
+ end
68
+ get do
69
+ model.all(query)
70
+ end
71
+
72
+ post do
73
+ resource = model.create(attributes)
74
+ error! resource.errors.full_messages unless resource.save
75
+ resource
76
+ end
77
+
78
+ route_param :id do
79
+ helpers do
80
+ def resource
81
+ model.get(params[:id])
82
+ end
83
+ end
84
+
85
+ get do
86
+ resource
87
+ end
88
+
89
+ patch do
90
+ resource = self.resource
91
+ resource.update(attributes)
92
+ error! resource.errors.full_messages unless resource.save
93
+ resource
94
+ end
95
+
96
+ delete do
97
+ resource = self.resource
98
+ error! unless resource.destroy
99
+ end
100
+
101
+ route_param :relationship do
102
+ helpers do
103
+ def relationship_name
104
+ params[:relationship]
105
+ end
106
+
107
+ def relationship
108
+ resource.model.relationships.select do |relationship|
109
+ relationship.name.to_s == relationship_name
110
+ end.first
111
+ end
112
+
113
+ def target_model
114
+ relationship.target_model
115
+ end
116
+
117
+ def target_property_names
118
+ property_names(target_model)
119
+ end
120
+
121
+ def target_attribute_names
122
+ attribute_names(target_property_names)
123
+ end
124
+
125
+ def target_attributes
126
+ params.slice(*target_attribute_names)
127
+ end
128
+
129
+ def association
130
+ resource.__send__(relationship_name)
131
+ end
132
+
133
+ def association=(target)
134
+ resource.__send__("#{relationship_name}=", target)
135
+ end
136
+ end
137
+
138
+ params do
139
+ optional :offset, type: Integer, default: 0
140
+ optional :limit, type: Integer, default: 30
141
+ optional :order, type: [String]
142
+ end
143
+ get do
144
+ association.all(query(target_model))
145
+ end
146
+
147
+ post do
148
+ target = target_model.create(target_attributes)
149
+ if association.is_a?(::DataMapper::Collection)
150
+ association << target
151
+ else
152
+ self.assocation = target
153
+ end
154
+ error! target.errors.full_messages unless target.save
155
+ target
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-grape-hypertext_application_language
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Roy Ratcliffe
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: data_mapper
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: grape-hypertext_application_language
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: ''
70
+ email:
71
+ - roy@pioneeringsoftware.co.uk
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - Gemfile
78
+ - Gemfile.lock
79
+ - Rakefile
80
+ - dm-grape-hypertext_application_language.gemspec
81
+ - lib/dm-grape-hypertext_application_language.rb
82
+ - lib/dm-serializer/to_hal.rb
83
+ - lib/hypertext_application_language/data_mapper/grape/api.rb
84
+ homepage: http://stateless.co/hal_specification.html
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.4.8
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Data Mapper and Grape extensions for Hypertext Application Language
108
+ test_files: []