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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +16 -3
  4. data/CHANGELOG.md +16 -8
  5. data/README.md +6 -6
  6. data/gemfiles/2.0.0-Gemfile +1 -1
  7. data/gemfiles/Gemfile.rails.3.2.22 +1 -1
  8. data/gemfiles/Gemfile.rails.4.1.13 +1 -1
  9. data/gemfiles/Gemfile.rails.4.2.7.1 +1 -1
  10. data/gemfiles/Gemfile.rails.4.2.7.1.new.swagger +1 -1
  11. data/gemfiles/Gemfile.rails.4.2.8 +1 -1
  12. data/gemfiles/Gemfile.rails.5.0.1 +1 -1
  13. data/gemfiles/Gemfile.rails.master +1 -1
  14. data/introspective_grape.gemspec +2 -2
  15. data/lib/introspective_grape/api.rb +16 -16
  16. data/lib/introspective_grape/camel_snake.rb +5 -4
  17. data/lib/introspective_grape/filters.rb +2 -2
  18. data/lib/introspective_grape/formatter/camel_json.rb +12 -9
  19. data/lib/introspective_grape/helpers.rb +3 -3
  20. data/lib/introspective_grape/snake_params.rb +2 -1
  21. data/lib/introspective_grape/traversal.rb +5 -5
  22. data/lib/introspective_grape/validators.rb +1 -1
  23. data/lib/introspective_grape/version.rb +1 -1
  24. data/spec/dummy/app/api/dummy/chat_api.rb +4 -4
  25. data/spec/dummy/app/api/dummy/company_api.rb +1 -1
  26. data/spec/dummy/app/api/dummy/location_api.rb +2 -2
  27. data/spec/dummy/app/api/dummy/project_api.rb +1 -1
  28. data/spec/dummy/app/api/dummy/sessions.rb +3 -3
  29. data/spec/dummy/app/api/dummy/user_api.rb +1 -1
  30. data/spec/dummy/app/api/dummy_api.rb +0 -3
  31. data/spec/dummy/app/api/error_handlers.rb +2 -2
  32. data/spec/dummy/app/models/admin_user.rb +1 -1
  33. data/spec/dummy/app/models/chat.rb +1 -1
  34. data/spec/dummy/app/models/chat_message.rb +1 -1
  35. data/spec/dummy/app/models/chat_user.rb +1 -1
  36. data/spec/dummy/app/models/company.rb +1 -1
  37. data/spec/dummy/app/models/image.rb +1 -1
  38. data/spec/dummy/app/models/project.rb +1 -1
  39. data/spec/dummy/app/models/user.rb +1 -1
  40. data/spec/dummy/app/models/user/chatter.rb +4 -4
  41. data/spec/dummy/app/models/user_location.rb +4 -4
  42. data/spec/dummy/app/policies/location_policy.rb +1 -1
  43. data/spec/dummy/app/policies/project_policy.rb +5 -5
  44. data/spec/dummy/app/policies/role_policy.rb +2 -2
  45. data/spec/dummy/app/policies/user_policy.rb +1 -1
  46. data/spec/dummy/db/migrate/20150414213154_add_user_authentication_token.rb +1 -1
  47. data/spec/dummy/db/migrate/20150601212924_create_location_beacons.rb +1 -1
  48. data/spec/dummy/db/migrate/20150616205336_add_role_user_constraint.rb +1 -1
  49. data/spec/dummy/db/migrate/20150727214950_add_confirmable_to_devise.rb +1 -1
  50. data/spec/dummy/db/migrate/20150820190524_add_user_names.rb +2 -2
  51. data/spec/models/project_spec.rb +3 -3
  52. data/spec/models/role_spec.rb +6 -6
  53. data/spec/models/team_spec.rb +2 -2
  54. data/spec/models/team_user_spec.rb +4 -4
  55. data/spec/models/user_location_spec.rb +1 -1
  56. data/spec/models/user_project_job_spec.rb +2 -2
  57. data/spec/models/user_spec.rb +10 -10
  58. data/spec/requests/chat_api_spec.rb +7 -7
  59. data/spec/requests/company_api_spec.rb +4 -4
  60. data/spec/requests/location_api_spec.rb +10 -10
  61. data/spec/requests/project_api_spec.rb +18 -18
  62. data/spec/requests/role_api_spec.rb +1 -1
  63. data/spec/requests/sessions_api_spec.rb +3 -3
  64. data/spec/requests/swagger_spec.rb +1 -1
  65. data/spec/requests/user_api_spec.rb +13 -13
  66. data/spec/support/blueprints.rb +10 -10
  67. data/spec/support/location_helper.rb +6 -6
  68. data/spec/support/request_helpers.rb +4 -3
  69. metadata +6 -10
  70. data/lib/.DS_Store +0 -0
  71. data/spec/.DS_Store +0 -0
  72. 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
