introspective_grape 0.3.2 → 0.3.3
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/.rubocop.yml +1 -1
- data/.travis.yml +16 -3
- data/CHANGELOG.md +16 -8
- data/README.md +6 -6
- data/gemfiles/2.0.0-Gemfile +1 -1
- data/gemfiles/Gemfile.rails.3.2.22 +1 -1
- data/gemfiles/Gemfile.rails.4.1.13 +1 -1
- data/gemfiles/Gemfile.rails.4.2.7.1 +1 -1
- data/gemfiles/Gemfile.rails.4.2.7.1.new.swagger +1 -1
- data/gemfiles/Gemfile.rails.4.2.8 +1 -1
- data/gemfiles/Gemfile.rails.5.0.1 +1 -1
- data/gemfiles/Gemfile.rails.master +1 -1
- data/introspective_grape.gemspec +2 -2
- data/lib/introspective_grape/api.rb +16 -16
- data/lib/introspective_grape/camel_snake.rb +5 -4
- data/lib/introspective_grape/filters.rb +2 -2
- data/lib/introspective_grape/formatter/camel_json.rb +12 -9
- data/lib/introspective_grape/helpers.rb +3 -3
- data/lib/introspective_grape/snake_params.rb +2 -1
- data/lib/introspective_grape/traversal.rb +5 -5
- data/lib/introspective_grape/validators.rb +1 -1
- data/lib/introspective_grape/version.rb +1 -1
- data/spec/dummy/app/api/dummy/chat_api.rb +4 -4
- data/spec/dummy/app/api/dummy/company_api.rb +1 -1
- data/spec/dummy/app/api/dummy/location_api.rb +2 -2
- data/spec/dummy/app/api/dummy/project_api.rb +1 -1
- data/spec/dummy/app/api/dummy/sessions.rb +3 -3
- data/spec/dummy/app/api/dummy/user_api.rb +1 -1
- data/spec/dummy/app/api/dummy_api.rb +0 -3
- data/spec/dummy/app/api/error_handlers.rb +2 -2
- data/spec/dummy/app/models/admin_user.rb +1 -1
- data/spec/dummy/app/models/chat.rb +1 -1
- data/spec/dummy/app/models/chat_message.rb +1 -1
- data/spec/dummy/app/models/chat_user.rb +1 -1
- data/spec/dummy/app/models/company.rb +1 -1
- data/spec/dummy/app/models/image.rb +1 -1
- data/spec/dummy/app/models/project.rb +1 -1
- data/spec/dummy/app/models/user.rb +1 -1
- data/spec/dummy/app/models/user/chatter.rb +4 -4
- data/spec/dummy/app/models/user_location.rb +4 -4
- data/spec/dummy/app/policies/location_policy.rb +1 -1
- data/spec/dummy/app/policies/project_policy.rb +5 -5
- data/spec/dummy/app/policies/role_policy.rb +2 -2
- data/spec/dummy/app/policies/user_policy.rb +1 -1
- data/spec/dummy/db/migrate/20150414213154_add_user_authentication_token.rb +1 -1
- data/spec/dummy/db/migrate/20150601212924_create_location_beacons.rb +1 -1
- data/spec/dummy/db/migrate/20150616205336_add_role_user_constraint.rb +1 -1
- data/spec/dummy/db/migrate/20150727214950_add_confirmable_to_devise.rb +1 -1
- data/spec/dummy/db/migrate/20150820190524_add_user_names.rb +2 -2
- data/spec/models/project_spec.rb +3 -3
- data/spec/models/role_spec.rb +6 -6
- data/spec/models/team_spec.rb +2 -2
- data/spec/models/team_user_spec.rb +4 -4
- data/spec/models/user_location_spec.rb +1 -1
- data/spec/models/user_project_job_spec.rb +2 -2
- data/spec/models/user_spec.rb +10 -10
- data/spec/requests/chat_api_spec.rb +7 -7
- data/spec/requests/company_api_spec.rb +4 -4
- data/spec/requests/location_api_spec.rb +10 -10
- data/spec/requests/project_api_spec.rb +18 -18
- data/spec/requests/role_api_spec.rb +1 -1
- data/spec/requests/sessions_api_spec.rb +3 -3
- data/spec/requests/swagger_spec.rb +1 -1
- data/spec/requests/user_api_spec.rb +13 -13
- data/spec/support/blueprints.rb +10 -10
- data/spec/support/location_helper.rb +6 -6
- data/spec/support/request_helpers.rb +4 -3
- metadata +6 -10
- data/lib/.DS_Store +0 -0
- data/spec/.DS_Store +0 -0
- data/spec/dummy/app/api/.DS_Store +0 -0
@@ -1,11 +1,12 @@
|
|
1
1
|
module IntrospectiveGrape
|
2
2
|
module SnakeParams
|
3
|
+
|
3
4
|
def snake_params_before_validation
|
4
5
|
before_validation do
|
5
6
|
# We have to snake case the Rack params then re-assign @params to the
|
6
7
|
# request.params, because of the I-think-very-goofy-and-inexplicable
|
7
8
|
# way Grape interacts with both independently of each other
|
8
|
-
(
|
9
|
+
(CamelSnakeKeys.snake_keys(params)||{}).each do |k,v|
|
9
10
|
request.delete_param(k.camelize(:lower))
|
10
11
|
request.update_param(k, v)
|
11
12
|
end
|
@@ -9,14 +9,14 @@ module IntrospectiveGrape::Traversal
|
|
9
9
|
# (the traversal of the intermediate nodes occurs in find_leaf())
|
10
10
|
return record if routes.size < 2 # the leaf is the root
|
11
11
|
record = find_leaf(routes, record, params)
|
12
|
-
if record
|
12
|
+
if record
|
13
13
|
assoc = routes.last
|
14
|
-
if assoc.many?
|
14
|
+
if assoc.many?
|
15
15
|
leaves = record.send( assoc.reflection.name ).includes( default_includes(assoc.model) )
|
16
16
|
verify_records_found(leaves, routes)
|
17
17
|
leaves
|
18
|
-
else
|
19
|
-
# has_one associations don't return a CollectionProxy and so don't support
|
18
|
+
else
|
19
|
+
# has_one associations don't return a CollectionProxy and so don't support
|
20
20
|
# eager loading.
|
21
21
|
record.send( assoc.reflection.name )
|
22
22
|
end
|
@@ -24,7 +24,7 @@ module IntrospectiveGrape::Traversal
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def verify_records_found(leaves, routes)
|
27
|
-
unless (leaves.map(&:class) - [routes.last.model]).empty?
|
27
|
+
unless (leaves.map(&:class) - [routes.last.model]).empty?
|
28
28
|
raise ActiveRecord::RecordNotFound.new("Records contain the wrong models, they should all be #{routes.last.model.name}, found #{records.map(&:class).map(&:name).join(',')}")
|
29
29
|
end
|
30
30
|
end
|
@@ -14,7 +14,7 @@ module Grape::Validators
|
|
14
14
|
class JsonArray < Grape::Validations::Base
|
15
15
|
def validate_param!(field, params)
|
16
16
|
begin
|
17
|
-
raise unless JSON.parse( params[field] ).kind_of? Array
|
17
|
+
raise unless JSON.parse( params[field] ).kind_of? Array
|
18
18
|
rescue
|
19
19
|
fail Grape::Exceptions::Validation, params: [@scope.full_name(field)], message: 'must be a valid JSON array!'
|
20
20
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class Dummy::ChatAPI < Grape::API
|
2
2
|
formatter :json, IntrospectiveGrape::Formatter::CamelJson
|
3
3
|
|
4
|
-
before do
|
4
|
+
before do
|
5
5
|
authenticate!
|
6
6
|
end
|
7
7
|
|
8
|
-
resource :chats do
|
8
|
+
resource :chats do
|
9
9
|
|
10
|
-
desc "list the current user's existing chats"
|
10
|
+
desc "list the current user's existing chats"
|
11
11
|
get '/' do
|
12
12
|
authorize Chat.new, :index?
|
13
13
|
present current_user.chats.includes(:users), with: ChatEntity
|
@@ -103,6 +103,6 @@ class Dummy::ChatAPI < Grape::API
|
|
103
103
|
class MessageEntity < Grape::Entity
|
104
104
|
expose :id, :chat_id, :message
|
105
105
|
expose :author, using: UserEntity
|
106
|
-
end
|
106
|
+
end
|
107
107
|
|
108
108
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class Dummy::LocationAPI < IntrospectiveGrape::API
|
2
|
-
exclude_actions Location, :none
|
3
|
-
include_actions LocationBeacon, :index
|
2
|
+
exclude_actions Location, :none
|
3
|
+
include_actions LocationBeacon, :index
|
4
4
|
include_actions LocationGps, :index
|
5
5
|
|
6
6
|
default_includes Location, :child_locations, :gps, :beacons, :locatables
|
@@ -11,7 +11,7 @@ class Dummy::ProjectAPI < IntrospectiveGrape::API
|
|
11
11
|
|
12
12
|
paginate per_page: 2, max_per_page: 10, offset: 2
|
13
13
|
|
14
|
-
restful Project, [:id, teams_attributes: [:id,:name,:_destroy, team_users_attributes: [:id, :user_id, :_destroy] ]]
|
14
|
+
restful Project, [:id, teams_attributes: [:id,:name,:_destroy, team_users_attributes: [:id, :user_id, :_destroy] ]]
|
15
15
|
|
16
16
|
class AdminEntity < Grape::Entity
|
17
17
|
expose :id, as: :user_id
|
@@ -34,18 +34,18 @@ class Dummy::Sessions < Grape::API
|
|
34
34
|
|
35
35
|
|
36
36
|
desc "delete a user session" do
|
37
|
-
detail "sign out the current user"
|
37
|
+
detail "sign out the current user"
|
38
38
|
end
|
39
39
|
delete '/' do
|
40
40
|
authorize User.new, :sessions?
|
41
41
|
u = User.find_by_authentication_token(params[:api_key])
|
42
|
-
if u
|
42
|
+
if u
|
43
43
|
u.authentication_token = nil
|
44
44
|
{status: u.save!}
|
45
45
|
else
|
46
46
|
{status: true } # the user is already logged out
|
47
47
|
end
|
48
|
-
end
|
48
|
+
end
|
49
49
|
|
50
50
|
end
|
51
51
|
end
|
@@ -32,6 +32,6 @@ class Dummy::UserAPI < IntrospectiveGrape::API
|
|
32
32
|
expose :id, :email, :first_name, :last_name, :avatar_url, :created_at
|
33
33
|
expose :roles, as: :roles_attributes, using: RoleEntity
|
34
34
|
expose :user_project_jobs, as: :user_project_jobs_attributes, using: UserProjectJobEntity
|
35
|
-
end
|
35
|
+
end
|
36
36
|
|
37
37
|
end
|
@@ -15,9 +15,6 @@ class DummyAPI < Grape::API
|
|
15
15
|
# sets server date in response header. This can be used on the client side
|
16
16
|
header "X-Server-Date", Time.now.to_i.to_s
|
17
17
|
header "Expires", 1.year.ago.httpdate
|
18
|
-
# Convert incoming camel case params to snake case: grape will totally blow this
|
19
|
-
# if the params hash is not a Hashie::Mash, so make it one of those:
|
20
|
-
#@params = Hashie::Mash.new(params.with_snake_keys)
|
21
18
|
end
|
22
19
|
|
23
20
|
before_validation do
|
@@ -18,11 +18,11 @@ module ErrorHandlers
|
|
18
18
|
end
|
19
19
|
|
20
20
|
m.rescue_from Pundit::NotAuthorizedError do
|
21
|
-
error_response message: "Forbidden", status: 403
|
21
|
+
error_response message: "Forbidden", status: 403
|
22
22
|
end
|
23
23
|
|
24
24
|
m.rescue_from Pundit::NotDefinedError do
|
25
|
-
error_response message: "Policy not implemented", status: 501
|
25
|
+
error_response message: "Policy not implemented", status: 501
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
class AdminUser < ActiveRecord::Base
|
2
2
|
# Include default devise modules. Others available are:
|
3
3
|
# :confirmable, :lockable, :timeoutable and :omniauthable
|
4
|
-
devise :database_authenticatable,
|
4
|
+
devise :database_authenticatable,
|
5
5
|
:recoverable, :rememberable, :trackable, :validatable
|
6
6
|
end
|
@@ -10,7 +10,7 @@ class Chat < AbstractAdapter
|
|
10
10
|
chat_users.includes(:user).select {|cu| cu.departed_at.nil? }.map(&:user)
|
11
11
|
end
|
12
12
|
|
13
|
-
before_create :add_creator_to_conversation
|
13
|
+
before_create :add_creator_to_conversation
|
14
14
|
def add_creator_to_conversation
|
15
15
|
users.push creator
|
16
16
|
end
|
@@ -2,7 +2,7 @@ class Company < AbstractAdapter
|
|
2
2
|
has_many :roles, as: :ownable
|
3
3
|
has_many :admins, through: :roles, source: :user
|
4
4
|
accepts_nested_attributes_for :roles, allow_destroy: true
|
5
|
-
|
5
|
+
|
6
6
|
has_many :beacons, class_name: 'LocationBeacon', dependent: :destroy
|
7
7
|
has_many :locatables
|
8
8
|
has_many :locations, through: :locatables, source: :locatable, source_type: 'Company'
|
@@ -5,7 +5,7 @@ class Image < ActiveRecord::Base
|
|
5
5
|
|
6
6
|
has_attached_file :file, styles: {medium: "300x300>", thumb: "100x100"},
|
7
7
|
url: "/system/:imageable_type/:imageable_id/:id/:style/:filename"
|
8
|
-
|
8
|
+
|
9
9
|
validates_attachment :file, content_type: {content_type: ["image/jpeg", "image/png", "image/gif"]}
|
10
10
|
validates_attachment_size :file, :less_than => 2.megabytes
|
11
11
|
|
@@ -8,7 +8,7 @@ class Project < AbstractAdapter
|
|
8
8
|
has_many :project_jobs, dependent: :destroy, inverse_of: :project
|
9
9
|
has_many :jobs, through: :project_jobs
|
10
10
|
accepts_nested_attributes_for :project_jobs, allow_destroy: true
|
11
|
-
|
11
|
+
|
12
12
|
has_many :user_project_jobs, dependent: :destroy, inverse_of: :project
|
13
13
|
has_many :users, through: :user_project_jobs, inverse_of: :projects
|
14
14
|
accepts_nested_attributes_for :user_project_jobs, allow_destroy: true
|
@@ -28,7 +28,7 @@ class User < AbstractAdapter
|
|
28
28
|
has_many :chat_users
|
29
29
|
has_many :chats, through: :chat_users
|
30
30
|
has_many :chat_message_users
|
31
|
-
has_many :messages, ->{ where('chat_messages.created_at >= chat_users.created_at and (chat_users.departed_at IS NULL OR chat_messages.created_at <= chat_users.departed_at)') }, through: :chats
|
31
|
+
has_many :messages, ->{ where('chat_messages.created_at >= chat_users.created_at and (chat_users.departed_at IS NULL OR chat_messages.created_at <= chat_users.departed_at)') }, through: :chats
|
32
32
|
include User::Chatter
|
33
33
|
|
34
34
|
has_many :roles, dependent: :destroy, inverse_of: :user
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module User::Chatter
|
2
2
|
|
3
3
|
def message_query(chat_id, new = true)
|
4
|
-
messages.joins(:chat_message_users)
|
4
|
+
messages.joins(:chat_message_users)
|
5
5
|
.where('chat_message_users.user_id'=> id)
|
6
6
|
.where(new ? {'chat_message_users.read_at'=>nil} : '')
|
7
7
|
.where(chat_id ? {'chat_messages.chat_id'=> chat_id} : '')
|
8
8
|
.order('') # or it will add an order by id clause that breaks the count query.
|
9
9
|
end
|
10
10
|
|
11
|
-
def new_messages?(chat=nil) # returns a hash of chat_ids with new message counts
|
11
|
+
def new_messages?(chat=nil) # returns a hash of chat_ids with new message counts
|
12
12
|
chat_id = chat.kind_of?(Chat) ? chat.id : chat
|
13
13
|
new = message_query(chat_id)
|
14
14
|
.select("chat_messages.chat_id, count(chat_messages.id) as count")
|
@@ -30,7 +30,7 @@ module User::Chatter
|
|
30
30
|
chat = Chat.create(creator: self)
|
31
31
|
chat.users.push users
|
32
32
|
chat.messages.build(message: message, author: self)
|
33
|
-
chat.save!
|
33
|
+
chat.save!
|
34
34
|
chat
|
35
35
|
end
|
36
36
|
|
@@ -51,7 +51,7 @@ module User::Chatter
|
|
51
51
|
chat.users.push users
|
52
52
|
chat.messages.build(chat: chat, author: self, message: "#{self.name} [[ADDED_USER_MESSAGE]] #{users.map(&:name).join(',')}")
|
53
53
|
chat.save!
|
54
|
-
else
|
54
|
+
else
|
55
55
|
chat.errors[:base] << "Only current chat participants can add users."
|
56
56
|
raise ActiveRecord::RecordInvalid.new(chat)
|
57
57
|
end
|
@@ -5,7 +5,7 @@ class UserLocation < AbstractAdapter
|
|
5
5
|
|
6
6
|
validates_inclusion_of :detectable_type, in: %w(LocationBeacon LocationGps)
|
7
7
|
|
8
|
-
default_scope { includes(:detectable).order("created_at desc") }
|
8
|
+
default_scope { includes(:detectable).order("created_at desc") }
|
9
9
|
|
10
10
|
def coords=(c) # convenience method to set coordinates by an array of [lat,lng,alt]
|
11
11
|
self.lat = c[0]
|
@@ -13,14 +13,14 @@ class UserLocation < AbstractAdapter
|
|
13
13
|
self.alt = c[2]
|
14
14
|
end
|
15
15
|
|
16
|
-
def beacon
|
16
|
+
def beacon
|
17
17
|
detectable.is_a?(LocationBeacon) ? detectable : {}
|
18
18
|
end
|
19
19
|
|
20
|
-
def distance
|
20
|
+
def distance
|
21
21
|
if location.gps && lat && lng
|
22
22
|
location.gps.distance_from(lat,lng)
|
23
|
-
else
|
23
|
+
else
|
24
24
|
nil
|
25
25
|
end
|
26
26
|
end
|
@@ -8,23 +8,23 @@ class ProjectPolicy < ApplicationPolicy
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def project_manager?
|
11
|
-
@user.superuser? || @user.all_admin_projects.include?(record)
|
11
|
+
@user.superuser? || @user.all_admin_projects.include?(record)
|
12
12
|
end
|
13
13
|
|
14
14
|
def show?
|
15
|
-
@user && project_user?
|
15
|
+
@user && project_user?
|
16
16
|
end
|
17
17
|
|
18
18
|
def update?
|
19
|
-
@user && project_manager?
|
19
|
+
@user && project_manager?
|
20
20
|
end
|
21
21
|
|
22
22
|
def create?
|
23
|
-
@user && project_manager?
|
23
|
+
@user && project_manager?
|
24
24
|
end
|
25
25
|
|
26
26
|
def destroy?
|
27
|
-
@user && project_manager?
|
27
|
+
@user && project_manager?
|
28
28
|
end
|
29
29
|
|
30
30
|
class Scope < ApplicationPolicy::Scope
|
@@ -5,7 +5,7 @@ class CreateLocationBeacons < ActiveRecord::Migration
|
|
5
5
|
t.references :company, null: false
|
6
6
|
t.string :mac_address, limit: 12
|
7
7
|
t.string :uuid, null: false, limit: 32
|
8
|
-
t.integer :major, null: false
|
8
|
+
t.integer :major, null: false
|
9
9
|
t.integer :minor, null: false
|
10
10
|
|
11
11
|
t.timestamps null: false
|
data/spec/models/project_spec.rb
CHANGED
@@ -2,15 +2,15 @@ require 'rails_helper'
|
|
2
2
|
|
3
3
|
RSpec.describe Project, type: :model do
|
4
4
|
|
5
|
-
it "should make a valid instance" do
|
5
|
+
it "should make a valid instance" do
|
6
6
|
Project.make.valid?.should == true
|
7
7
|
end
|
8
8
|
|
9
|
-
it "should save a valid instance" do
|
9
|
+
it "should save a valid instance" do
|
10
10
|
Project.make!.should == Project.last
|
11
11
|
end
|
12
12
|
|
13
|
-
it "should be owned by a company" do
|
13
|
+
it "should be owned by a company" do
|
14
14
|
Project.make.owner.kind_of?(Company).should == true
|
15
15
|
end
|
16
16
|
|