api_me 0.9.4 → 0.10.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +16 -39
  3. data/lib/api_me.rb +12 -10
  4. data/lib/api_me/base_filter.rb +2 -0
  5. data/lib/api_me/engine.rb +5 -0
  6. data/lib/api_me/model.rb +2 -0
  7. data/lib/api_me/pagination.rb +28 -11
  8. data/lib/api_me/sorting.rb +24 -11
  9. data/lib/api_me/version.rb +3 -1
  10. data/lib/generators/api_me/controller/controller_generator.rb +8 -6
  11. data/lib/generators/api_me/filter/filter_generator.rb +2 -0
  12. data/lib/generators/api_me/install_generator.rb +2 -0
  13. data/lib/generators/api_me/policy/policy_generator.rb +2 -0
  14. data/lib/generators/api_me/resource/resource_generator.rb +2 -0
  15. metadata +25 -92
  16. data/.editorconfig +0 -41
  17. data/.gitignore +0 -3
  18. data/.rubocop.yml +0 -8
  19. data/.ruby-version +0 -1
  20. data/.travis.yml +0 -4
  21. data/Gemfile +0 -11
  22. data/Gemfile.lock +0 -153
  23. data/LICENSE +0 -20
  24. data/README.md +0 -194
  25. data/api_me.gemspec +0 -33
  26. data/config.ru +0 -7
  27. data/spec/acceptance/api/v1/fails_spec.rb +0 -12
  28. data/spec/acceptance/api/v1/posts_spec.rb +0 -154
  29. data/spec/acceptance/api/v1/users_spec.rb +0 -96
  30. data/spec/acceptance/multi_word_resource_spec.rb +0 -12
  31. data/spec/internal/app/controllers/api/v1/fails_controller.rb +0 -11
  32. data/spec/internal/app/controllers/api/v1/multi_word_resources_controller.rb +0 -6
  33. data/spec/internal/app/controllers/api/v1/posts_controller.rb +0 -3
  34. data/spec/internal/app/controllers/api/v1/users_controller.rb +0 -3
  35. data/spec/internal/app/controllers/application_controller.rb +0 -12
  36. data/spec/internal/app/filters/user_filter.rb +0 -7
  37. data/spec/internal/app/models/post.rb +0 -3
  38. data/spec/internal/app/models/test_model.rb +0 -21
  39. data/spec/internal/app/models/user.rb +0 -3
  40. data/spec/internal/app/policies/application_policy.rb +0 -65
  41. data/spec/internal/app/policies/post_policy.rb +0 -4
  42. data/spec/internal/app/policies/test_model_policy.rb +0 -5
  43. data/spec/internal/app/policies/user_policy.rb +0 -8
  44. data/spec/internal/app/serializers/post_serializer.rb +0 -5
  45. data/spec/internal/app/serializers/test_model_serializer.rb +0 -5
  46. data/spec/internal/app/serializers/user_serializer.rb +0 -3
  47. data/spec/internal/config/database.yml +0 -3
  48. data/spec/internal/config/initializers/active_model_serializers.rb +0 -1
  49. data/spec/internal/config/routes.rb +0 -10
  50. data/spec/internal/db/schema.rb +0 -12
  51. data/spec/internal/log/.gitignore +0 -1
  52. data/spec/internal/public/favicon.ico +0 -0
  53. data/spec/spec_helper.rb +0 -24