- (params.try(:with_snake_keys)||{}).each do |k,v|
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,3 +1,3 @@
1
1
  module IntrospectiveGrape
2
- VERSION = "0.3.2".freeze
2
+ VERSION = "0.3.3".freeze
3
3
  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
@@ -13,7 +13,7 @@ class Dummy::CompanyAPI < IntrospectiveGrape::API
13
13
  authorize Company.new, :index?
14
14
  present params
15
15
  end
16
-
16
+
17
17
  end
18
18
 
19
19
  class CompanyEntity < Grape::Entity
@@ -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
@@ -31,4 +31,4 @@ class ChatMessage < AbstractAdapter
31
31
  Chat.eager_load(:chat_users).where("chat_users.departed_at IS NULL").order('chats.created_at desc').detect {|c| c.chat_users.map(&:user_id).uniq.sort == users.map(&:id).sort }
32
32
  end
33
33
 
34
- end
34
+ end
@@ -1,6 +1,6 @@
1
1
  class ChatUser < AbstractAdapter
2
2
  belongs_to :chat
3
- belongs_to :user
3
+ belongs_to :user
4
4
 
5
5
  alias_attribute :joined_at, :created_at
6
6
  alias_attribute :left_at, :departed_at
@@ -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
@@ -4,7 +4,7 @@ class LocationPolicy < ApplicationPolicy
4
4
  end
5
5
 
6
6
  def show?
7
- @user
7
+ @user
8
8
  end
9
9
 
10
10
  def update?
@@ -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,11 +5,11 @@ class RolePolicy < ApplicationPolicy
5
5
  end
6
6
 
7
7
  def show?
8
- @user.admin?(record.ownable)
8
+ @user.admin?(record.ownable)
9
9
  end
10
10
 
11
11
  def update?
12
- @user.admin?(record.ownable)
12
+ @user.admin?(record.ownable)
13
13
  end
14
14
 
15
15
  def create?
@@ -1,6 +1,6 @@
1
1
  class UserPolicy < ApplicationPolicy
2
2
 
3
- def sessions?
3
+ def sessions?
4
4
  true
5
5
  end
6
6
 
@@ -1,6 +1,6 @@
1
1
  class AddUserAuthenticationToken < ActiveRecord::Migration
2
2
  def change
3
- add_column :users, :authentication_token, :string
3
+ add_column :users, :authentication_token, :string
4
4
  add_index :users, :authentication_token, :unique => true
5
5
  end
6
6
 
@@ -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
@@ -3,7 +3,7 @@ class AddRoleUserConstraint < ActiveRecord::Migration
3
3
  change_column :roles, :user_id, :integer, null: false
4
4
  end
5
5
 
6
- def down
6
+ def down
7
7
  change_column :roles, :user_id, :integer, null: true
8
8
  end
9
9
  end
@@ -1,6 +1,6 @@
1
1
  class AddConfirmableToDevise < ActiveRecord::Migration
2
2
  def change
3
- change_table(:users) do |t|
3
+ change_table(:users) do |t|
4
4
  t.string :confirmation_token
5
5
  t.datetime :confirmed_at
6
6
  t.datetime :confirmation_sent_at
@@ -1,6 +1,6 @@
1
1
  class AddUserNames < ActiveRecord::Migration
2
2
  def change
3
- add_column :users, :first_name, :string
4
- add_column :users, :last_name, :string
3
+ add_column :users, :first_name, :string
4
+ add_column :users, :last_name, :string
5
5
  end
6
6
  end
@@ -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