grape-hal 0.0.1

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