data/api_me.gemspec DELETED
@@ -1,33 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- lib = File.expand_path('../lib', __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'api_me/version'
6
-
7
- Gem::Specification.new do |s|
8
- s.name = 'api_me'
9
- s.version = ApiMe::VERSION
10
- s.authors = ['Sam Clopton', 'Joe Weakley']
11
- s.email = ['samsinite@gmail.com']
12
- s.homepage = 'https://github.com/wildland/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
-
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
-
21
- s.add_runtime_dependency 'activerecord', '>= 4.1.16'
22
- s.add_runtime_dependency 'activesupport', '>= 4.1.16'
23
- s.add_runtime_dependency 'pundit', '~> 1.1.0'
24
- s.add_runtime_dependency 'active_model_serializers', '~> 0.10.0'
25
- s.add_runtime_dependency 'search_object', '~> 1.0'
26
- s.add_runtime_dependency 'kaminari', '~> 0.16.3'
27
-
28
- s.add_development_dependency 'combustion', '~> 0.5.1'
29
- s.add_development_dependency 'rspec-rails', '~> 3'
30
- s.add_development_dependency 'sqlite3', '~> 1.3.7'
31
- s.add_development_dependency 'rubocop', '~> 0.49'
32
- s.add_development_dependency 'rake-notes', '>= 0.2.0'
33
- end
data/config.ru DELETED
@@ -1,7 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler'
3
-
4
- Bundler.require :default, :development
5
-
6
- Combustion.initialize!
7
- run Combustion::Application
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'fails API' do
4
- it 'fails in the before action' do
5
- get '/api/v1/fails'
6
-
7
- expect(last_response.status).to eq(404)
8
- json = JSON.parse(last_response.body)
9
-
10
- expect(json['status']).to eq('failed')
11
- end
12
- end
@@ -1,154 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Posts API' do
4
- it 'sends the list of posts using the default filter' do
5
- posts = [
6
- Post.create(name: 'test'),
7
- Post.create(name: 'test 2')
8
- ]
9
-
10
- get '/api/v1/posts'
11
-
12
- expect(last_response.status).to eq(200)
13
- json = JSON.parse(last_response.body)
14
-
15
- expect(json['posts'].length).to eq(posts.count)
16
- end
17
-
18
- it 'is paging with page offset using default page size and restricting size' do
19
- 40.times do
20
- Post.create(name: 'page item')
21
- end
22
-
23
- get '/api/v1/posts?page%5Boffset%5D=1'
24
- json = JSON.parse(last_response.body)
25
- expect(json['posts'].length).to eq(25)
26
- end
27
-
28
- it 'is page offset of 2 working for size of 40 default page size of 25' do
29
- 40.times do
30
- Post.create(name: 'page item')
31
- end
32
-
33
- get '/api/v1/posts?page%5Boffset%5D=2'
34
- json = JSON.parse(last_response.body)
35
- expect(json['posts'].length).to eq(15)
36
- end
37
-
38
- it 'is page offset of -1 working for size of 40 default page size of 25' do
39
- # min page offset is 1, anything less gets converted to 1 and results in page size records
40
- 40.times do
41
- Post.create(name: 'page item')
42
- end
43
-
44
- get '/api/v1/posts?page%5Boffset%5D=-1'
45
- json = JSON.parse(last_response.body)
46
- expect(json['posts'].length).to eq(25)
47
- end
48
-
49
- it 'is page offset of 3 working for size of 40 default page size of 25' do
50
- # overflow on page offset will result in 0 records
51
- 40.times do
52
- Post.create(name: 'page item')
53
- end
54
-
55
- get '/api/v1/posts?page%5Boffset%5D=3'
56
- json = JSON.parse(last_response.body)
57
- expect(json['posts'].length).to eq(0)
58
- end
59
-
60
- it 'is page size of 10 working for default offset of 1' do
61
- # overflow on page offset will result in 0 records
62
- 40.times do
63
- Post.create(name: 'page item')
64
- end
65
-
66
- get '/api/v1/posts?page%5Bsize%5D=10'
67
- json = JSON.parse(last_response.body)
68
- expect(json['posts'].length).to eq(10)
69
- end
70
-
71
- it 'is page size working when the value is negative' do
72
- # overflow on page offset will result in 0 records
73
- 40.times do
74
- Post.create(name: 'page item')
75
- end
76
-
77
- get '/api/v1/posts?page%5Bsize%5D=-10'
78
- json = JSON.parse(last_response.body)
79
- expect(json['posts'].length).to eq(25)
80
- end
81
-
82
- it 'is page size working when the value is higher than the total record count' do
83
- # overflow on page offset will result in 0 records
84
- 40.times do
85
- Post.create(name: 'page item')
86
- end
87
-
88
- get '/api/v1/posts?page%5Bsize%5D=100'
89
- json = JSON.parse(last_response.body)
90
- expect(json['posts'].length).to eq(40)
91
- end
92
-
93
- it 'is the result all records when no page paramas are sent' do
94
- # overflow on page offset will result in 0 records
95
- 100.times do
96
- Post.create(name: 'page item')
97
- end
98
-
99
- get '/api/v1/posts'
100
- json = JSON.parse(last_response.body)
101
- expect(json['posts'].length).to eq(100)
102
- end
103
-
104
- it 'restricts page_size when max_per_page config is less' do
105
- 100.times do
106
- Post.create(name: 'page item')
107
- end
108
-
109
- Kaminari.config.max_per_page = 10
110
-
111
- get '/api/v1/posts?page%5Bsize%5D=100'
112
- json = JSON.parse(last_response.body)
113
- expect(json['posts'].length).to eq(10)
114
- end
115
-
116
- it 'sends posts filtered by ids' do
117
- all_posts = [
118
- Post.create(name: 'test'),
119
- Post.create(name: 'test 2'),
120
- Post.create(name: 'test 3')
121
- ]
122
-
123
- filtered_posts = [all_posts[0], all_posts[2]]
124
-
125
- get '/api/v1/posts?ids%5B%5D=' + filtered_posts[0].id.to_s +
126
- '&ids%5B%5D=' + filtered_posts[1].id.to_s
127
-
128
- expect(last_response.status).to eq(200)
129
- json = JSON.parse(last_response.body)
130
-
131
- expect(json['posts'].length).to eq(filtered_posts.count)
132
- end
133
-
134
- it 'sends posts reverse sorted by id' do
135
- 20.times do |i|
136
- Post.create(name: 'Post' + i.to_s)
137
- end
138
-
139
- get '/api/v1/posts?sort%5Bcriteria%5D=id&sort%5Breverse%5D=true'
140
- json = JSON.parse(last_response.body)
141
- expect(json['posts'].last['name']).to eq('Post0')
142
- end
143
-
144
- it 'sends posts reverse sorted by id and paginated with a size of 10 and an offset of 1' do
145
- 20.times do |i|
146
- Post.create(name: 'Post' + i.to_s)
147
- end
148
-
149
- get '/api/v1/posts?page%5Boffset%5D=1&page%5Bsize%5D=10&sort%5Bcriteria%5D=id&sort%5Breverse%5D=true'
150
- json = JSON.parse(last_response.body)
151
- expect(json['posts'].first['name']).to eq('Post19')
152
- expect(json['posts'].length).to eq(10)
153
- end
154
- end
@@ -1,96 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Users API' do
4
- it 'sends the list of users' do
5
- users = [
6
- User.create(username: 'Test'),
7
- User.create(username: 'Test 2')
8
- ]
9
-
10
- get '/api/v1/users'
11
-
12
- expect(last_response.status).to eq(200)
13
- json = JSON.parse(last_response.body)
14
-
15
- expect(json['users'].length).to eq(users.count)
16
- end
17
-
18
- it 'returns a 404 for a user that does not exist' do
19
- invalid_user_id = User.maximum(:id).to_i + 1
20
-
21
- get '/api/v1/users/' + invalid_user_id.to_s + '/'
22
-
23
- expect(last_response.status).to eq(404)
24
- end
25
-
26
- it 'returns a 404 for new' do
27
-
28
- get '/api/v1/users/new'
29
-
30
- expect(last_response.status).to eq(404)
31
- end
32
-
33
- it 'returns a 404 for edit' do
34
- user = User.create(username: 'Foo')
35
-
36
- expect(user.username).to eq('Foo')
37
-
38
- get '/api/v1/users/' + user.id.to_s + '/edit'
39
-
40
- expect(last_response.status).to eq(404)
41
- end
42
-
43
- it 'creates a new user' do
44
- user_params = {
45
- username: 'Test'
46
- }
47
-
48
- post '/api/v1/users/', user: user_params
49
-
50
- expect(last_response.status).to eq(201)
51
- json = JSON.parse(last_response.body)
52
-
53
- expect(json['user']['username']).to eq(user_params[:username])
54
- end
55
-
56
- it 'updates an existing user' do
57
- user = User.create(username: 'Foo')
58
-
59
- expect(user.username).to eq('Foo')
60
-
61
- put '/api/v1/users/' + user.id.to_s + '/', user: { username: 'Bar' }
62
-
63
- updated_user = User.find(user.id)
64
- expect(last_response.status).to eq(204)
65
- expect(updated_user.username).to eq('Bar')
66
- end
67
-
68
- it 'destroys an existing user' do
69
- user = User.create(username: 'Foo')
70
-
71
- expect(user.id).to_not eq(nil)
72
-
73
- delete '/api/v1/users/' + user.id.to_s + '/'
74
-
75
- does_user_exist = User.where(id: user.id).exists?
76
- expect(last_response.status).to eq(204)
77
- expect(does_user_exist).to eq(false)
78
- end
79
-
80
- it 'sends a filtered list of users' do
81
- all_users = [
82
- User.create(username: 'Test'),
83
- User.create(username: 'Demo'),
84
- User.create(username: 'Test 2')
85
- ]
86
-
87
- filtered_users = [all_users[0], all_users[2]]
88
-
89
- get '/api/v1/users?filters%5Bsearch%5D=Test'
90
-
91
- expect(last_response.status).to eq(200)
92
- json = JSON.parse(last_response.body)
93
-
94
- expect(json['users'].length).to eq(filtered_users.count)
95
- end
96
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'multi-word API resource' do
4
- it 'succeeds creating a new object using a resource that consists of multiple words' do
5
- post '/api/v1/multi_word_resources', test_model: { test: true }
6
-
7
- expect(last_response.status).to eq(201)
8
- json = JSON.parse(last_response.body)
9
-
10
- expect(json['test_model']['created']).to eq(true)
11
- end
12
- end
@@ -1,11 +0,0 @@
1
- class Api::V1::FailsController < ApplicationController # rubocop:disable ClassAndModuleChildren
2
- include ApiMe
3
-
4
- before_action :fail
5
-
6
- private
7
-
8
- def fail
9
- render json: { status: 'failed' }, status: 404
10
- end
11
- end
@@ -1,6 +0,0 @@
1
- class Api::V1::MultiWordResourcesController < ApplicationController # rubocop:disable ClassAndModuleChildren, LineLength
2
- include ApiMe
3
-
4
- model TestModel
5
- serializer TestModelSerializer
6
- end
@@ -1,3 +0,0 @@
1
- class Api::V1::PostsController < ApplicationController # rubocop:disable ClassAndModuleChildren
2
- include ApiMe
3
- end
@@ -1,3 +0,0 @@
1
- class Api::V1::UsersController < ApplicationController # rubocop:disable ClassAndModuleChildren
2
- include ApiMe
3
- end
@@ -1,12 +0,0 @@
1
- class ApplicationController < ActionController::Base
2
- # Prevent CSRF attacks by raising an exception.
3
- # For APIs, you may want to use :null_session instead.
4
- protect_from_forgery with: :exception
5
-
6
- private
7
-
8
- # Needed by pundit
9
- def current_user
10
- nil
11
- end
12
- end
@@ -1,7 +0,0 @@
1
- require 'search_object'
2
-
3
- class UserFilter < ApiMe::BaseFilter
4
- include ::SearchObject.module
5
-
6
- option(:search) { |scope, value| scope.where('username LIKE ?', "%#{value}%") }
7
- end
@@ -1,3 +0,0 @@
1
- class Post < ActiveRecord::Base
2
- belongs_to :user
3
- end
@@ -1,21 +0,0 @@
1
- require 'active_model_serializers/model'
2
-
3
- class TestModel < ActiveModelSerializers::Model
4
- def self.create
5
- @created = true
6
- end
7
-
8
- def self.created
9
- @created ||= false
10
- end
11
-
12
- def initialize(*_args); end
13
-
14
- def save!(*_args)
15
- TestModel.create
16
- end
17
-
18
- def created
19
- TestModel.created
20
- end
21
- end
@@ -1,3 +0,0 @@
1
- class User < ActiveRecord::Base
2
- has_many :posts
3
- end
@@ -1,65 +0,0 @@
1
- class ApplicationPolicy
2
- attr_reader :user, :record
3
-
4
- def initialize(user, record)
5
- @user = user
6
- @record = record
7
- end
8
-
9
- def index?
10
- true
11
- end
12
-
13
- def show?
14
- scope.where(id: record.id).exists?
15
- end
16
-
17
- def create?
18
- true
19
- end
20
-
21
- def new?
22
- create?
23
- end
24
-
25
- def update?
26
- true
27
- end
28
-
29
- def edit?
30
- update?
31
- end
32
-
33
- def destroy?
34
- true
35
- end
36
-
37
- def scope
38
- Pundit.policy_scope!(user, record.class)
39
- end
40
-
41
- class Scope
42
- attr_reader :user, :scope
43
-
44
- def initialize(user, scope)
45
- @user = user
46
- @scope = scope
47
- end
48
-
49
- def resolve
50
- readable
51
- end
52
-
53
- def readable
54
- scope
55
- end
56
-
57
- def modifyable
58
- scope
59
- end
60
-
61
- def destroyable
62
- scope
63
- end
64
- end
65
- end