api_me 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://badge.fury.io/rb/api_me.png)](http://badge.fury.io/rb/api_me) [![Build Status](https://travis-ci.org/inigo-llc/api_me.png?branch=master)](https://travis-ci.org/inigo-llc/api_me) [![Code Climate](https://codeclimate.com/github/inigo-llc/api_me/badges/gpa.svg)](https://codeclimate.com/github/inigo-llc/api_me) [![
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/api_me.png)](http://badge.fury.io/rb/api_me) [![Build Status](https://travis-ci.org/inigo-llc/api_me.png?branch=master)](https://travis-ci.org/inigo-llc/api_me) [![Code Climate](https://codeclimate.com/github/inigo-llc/api_me/badges/gpa.svg)](https://codeclimate.com/github/inigo-llc/api_me) [![Dependency Status](https://gemnasium.com/inigo-llc/api_me.svg)](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:
|