api_me 0.9.4 → 0.10.0

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