api_me 0.2.0 → 0.3.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 +4 -4
- data/README.md +22 -2
- data/Rakefile +38 -5
- data/api_me.gemspec +20 -18
- data/lib/api_me.rb +28 -33
- data/lib/api_me/version.rb +1 -1
- data/lib/generators/api_me/controller/controller_generator.rb +11 -11
- data/lib/generators/api_me/policy/policy_generator.rb +6 -6
- data/lib/generators/api_me/resource/resource_generator.rb +4 -4
- data/spec/acceptance/api/v1/fails_spec.rb +1 -1
- data/spec/acceptance/api/v1/users_spec.rb +11 -11
- data/spec/internal/app/controllers/api/v1/fails_controller.rb +1 -1
- data/spec/internal/app/controllers/application_controller.rb +1 -1
- data/spec/internal/app/policies/application_policy.rb +1 -1
- data/spec/internal/db/schema.rb +4 -4
- data/spec/spec_helper.rb +2 -2
- metadata +31 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47cb01169b34ee2781c7a1780659b99605797343
|
4
|
+
data.tar.gz: 8a19a3832d2cf1cdc9e663f52949d58e00aa3dc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6aae861edb9a28dee94fbdc56eac28a0a79efa2c765071d87ad7c90e5517ea05925489851a5979fceb5129c3eec7dc231b0af8d85c4769e6452f03ecd82a1b4d
|
7
|
+
data.tar.gz: ac8a6dbcbaf4472be7216ffabca39bbbc7bbc85fe8ed0987cbeb6e6ff2079b35dfb5550e5d062a9bda20050cb9ba8c1d8dda04996d4e74cc1332049aa3276aeb
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[](http://badge.fury.io/rb/api_me) [](https://travis-ci.org/inigo-llc/api_me) [](https://codeclimate.com/github/inigo-llc/api_me) [](http://badge.fury.io/rb/api_me) [](https://travis-ci.org/inigo-llc/api_me) [](https://codeclimate.com/github/inigo-llc/api_me) [](https://gemnasium.com/inigo-llc/api_me)
|
2
2
|
ApiMe
|
3
3
|
=========
|
4
4
|
|
@@ -7,12 +7,32 @@ ApiMe
|
|
7
7
|
### A gem for building RESTful Api resources in Rails
|
8
8
|
ApiMe provides a set of generators and base classes to assist with building Restful API's in Ruby on Rails.
|
9
9
|
|
10
|
+
### Usage
|
11
|
+
`rails g api_me:resource user organization:belongs_to name:string ...`
|
12
|
+
|
13
|
+
this generates the following:
|
14
|
+
|
15
|
+
* app/controllers/api/v1/users_controller.rb
|
16
|
+
* app/policies/user_policy.rb
|
17
|
+
* app/serializers/user_serializer.rb
|
18
|
+
* app/models/user.rb
|
19
|
+
|
20
|
+
Or
|
21
|
+
|
22
|
+
users_controller.rb
|
23
|
+
````rb
|
24
|
+
class UsersController < ApplicationController
|
25
|
+
include ApiMe
|
26
|
+
end
|
27
|
+
````
|
28
|
+
|
10
29
|
#### This gem uses the following libraries:
|
11
30
|
* Pundit
|
12
31
|
* Active Model Serializers (0.8)
|
13
32
|
|
14
33
|
#### Todo:
|
15
|
-
|
34
|
+
- [ ] Add the ability to specify resource filters
|
35
|
+
- [ ] Add the ability to specify the api controller path (I.E. app/controllers/api/v2)
|
16
36
|
|
17
37
|
## License
|
18
38
|
Copyright (c) 2014, Api Me is developed and maintained by Sam Clopton, and is released under the open MIT Licence.
|
data/Rakefile
CHANGED
@@ -1,11 +1,44 @@
|
|
1
1
|
require 'bundler'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rake/notes/rake_task'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
2
6
|
|
3
7
|
Bundler::GemHelper.install_tasks
|
4
8
|
|
5
9
|
task :console do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
require 'irb'
|
11
|
+
require 'irb/completion'
|
12
|
+
require 'api_me' # You know what to do.
|
13
|
+
ARGV.clear
|
14
|
+
IRB.start
|
15
|
+
end
|
16
|
+
|
17
|
+
task default: 'reports:all'
|
18
|
+
|
19
|
+
namespace :reports do
|
20
|
+
task all: [:fixme_notes, :rubocop, :spec]
|
21
|
+
|
22
|
+
task :rubocop do
|
23
|
+
system 'bundle exec rubocop --rails --display-cop-names'
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Create a report on all notes'
|
27
|
+
task :notes do
|
28
|
+
puts "\nCollecting all of the standard code notes..."
|
29
|
+
system 'bundle exec rake notes'
|
30
|
+
puts "\nCollecting all HACK code notes..."
|
31
|
+
system 'bundle exec rake notes:custom ANNOTATION=HACK'
|
32
|
+
puts "\nCollecting all spec code notes..."
|
33
|
+
system "grep -rnE 'OPTIMIZE:|OPTIMIZE|FIXME:|FIXME|TODO:|TODO|HACK:|HACK'"\
|
34
|
+
' spec'
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Print only FIXME notes'
|
38
|
+
task :fixme_notes do
|
39
|
+
puts "\nFIXME Notes (These should all be fixed before merging to master):"
|
40
|
+
system 'bundle exec rake notes:fixme'
|
41
|
+
system "grep -rnE 'FIXME:|FIXME'"\
|
42
|
+
' spec'
|
43
|
+
end
|
11
44
|
end
|
data/api_me.gemspec
CHANGED
@@ -5,25 +5,27 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'api_me/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
s.name = 'api_me'
|
9
|
+
s.version = ApiMe::VERSION
|
10
|
+
s.authors = ['Sam Clopton']
|
11
|
+
s.email = ['samsinite@gmail.com']
|
12
|
+
s.homepage = 'https://github.com/inigo/api_me'
|
13
|
+
s.summary = 'Api Me'
|
14
|
+
s.description = "This friendly library gives you helpers and generators to assist building RESTful API's in your Rails app."
|
15
|
+
s.license = 'MIT'
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
19
|
+
s.require_paths = %w(lib app)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
s.add_runtime_dependency 'activerecord', '>= 3.2.0'
|
22
|
+
s.add_runtime_dependency 'activesupport', '>= 3.2.0'
|
23
|
+
s.add_runtime_dependency 'pundit', '~> 0.1'
|
24
|
+
s.add_runtime_dependency 'active_model_serializers', '~> 0.8.0'
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
s.add_development_dependency 'combustion', '~> 0.5.1'
|
27
|
+
s.add_development_dependency 'rspec-rails', '~> 3'
|
28
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.7'
|
29
|
+
s.add_development_dependency 'rubocop', '>= 0.27.0'
|
30
|
+
s.add_development_dependency 'rake-notes', '>= 0.2.0'
|
29
31
|
end
|
data/lib/api_me.rb
CHANGED
@@ -7,13 +7,12 @@ module ApiMe
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
include ::Pundit
|
9
9
|
|
10
|
-
|
10
|
+
included do
|
11
11
|
|
12
|
-
|
13
|
-
rescue_from Pundit::NotAuthorizedError, :with => :user_not_authorized
|
12
|
+
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
14
13
|
|
15
|
-
after_action :verify_authorized, :
|
16
|
-
after_action :verify_policy_scoped, :
|
14
|
+
after_action :verify_authorized, except: :index
|
15
|
+
after_action :verify_policy_scoped, only: :index
|
17
16
|
end
|
18
17
|
|
19
18
|
module ClassMethods
|
@@ -44,60 +43,56 @@ module ApiMe
|
|
44
43
|
end
|
45
44
|
|
46
45
|
def model_klass_name
|
47
|
-
@model_klass_name ||=
|
46
|
+
@model_klass_name ||= name.demodulize.sub(/Controller$/, '').singularize
|
48
47
|
end
|
49
48
|
|
50
49
|
def serializer_klass_name
|
51
|
-
@serializer_klass_name ||= "#{
|
50
|
+
@serializer_klass_name ||= "#{name.demodulize.sub(/Controller$/, '').singularize}Serializer"
|
52
51
|
end
|
53
52
|
|
54
53
|
def params_klass_symbol
|
55
|
-
|
54
|
+
model_klass.name.downcase.to_sym
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
58
|
def index
|
60
59
|
@scoped_objects = policy_scope(model_klass.all)
|
61
|
-
render :
|
60
|
+
render json: @scoped_objects, each_serializer: serializer_klass
|
62
61
|
end
|
63
62
|
|
64
63
|
def show
|
65
64
|
@object = model_klass.find(params[:id])
|
66
65
|
authorize @object
|
67
66
|
|
68
|
-
render :
|
67
|
+
render json: @object, serializer: serializer_klass
|
69
68
|
end
|
70
69
|
|
71
70
|
def create
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
handle_errors(e)
|
80
|
-
end
|
71
|
+
@object = model_klass.new(object_params)
|
72
|
+
authorize @object
|
73
|
+
@object.save!(object_params)
|
74
|
+
|
75
|
+
render status: 201, json: @object, serializer: serializer_klass
|
76
|
+
rescue ActiveRecord::RecordInvalid => e
|
77
|
+
handle_errors(e)
|
81
78
|
end
|
82
79
|
|
83
80
|
def update
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
handle_errors(e)
|
92
|
-
end
|
81
|
+
@object = model_klass.find(params[:id])
|
82
|
+
authorize @object
|
83
|
+
@object.update!(object_params)
|
84
|
+
|
85
|
+
render status: 204, nothing: true
|
86
|
+
rescue ActiveRecord::RecordInvalid => e
|
87
|
+
handle_errors(e)
|
93
88
|
end
|
94
89
|
|
95
90
|
def destroy
|
96
91
|
@object = model_klass.find(params[:id])
|
97
92
|
authorize @object
|
98
|
-
@object.destroy
|
93
|
+
@object.destroy
|
99
94
|
|
100
|
-
render :
|
95
|
+
render status: 204, nothing: true
|
101
96
|
end
|
102
97
|
|
103
98
|
private
|
@@ -107,7 +102,7 @@ module ApiMe
|
|
107
102
|
end
|
108
103
|
|
109
104
|
def render_errors(errors, status = 422)
|
110
|
-
render(:
|
105
|
+
render(json: { errors: errors }, status: status)
|
111
106
|
end
|
112
107
|
|
113
108
|
def handle_errors(e)
|
@@ -115,8 +110,8 @@ module ApiMe
|
|
115
110
|
end
|
116
111
|
|
117
112
|
def user_not_authorized
|
118
|
-
payload = { :
|
119
|
-
render :
|
113
|
+
payload = { message: "User is not allowed to access #{params[:action]} on this resource" }
|
114
|
+
render json: payload, status: 403
|
120
115
|
end
|
121
116
|
|
122
117
|
def params_klass_symbol
|
data/lib/api_me/version.rb
CHANGED
@@ -2,26 +2,26 @@ module ApiMe
|
|
2
2
|
module Generators
|
3
3
|
class ControllerGenerator < ::Rails::Generators::NamedBase
|
4
4
|
source_root File.expand_path('../templates', __FILE__)
|
5
|
-
check_class_collision :
|
5
|
+
check_class_collision suffix: 'Controller'
|
6
6
|
|
7
|
-
argument :attributes, :
|
7
|
+
argument :attributes, type: :array, default: [], banner: 'field field'
|
8
8
|
|
9
|
-
class_option :parent, :
|
9
|
+
class_option :parent, type: :string, desc: 'The parent class for the generated controller'
|
10
10
|
|
11
11
|
def create_api_controller_file
|
12
12
|
template 'controller.rb', File.join('app/controllers',
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
controllers_namespace,
|
14
|
+
controllers_api_version,
|
15
|
+
"#{plural_name}_controller.rb")
|
16
16
|
end
|
17
17
|
|
18
18
|
def controllers_namespace
|
19
|
-
|
19
|
+
'api'
|
20
20
|
# @generators.options.fetch(:api, {}).fetch(:namespace, 'api')
|
21
21
|
end
|
22
22
|
|
23
23
|
def controllers_api_version
|
24
|
-
|
24
|
+
'v1'
|
25
25
|
# @generators.options.fetch(:api, {}).fetch(:version, 'v1')
|
26
26
|
end
|
27
27
|
|
@@ -34,7 +34,7 @@ module ApiMe
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def associations
|
37
|
-
attributes.select
|
37
|
+
attributes.select(&:reference?)
|
38
38
|
end
|
39
39
|
|
40
40
|
def nonpolymorphic_attribute_names
|
@@ -54,7 +54,7 @@ module ApiMe
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def strong_parameters
|
57
|
-
(attributes_names + association_attribute_names).map(&:inspect).join(
|
57
|
+
(attributes_names + association_attribute_names).map(&:inspect).join(', ')
|
58
58
|
end
|
59
59
|
|
60
60
|
def parent_class_name
|
@@ -62,7 +62,7 @@ module ApiMe
|
|
62
62
|
if options[:parent]
|
63
63
|
options[:parent]
|
64
64
|
else
|
65
|
-
|
65
|
+
'ApplicationController'
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -2,11 +2,11 @@ module ApiMe
|
|
2
2
|
module Generators
|
3
3
|
class PolicyGenerator < ::Rails::Generators::NamedBase
|
4
4
|
source_root File.expand_path('../templates', __FILE__)
|
5
|
-
check_class_collision :
|
5
|
+
check_class_collision suffix: 'Policy'
|
6
6
|
|
7
|
-
argument :attributes, :
|
7
|
+
argument :attributes, type: :array, default: [], banner: 'field field'
|
8
8
|
|
9
|
-
class_option :parent, :
|
9
|
+
class_option :parent, type: :string, desc: 'The parent class for the generated policy'
|
10
10
|
|
11
11
|
def create_api_policy_file
|
12
12
|
template 'policy.rb', File.join('app/policies', "#{singular_name}_policy.rb")
|
@@ -21,7 +21,7 @@ module ApiMe
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def associations
|
24
|
-
attributes.select
|
24
|
+
attributes.select(&:reference?)
|
25
25
|
end
|
26
26
|
|
27
27
|
def nonpolymorphic_attribute_names
|
@@ -41,14 +41,14 @@ module ApiMe
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def strong_parameters
|
44
|
-
(attributes_names + association_attribute_names).map(&:inspect).join(
|
44
|
+
(attributes_names + association_attribute_names).map(&:inspect).join(', ')
|
45
45
|
end
|
46
46
|
|
47
47
|
def parent_class_name
|
48
48
|
if options[:parent]
|
49
49
|
options[:parent]
|
50
50
|
else
|
51
|
-
|
51
|
+
'ApplicationPolicy'
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -3,10 +3,10 @@ module ApiMe
|
|
3
3
|
class ResourceGenerator < Rails::Generators::Base
|
4
4
|
def run_generators
|
5
5
|
params = @_initializer[0]
|
6
|
-
invoke
|
7
|
-
invoke
|
8
|
-
invoke
|
9
|
-
invoke
|
6
|
+
invoke 'model', params
|
7
|
+
invoke 'serializer', params + %w(created_at updated_at)
|
8
|
+
invoke 'api_me:policy', params
|
9
|
+
invoke 'api_me:controller', params
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -3,8 +3,8 @@ require 'spec_helper'
|
|
3
3
|
describe 'Users API' do
|
4
4
|
it 'sends the list of users' do
|
5
5
|
users = [
|
6
|
-
User.create(:
|
7
|
-
User.create(:
|
6
|
+
User.create(username: 'Test'),
|
7
|
+
User.create(username: 'Test 2')
|
8
8
|
]
|
9
9
|
|
10
10
|
get '/api/v1/users'
|
@@ -16,7 +16,7 @@ describe 'Users API' do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'sends an individual user' do
|
19
|
-
user = User.create(:
|
19
|
+
user = User.create(username: 'Test')
|
20
20
|
|
21
21
|
get '/api/v1/users/' + user.id.to_s + '/'
|
22
22
|
|
@@ -28,10 +28,10 @@ describe 'Users API' do
|
|
28
28
|
|
29
29
|
it 'creates a new user' do
|
30
30
|
user_params = {
|
31
|
-
:
|
31
|
+
username: 'Test'
|
32
32
|
}
|
33
33
|
|
34
|
-
post '/api/v1/users/',
|
34
|
+
post '/api/v1/users/', user: user_params
|
35
35
|
|
36
36
|
expect(last_response.status).to eq(201)
|
37
37
|
json = JSON.parse(last_response.body)
|
@@ -40,25 +40,25 @@ describe 'Users API' do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'updates an existing user' do
|
43
|
-
user = User.create(:
|
43
|
+
user = User.create(username: 'Foo')
|
44
44
|
|
45
|
-
expect(user.username).to eq(
|
45
|
+
expect(user.username).to eq('Foo')
|
46
46
|
|
47
|
-
put '/api/v1/users/' + user.id.to_s + '/',
|
47
|
+
put '/api/v1/users/' + user.id.to_s + '/', user: { username: 'Bar' }
|
48
48
|
|
49
49
|
updated_user = User.find(user.id)
|
50
50
|
expect(last_response.status).to eq(204)
|
51
|
-
expect(updated_user.username).to eq(
|
51
|
+
expect(updated_user.username).to eq('Bar')
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'destroys an existing user' do
|
55
|
-
user = User.create(:
|
55
|
+
user = User.create(username: 'Foo')
|
56
56
|
|
57
57
|
expect(user.id).to_not eq(nil)
|
58
58
|
|
59
59
|
delete '/api/v1/users/' + user.id.to_s + '/'
|
60
60
|
|
61
|
-
does_user_exist = User.where(:
|
61
|
+
does_user_exist = User.where(id: user.id).exists?
|
62
62
|
expect(last_response.status).to eq(204)
|
63
63
|
expect(does_user_exist).to eq(false)
|
64
64
|
end
|
data/spec/internal/db/schema.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_me
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Clopton
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: sqlite3
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,34 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 1.3.7
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.27.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.27.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rake-notes
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.2.0
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.2.0
|
111
139
|
description: This friendly library gives you helpers and generators to assist building
|
112
140
|
RESTful API's in your Rails app.
|
113
141
|
email:
|