introspective_grape 0.3.2 → 0.3.3

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