grape-hal 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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZGIyNjRkMTU5MDdhNTMzY2UyZjE2NzVjNDViMzcyZWMwZGMwZTUwNw==
5
+ data.tar.gz: !binary |-
6
+ YTY0ODMzZTY0ZWYxODhmMzMwYWYyNDI1MTIzMjVhNGRiNzhjMjZhZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjVhYTAwNGJmZmU1ZmIxNDE0YTdiZGQ5YjBiOWYxODRiNWE5MWQ1OWE4M2Y0
10
+ ZDVmYmM2NDFiMGExYzI4ODg2NTI4OWFhZWI1YjZmNWEzODA5NDYwZmMzMWZk
11
+ ZmM4YTc5OTIxOTNiMDI2ZjU0N2UwNDdkMDZmNTZlODNkM2E3YjM=
12
+ data.tar.gz: !binary |-
13
+ YzBiM2ZlMjJmOGM5ODMxMGQ5ZGUzOGNhYzA1NmI0MzEzNjQxYjA3NmFhZjAx
14
+ ZDRkNzM4NWY3YWIzMDk4OTk0OWVjZWM2NTBhY2Y5YjE2NzMwOGU3ZjA3NjM5
15
+ ZmZjZjU5YTE1NmQ1Yzg5NWQ5ZGE5YjlkNDAzMTNjNDI0MzRlMDI=
@@ -0,0 +1,2 @@
1
+ .idea/
2
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
@@ -0,0 +1,95 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ grape-hal (0.0.1)
5
+ grape
6
+ rack
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (4.0.2)
12
+ i18n (~> 0.6, >= 0.6.4)
13
+ minitest (~> 4.2)
14
+ multi_json (~> 1.3)
15
+ thread_safe (~> 0.1)
16
+ tzinfo (~> 0.3.37)
17
+ atomic (1.1.14)
18
+ axiom-types (0.0.5)
19
+ descendants_tracker (~> 0.0.1)
20
+ ice_nine (~> 0.9)
21
+ builder (3.2.2)
22
+ coderay (1.1.0)
23
+ coercible (1.0.0)
24
+ descendants_tracker (~> 0.0.1)
25
+ columnize (0.3.6)
26
+ debugger (1.6.4)
27
+ columnize (>= 0.3.1)
28
+ debugger-linecache (~> 1.2.0)
29
+ debugger-ruby_core_source (~> 1.3.0)
30
+ debugger-linecache (1.2.0)
31
+ debugger-ruby_core_source (1.3.0)
32
+ descendants_tracker (0.0.3)
33
+ diff-lcs (1.2.5)
34
+ equalizer (0.0.9)
35
+ grape (0.6.1)
36
+ activesupport
37
+ builder
38
+ hashie (>= 1.2.0)
39
+ multi_json (>= 1.3.2)
40
+ multi_xml (>= 0.5.2)
41
+ rack (>= 1.3.0)
42
+ rack-accept
43
+ rack-mount
44
+ virtus (>= 1.0.0)
45
+ hashie (2.0.5)
46
+ i18n (0.6.9)
47
+ ice_nine (0.11.0)
48
+ method_source (0.8.2)
49
+ minitest (4.7.5)
50
+ multi_json (1.8.2)
51
+ multi_xml (0.5.5)
52
+ pry (0.9.12.4)
53
+ coderay (~> 1.0)
54
+ method_source (~> 0.8)
55
+ slop (~> 3.4)
56
+ pry-debugger (0.2.2)
57
+ debugger (~> 1.3)
58
+ pry (~> 0.9.10)
59
+ rack (1.5.2)
60
+ rack-accept (0.4.5)
61
+ rack (>= 0.4)
62
+ rack-mount (0.8.3)
63
+ rack (>= 1.0.0)
64
+ rack-test (0.6.2)
65
+ rack (>= 1.0)
66
+ rake (10.0.4)
67
+ rspec (2.13.0)
68
+ rspec-core (~> 2.13.0)
69
+ rspec-expectations (~> 2.13.0)
70
+ rspec-mocks (~> 2.13.0)
71
+ rspec-core (2.13.1)
72
+ rspec-expectations (2.13.0)
73
+ diff-lcs (>= 1.1.3, < 2.0)
74
+ rspec-mocks (2.13.1)
75
+ slop (3.4.7)
76
+ thread_safe (0.1.3)
77
+ atomic
78
+ tzinfo (0.3.38)
79
+ virtus (1.0.1)
80
+ axiom-types (~> 0.0.5)
81
+ coercible (~> 1.0)
82
+ descendants_tracker (~> 0.0.1)
83
+ equalizer (~> 0.0.7)
84
+
85
+ PLATFORMS
86
+ ruby
87
+
88
+ DEPENDENCIES
89
+ bundler (~> 1.3)
90
+ grape-hal!
91
+ pry
92
+ pry-debugger
93
+ rack-test
94
+ rake (~> 10.0.4)
95
+ rspec
@@ -0,0 +1,98 @@
1
+ Grape Hal
2
+ =========
3
+
4
+ Description
5
+ -----------
6
+
7
+ A ruby gem which adds HAL support to ruby Grape Api.
8
+
9
+ HAL
10
+ ---
11
+
12
+ HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API. See [HAL (Hyperlink Application Language)](http://stateless.co/hal_specification.html)
13
+
14
+ Ruby Grape
15
+ ----------
16
+
17
+ github: [ruby grape api](https://github.com/intridea/grape)
18
+
19
+ Installation
20
+ ------------
21
+
22
+ Install the gem by:
23
+
24
+ gem install grape-hal
25
+
26
+ Or add the gem to your Gemfile
27
+
28
+ gem 'grape-hal'
29
+
30
+ Examples
31
+ --------
32
+
33
+ If you want to add Hal response to your exist Grape Api, just simply include `Grape::Hal` and then use the dsl to describe your Apis.
34
+
35
+ Here are some Grape Apis. Note the `include Grape::Hal` and `hal_for` block.
36
+
37
+ ```ruby
38
+ class FooApi < ::Grape::API
39
+ desc 'foo api description', rel: 'foo api'
40
+ get '/foo_path/'
41
+ end
42
+
43
+ class SubApi < ::Grape::API
44
+ desc 'bar api description with {param}', rel: 'bar api'
45
+ get 'bar_path/:param'
46
+
47
+ desc 'qux api description', rel: 'qux api'
48
+ get 'qux_path'
49
+ end
50
+
51
+ class BazApi < ::Grape::API
52
+
53
+ include Grape::Hal
54
+
55
+ mount FooApi
56
+ mount SubApi
57
+
58
+ hal_for '/' do
59
+ hal_for '/sub', rel: 'sub', title: 'a sub api module' do
60
+ mount SubApi
61
+ end
62
+ mount FooApi
63
+ end
64
+
65
+ end
66
+ ```
67
+
68
+ After this, when a http request to specific path with `json` format accept headers.
69
+
70
+ GET / HTTP/1.1
71
+ Accept: application/hal+json, application/json, */*; q=0.01
72
+
73
+ `grape/hal` will response with the Hal data for you.
74
+
75
+ HTTP/1.1 200 OK
76
+ Content-Type: application/hal+json
77
+
78
+ {
79
+ "_links": {
80
+ "self": {
81
+ "href": "/"
82
+ },
83
+ "sub": {
84
+ "href": "/sub",
85
+ "title": "a sub api module"
86
+ },
87
+ "foo api": {
88
+ "href": "/foo_path",
89
+ "title": "foo api description"
90
+ }
91
+ }
92
+ }
93
+
94
+ Footer
95
+ ------
96
+
97
+ Feng Zhichao flankerfc(at)gmail.com
98
+
@@ -0,0 +1,8 @@
1
+ require 'rspec/core'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |spec|
5
+ spec.pattern = FileList['spec/**/*_spec.rb']
6
+ end
7
+
8
+ task :default => [:spec]
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'grape-hal'
7
+ spec.version = '0.0.1'
8
+ spec.authors = ['Feng Zhichao']
9
+ spec.email = %w(flankerfc@gmail.com)
10
+ spec.description = %q{Provides the HAL response for Grape API application}
11
+ spec.summary = %q{HAL support for your Grape app}
12
+ spec.homepage = 'https://github.com/flanker/grape-hal'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = %w(lib)
19
+
20
+ spec.add_development_dependency 'bundler', '~> 1.3'
21
+ spec.add_development_dependency 'rake', '~> 10.0.4'
22
+ spec.add_development_dependency 'rspec'
23
+ spec.add_development_dependency 'rack-test'
24
+ spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'pry-debugger'
26
+
27
+ spec.add_runtime_dependency 'rack'
28
+ spec.add_runtime_dependency 'grape'
29
+ end
@@ -0,0 +1,13 @@
1
+ require 'grape'
2
+ require 'grape/hal/dsl'
3
+ require 'grape/hal/endpoint'
4
+
5
+ module Grape
6
+ module Hal
7
+
8
+ def self.included(base)
9
+ base.extend(Dsl)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Grape
2
+ module Hal
3
+ module Dsl
4
+
5
+ def hal_for(context_path, &block)
6
+ content_type :json, 'application/hal+json'
7
+
8
+ endpoint = Endpoint.new self, context_path
9
+ endpoint.instance_eval(&block)
10
+
11
+ get context_path do
12
+ base_url = env['PATH_INFO']
13
+ content_type 'application/hal+json'
14
+ endpoint.generate_hal base_url
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,87 @@
1
+ module Grape
2
+ module Hal
3
+ class Endpoint
4
+
5
+ include Dsl
6
+
7
+ attr_reader :entries, :context_path, :current_api
8
+
9
+ def initialize(current_api, context_path)
10
+ @current_api = current_api
11
+ @context_path = context_path
12
+ @entries = []
13
+ add_self
14
+ end
15
+
16
+ def hal_for(path, options = {}, &block)
17
+ entries << {
18
+ path: path,
19
+ rel: options[:rel],
20
+ title: options[:title]
21
+ }
22
+ current_api.hal_for path, &block
23
+ end
24
+
25
+ def mount(api)
26
+ api.endpoints.each do |endpoint|
27
+ options = endpoint.options
28
+ options[:path].each do |path|
29
+ entries << {
30
+ path: path,
31
+ rel: options[:route_options][:rel],
32
+ title: options[:route_options][:description]
33
+ }
34
+ end
35
+ end
36
+ end
37
+
38
+ def generate_hal(base_path)
39
+ hal_array = entries.map do |entry|
40
+ key = entry[:rel] || entry[:path]
41
+
42
+ value = {href: get_full_path(base_path, entry)}
43
+ value[:title] = entry[:title] if entry[:title]
44
+ value[:templated] = true if is_templated?(entry)
45
+ [key, value]
46
+ end
47
+ {:_links => Hash[hal_array]}
48
+ end
49
+
50
+ private
51
+
52
+ def add_self
53
+ self_entry = {
54
+ path: '',
55
+ rel: 'self'
56
+ }
57
+ entries << self_entry
58
+ end
59
+
60
+ def get_full_path(base_path, entry)
61
+ base_path = remove_parent_context_path(base_path) unless entry[:rel] === 'self'
62
+ handle_path = parameterize(entry)
63
+ File.join(base_path + handle_path)
64
+ end
65
+
66
+ def parameterize(entry)
67
+ entry[:path].split('/').map do |segment|
68
+ segment = '{' + segment[1..-1] + '}' if segment.start_with?(':')
69
+ segment
70
+ end.join('/')
71
+ end
72
+
73
+ def remove_parent_context_path(base_path)
74
+ if base_path.end_with?(context_path)
75
+ slice_to = base_path.rindex(context_path)
76
+ base_path = base_path.slice(0, slice_to)
77
+ end
78
+ base_path
79
+ end
80
+
81
+ def is_templated?(entry)
82
+ entry[:path].split('/').any? { |s| s.start_with?(':') }
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ module IntegrationTests
4
+
5
+ class FooApi < ::Grape::API
6
+ desc 'foo api description', rel: 'foo api'
7
+ get '/foo_path/'
8
+ end
9
+
10
+ class SubApi < ::Grape::API
11
+ desc 'bar api description with {param}', rel: 'bar api'
12
+ get 'bar_path/:param'
13
+
14
+ desc 'qux api description', rel: 'qux api'
15
+ get 'qux_path'
16
+ end
17
+
18
+ class BazApi < ::Grape::API
19
+
20
+ after do
21
+ header 'Access-Control-Allow-Origin', '*'
22
+ end
23
+
24
+ include Grape::Hal
25
+
26
+ mount FooApi
27
+ mount SubApi
28
+
29
+ hal_for '/' do
30
+ hal_for '/sub', rel: 'sub', title: 'a sub api module' do
31
+ mount SubApi
32
+ end
33
+ mount FooApi
34
+ end
35
+
36
+ end
37
+
38
+ describe 'Hal for grape' do
39
+
40
+ include Rack::Test::Methods
41
+
42
+ def app
43
+ Rack::Builder.new do
44
+ run BazApi
45
+ end
46
+ end
47
+
48
+ describe 'root path' do
49
+
50
+ subject {
51
+ response = get '/', :format => 'json'
52
+ JSON.parse(response.body)['_links']
53
+ }
54
+
55
+ it { should == {
56
+ 'self' => {
57
+ 'href' => '/'
58
+ },
59
+ 'sub' => {
60
+ 'href' => '/sub',
61
+ 'title' => 'a sub api module'
62
+ },
63
+ 'foo api' => {
64
+ 'href' => '/foo_path',
65
+ 'title' => 'foo api description'
66
+ }
67
+ }}
68
+
69
+ end
70
+
71
+
72
+ end
73
+ end
@@ -0,0 +1,5 @@
1
+ require 'rack'
2
+ require 'rack/test'
3
+ require 'json'
4
+
5
+ require 'grape/hal'
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grape-hal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Feng Zhichao
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-01-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 10.0.4
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 10.0.4
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: rack-test
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
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-debugger
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: grape
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Provides the HAL response for Grape API application
126
+ email:
127
+ - flankerfc@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .gitignore
133
+ - Gemfile
134
+ - Gemfile.lock
135
+ - README.md
136
+ - Rakefile
137
+ - grape-hal.gemspec
138
+ - lib/grape/hal.rb
139
+ - lib/grape/hal/dsl.rb
140
+ - lib/grape/hal/endpoint.rb
141
+ - spec/integration_tests/hal_for_grape_spec.rb
142
+ - spec/spec_helper.rb
143
+ homepage: https://github.com/flanker/grape-hal
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.0.14
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: HAL support for your Grape app
167
+ test_files:
168
+ - spec/integration_tests/hal_for_grape_spec.rb
169
+ - spec/spec_helper.rb