introspective_grape 0.0.4 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +1164 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +4 -2
  7. data/CHANGELOG.md +58 -0
  8. data/Gemfile +5 -3
  9. data/README.md +70 -17
  10. data/introspective_grape.gemspec +8 -8
  11. data/lib/.DS_Store +0 -0
  12. data/lib/introspective_grape/api.rb +177 -216
  13. data/lib/introspective_grape/camel_snake.rb +28 -59
  14. data/lib/introspective_grape/filters.rb +66 -0
  15. data/lib/introspective_grape/formatter/camel_json.rb +14 -0
  16. data/lib/introspective_grape/helpers.rb +63 -0
  17. data/lib/introspective_grape/traversal.rb +54 -0
  18. data/lib/introspective_grape/version.rb +1 -1
  19. data/lib/introspective_grape.rb +11 -0
  20. data/spec/.DS_Store +0 -0
  21. data/spec/dummy/Gemfile +5 -3
  22. data/spec/dummy/app/api/.DS_Store +0 -0
  23. data/spec/dummy/app/api/api_helpers.rb +5 -6
  24. data/spec/dummy/app/api/dummy/chat_api.rb +1 -2
  25. data/spec/dummy/app/api/dummy/company_api.rb +16 -1
  26. data/spec/dummy/app/api/dummy/location_api.rb +3 -3
  27. data/spec/dummy/app/api/dummy/project_api.rb +1 -0
  28. data/spec/dummy/app/api/dummy/sessions.rb +4 -8
  29. data/spec/dummy/app/api/dummy/user_api.rb +3 -1
  30. data/spec/dummy/app/api/dummy_api.rb +6 -6
  31. data/spec/dummy/app/api/error_handlers.rb +2 -2
  32. data/spec/dummy/app/models/chat_user.rb +1 -1
  33. data/spec/dummy/app/models/image.rb +2 -2
  34. data/spec/dummy/app/models/role.rb +1 -1
  35. data/spec/dummy/app/models/user/chatter.rb +6 -6
  36. data/spec/dummy/app/models/user_project_job.rb +3 -3
  37. data/spec/dummy/config/application.rb +1 -1
  38. data/spec/dummy/db/migrate/20150824215701_create_images.rb +3 -3
  39. data/spec/dummy/db/schema.rb +1 -1
  40. data/spec/models/image_spec.rb +1 -1
  41. data/spec/models/role_spec.rb +5 -5
  42. data/spec/models/user_location_spec.rb +2 -2
  43. data/spec/models/user_project_job_spec.rb +1 -1
  44. data/spec/rails_helper.rb +3 -1
  45. data/spec/requests/company_api_spec.rb +28 -0
  46. data/spec/requests/location_api_spec.rb +19 -2
  47. data/spec/requests/project_api_spec.rb +34 -3
  48. data/spec/requests/sessions_api_spec.rb +1 -1
  49. data/spec/requests/user_api_spec.rb +24 -3
  50. data/spec/support/blueprints.rb +3 -3
  51. data/spec/support/location_helper.rb +26 -21
  52. data/spec/support/request_helpers.rb +1 -3
  53. metadata +58 -28
  54. data/spec/dummy/app/api/active_record_helpers.rb +0 -17
@@ -0,0 +1,66 @@
1
+ module IntrospectiveGrape::Filters
2
+ #
3
+ # Allow filters on all whitelisted model attributes (from api_params)
4
+ #
5
+ def simple_filters(klass, model, api_params)
6
+ @simple_filters ||= api_params.select {|p| p.is_a? Symbol }.map { |field|
7
+ (klass.param_type(model,field) == DateTime ? ["#{field}_start", "#{field}_end"] : field.to_s)
8
+ }.flatten
9
+ end
10
+
11
+ def timestamp_filter(klass,model,field)
12
+ filter = field.sub(/_(end|start)\z/,'')
13
+ if field =~ /_(end|start)\z/ && klass.param_type(model,filter) == DateTime
14
+ filter
15
+ else
16
+ false
17
+ end
18
+ end
19
+
20
+ def identifier_filter(klass,model,field)
21
+ if field.ends_with?('id') && klass.param_type(model,field) == Integer
22
+ field
23
+ else
24
+ false
25
+ end
26
+ end
27
+
28
+ def declare_filter_params(dsl, klass, model, api_params)
29
+ # Declare optional parameters for filtering parameters, create two parameters per
30
+ # timestamp, a Start and an End, to apply a date range.
31
+ simple_filters(klass, model, api_params).each do |field|
32
+ if timestamp_filter(klass,model,field)
33
+ terminal = field.ends_with?("_start") ? "initial" : "terminal"
34
+ dsl.optional field, type: klass.param_type(model,field), description: "Constrain #{field} by #{terminal} date."
35
+ elsif identifier_filter(klass,model,field)
36
+ dsl.optional field, type: Array[Integer], coerce_with: ->(val) { val.split(',') }
37
+ else
38
+ dsl.optional field, type: klass.param_type(model,field), description: "Filter on #{field} by value."
39
+ end
40
+ end
41
+ dsl.optional :filter, type: String, description: "JSON of conditions for query. If you're familiar with ActiveRecord's query conventions you can build more complex filters, e.g. against included child associations, e.g. {\"<association_name>_<parent>\":{\"field\":\"value\"}}"
42
+
43
+ end
44
+
45
+ def apply_filter_params(klass, model, api_params, params, records)
46
+ simple_filters(klass, model, api_params).each do |field|
47
+ next if params[field].blank?
48
+
49
+ if timestamp_filter(klass,model,field)
50
+ op = field.ends_with?("_start") ? ">=" : "<="
51
+ records = records.where("#{timestamp_filter(klass,model,field)} #{op} ?", Time.zone.parse(params[field]))
52
+ else
53
+ records = records.where(field => params[field])
54
+ end
55
+ end
56
+
57
+ if params[:filter].present?
58
+ filters = JSON.parse( params[:filter].delete('\\') )
59
+ filters.each do |key, value|
60
+ records = records.where(key => value) if value.present?
61
+ end
62
+ end
63
+
64
+ records
65
+ end
66
+ end
@@ -0,0 +1,14 @@
1
+ # Add a formatter to grape that converts all snake case hash keys from ruby to camel case.
2
+ module IntrospectiveGrape
3
+ module Formatter
4
+ module CamelJson
5
+ def self.call(object, _env)
6
+ if object.respond_to?(:to_json)
7
+ JSON.parse(object.to_json).with_camel_keys.to_json
8
+ else
9
+ MultiJson.dump(object).with_camel_keys.to_json
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ module IntrospectiveGrape::Helpers
2
+ API_ACTIONS = [:index,:show,:create,:update,:destroy].freeze
3
+ def authentication_method=(method)
4
+ # IntrospectiveGrape::API.authentication_method=
5
+ @authentication_method = method
6
+ end
7
+
8
+ def authentication_method(context)
9
+ # Default to "authenticate!" or as grape docs once suggested, "authorize!"
10
+ if @authentication_method
11
+ @authentication_method
12
+ elsif context.respond_to?('authenticate!')
13
+ 'authenticate!'
14
+ elsif context.respond_to?('authorize!')
15
+ 'authorize!'
16
+ end
17
+ end
18
+
19
+ def paginate(args={})
20
+ @pagination = args
21
+ end
22
+
23
+ def pagination
24
+ @pagination
25
+ end
26
+
27
+ def exclude_actions(model, *args)
28
+ @exclude_actions ||= {}; @exclude_actions[model.name] ||= []
29
+ args.flatten!
30
+ args = API_ACTIONS if args.include?(:all)
31
+ args = [] if args.include?(:none)
32
+
33
+ undefined_actions = args.compact-API_ACTIONS
34
+ raise "#{model.name} defines invalid actions: #{undefined_actions}" if undefined_actions.present?
35
+
36
+ @exclude_actions[model.name] = args.present? ? args.compact : @exclude_actions[model.name] || []
37
+ end
38
+
39
+ def include_actions(model, *args)
40
+ @exclude_actions ||= {}; @exclude_actions[model.name] ||= []
41
+ @exclude_actions[model.name] = API_ACTIONS-exclude_actions(model, args)
42
+ end
43
+
44
+
45
+ def default_includes(model, *args)
46
+ @default_includes ||= {}
47
+ @default_includes[model.name] = args.present? ? args.flatten : @default_includes[model.name] || []
48
+ end
49
+
50
+ def whitelist(whitelist=nil)
51
+ return @whitelist if !whitelist
52
+ @whitelist = whitelist
53
+ end
54
+
55
+ def skip_presence_validations(fields=nil)
56
+ return @skip_presence_fields||[] if !fields
57
+ @skip_presence_fields = [fields].flatten
58
+ end
59
+
60
+
61
+ end
62
+
63
+
@@ -0,0 +1,54 @@
1
+ module IntrospectiveGrape::Traversal
2
+ # For deeply nested endpoints we want to present the record being affected, these
3
+ # methods traverse down from the parent instance to the child model associations
4
+ # of the deeply nested route.
5
+
6
+ def find_leaves(routes, record, params)
7
+ # Traverse down our route and find the leaf's siblings from its parent, e.g.
8
+ # project/#/teams/#/team_users ~> project.find.teams.find.team_users
9
+ # (the traversal of the intermediate nodes occurs in find_leaf())
10
+ return record if routes.size < 2 # the leaf is the root
11
+ record = find_leaf(routes, record, params)
12
+ if record
13
+ assoc = routes.last
14
+ if assoc.many?
15
+ leaves = record.send( assoc.reflection.name ).includes( default_includes(assoc.model) )
16
+ verify_records_found(leaves, routes)
17
+ leaves
18
+ else
19
+ # has_one associations don't return a CollectionProxy and so don't support
20
+ # eager loading.
21
+ record.send( assoc.reflection.name )
22
+ end
23
+ end
24
+ end
25
+
26
+ def verify_records_found(leaves, routes)
27
+ unless (leaves.map(&:class) - [routes.last.model]).empty?
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
+ end
30
+ end
31
+
32
+ def find_leaf(routes, record, params)
33
+ return record unless routes.size > 1
34
+ # For deeply nested routes we need to search from the root of the API to the leaf
35
+ # of its nested associations in order to guarantee the validity of the relationship,
36
+ # the authorization on the parent model, and the sanity of passed parameters.
37
+ routes[1..-1].each_with_index do |r|
38
+ if record && params[r.key]
39
+ ref = r.reflection
40
+ record = record.send(ref.name).where( id: params[r.key] ).first if ref
41
+ end
42
+ end
43
+
44
+ verify_record_found(routes, params, record)
45
+ record
46
+ end
47
+
48
+ def verify_record_found(routes, params, record)
49
+ if params[routes.last.key] && record.class != routes.last.model
50
+ raise ActiveRecord::RecordNotFound.new("No #{routes.last.model.name} with ID '#{params[routes.last.key]}'")
51
+ end
52
+ end
53
+
54
+ end
@@ -1,3 +1,3 @@
1
1
  module IntrospectiveGrape
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.9".freeze
3
3
  end
@@ -1,4 +1,15 @@
1
1
  module IntrospectiveGrape
2
2
  autoload :API, 'introspective_grape/api'
3
3
  autoload :CamelSnake, 'introspective_grape/camel_snake'
4
+ autoload :Filters, 'introspective_grape/filters'
5
+ autoload :Helpers, 'introspective_grape/helpers'
6
+ autoload :Traversal, 'introspective_grape/traversal'
7
+
8
+ module Formatter
9
+ autoload :CamelJson, 'introspective_grape/formatter/camel_json'
10
+ end
11
+
12
+ def self.config
13
+ @config = OpenStruct.new(camelize_parameters: true)
14
+ end
4
15
  end
data/spec/.DS_Store ADDED
Binary file
data/spec/dummy/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
-
1
+ source 'https://rubygems.org'
2
+ gem 'grape-kaminari'
2
3
  gem 'pundit'
3
- gem 'paperclip', '3.4.2'
4
- gem 'delayed_paperclip', git: 'https://github.com/buermann/delayed_paperclip.git'
4
+ #gem 'byebug'
5
+ gem 'paperclip'
6
+ gem 'delayed_paperclip'
Binary file
@@ -1,5 +1,4 @@
1
1
  module ApiHelpers
2
- include IntrospectiveGrape::CamelSnake
3
2
  def warden
4
3
  env['warden']
5
4
  end
@@ -8,13 +7,13 @@ module ApiHelpers
8
7
  warden.user || params[:api_key].present? && @user = User.find_by_authentication_token(params[:api_key])
9
8
  end
10
9
 
11
- def authorize!
12
- unauthorized! unless current_user
10
+ def authenticate!
11
+ unauthenticated! unless current_user
13
12
  end
14
13
 
15
- # returns an 'unauthorized' response
16
- def unauthorized!(error_type = nil)
17
- respond_error!('unauthorized', error_type, 401)
14
+ # returns an 'unauthenticated' response
15
+ def unauthenticated!(error_type = nil)
16
+ respond_error!('unauthenticated', error_type, 401)
18
17
  end
19
18
 
20
19
  # returns a error response with given type, message_key and status
@@ -1,8 +1,7 @@
1
1
  class Dummy::ChatAPI < DummyAPI
2
- Chat.default_includes :chat
3
2
 
4
3
  before do
5
- authorize!
4
+ authenticate!
6
5
  end
7
6
 
8
7
  resource :chats do
@@ -1,5 +1,20 @@
1
1
  class Dummy::CompanyAPI < IntrospectiveGrape::API
2
- restful Company
2
+ paginate
3
+
4
+ restful Company do
5
+
6
+ desc "Test default values in an extra endpoint"
7
+ params do
8
+ optional :boolean_default, type: Boolean, default: false
9
+ optional :string_default, type: String, default: "foo"
10
+ optional :integer_default, type: Integer, default: 123
11
+ end
12
+ get '/special/list' do
13
+ authorize Company.new, :index?
14
+ present params
15
+ end
16
+
17
+ end
3
18
 
4
19
  class CompanyEntity < Grape::Entity
5
20
  expose :id, :name, :short_name, :created_at, :updated_at
@@ -1,10 +1,10 @@
1
1
  class Dummy::LocationAPI < IntrospectiveGrape::API
2
+ exclude_actions Location, :none
3
+ include_actions LocationBeacon, :index
4
+ include_actions LocationGps, :index
2
5
 
3
6
  default_includes Location, :child_locations, :gps, :beacons, :locatables
4
7
 
5
- exclude_actions LocationBeacon, :show,:create,:update,:destroy
6
- exclude_actions LocationGps, :show,:create,:update,:destroy
7
-
8
8
  restful Location, [:name, :kind,
9
9
  {gps_attributes: [:id, :lat, :lng, :alt, :_destroy]},
10
10
  {beacons_attributes: [:id, :company_id, :mac_address, :uuid, :major, :minor, :_destroy]},
@@ -9,6 +9,7 @@ class Dummy::ProjectAPI < IntrospectiveGrape::API
9
9
  exclude_actions Team, :show
10
10
  exclude_actions TeamUser, :show,:update
11
11
 
12
+ paginate per_page: 2, max_per_page: 10, offset: 2
12
13
 
13
14
  restful Project, [:id, teams_attributes: [:id,:name,:_destroy, team_users_attributes: [:id, :user_id, :_destroy] ]]
14
15
 
@@ -16,15 +16,10 @@ class Dummy::Sessions < Grape::API
16
16
  if user && user.valid_password?(params[:password]) && user.valid_for_authentication?
17
17
 
18
18
  # commented out for now, User model is not yet confirmable
19
- #unauthorized! DummyAPI::USER_NOT_CONFIRMED unless user.confirmed?
19
+ #unauthenticated! DummyAPI::USER_NOT_CONFIRMED unless user.confirmed?
20
20
 
21
21
  token = nil
22
22
  if params[:token]
23
- payload = {
24
- uid: "#{user.id}", # uid must be a string
25
- email: user.email,
26
- avatar_url: user.avatar_url
27
- }
28
23
  user.authentication_token = SecureRandom.urlsafe_base64(nil, false)
29
24
  user.save
30
25
  end
@@ -33,7 +28,7 @@ class Dummy::Sessions < Grape::API
33
28
  env['warden'].set_user(user, scope: :user)
34
29
  present user, with: Dummy::Entities::User, token: token
35
30
  else
36
- unauthorized! DummyAPI::BAD_LOGIN
31
+ unauthenticated! DummyAPI::BAD_LOGIN
37
32
  end
38
33
  end
39
34
 
@@ -43,7 +38,8 @@ class Dummy::Sessions < Grape::API
43
38
  end
44
39
  delete '/' do
45
40
  authorize User.new, :sessions?
46
- if u = User.find_by_authentication_token(params[:api_key])
41
+ u = User.find_by_authentication_token(params[:api_key])
42
+ if u
47
43
  u.authentication_token = nil
48
44
  {status: u.save!}
49
45
  else
@@ -2,10 +2,12 @@ class Dummy::UserAPI < IntrospectiveGrape::API
2
2
 
3
3
  skip_presence_validations :password
4
4
 
5
+ include_actions User, :all
5
6
  exclude_actions Role, :show,:update
6
7
  exclude_actions UserProjectJob, :show,:update
7
8
 
8
9
  restful User, [:id, :email, :password, :first_name, :last_name, :skip_confirmation_email,
10
+ :created_at, :updated_at,
9
11
  user_project_jobs_attributes: [:id, :job_id, :project_id, :_destroy],
10
12
  roles_attributes: [:id, :ownable_type, :ownable_id, :_destroy],
11
13
  avatar_attributes: [:id, :file, :_destroy]
@@ -24,7 +26,7 @@ class Dummy::UserAPI < IntrospectiveGrape::API
24
26
  end
25
27
 
26
28
  class UserEntity < Grape::Entity
27
- expose :id, :email, :first_name, :last_name, :avatar_url
29
+ expose :id, :email, :first_name, :last_name, :avatar_url, :created_at
28
30
  expose :roles, as: :roles_attributes, using: RoleEntity
29
31
  expose :user_project_jobs, as: :user_project_jobs_attributes, using: UserProjectJobEntity
30
32
  end
@@ -1,27 +1,27 @@
1
1
  #require 'grape-swagger'
2
2
  #require 'grape-entity'
3
- require 'active_record_helpers'
4
3
  #require 'introspective_grape/camel_snake'
5
4
 
6
5
  class DummyAPI < Grape::API
7
6
  version 'v1', using: :path
8
- format :json
7
+ format :json
8
+ formatter :json, IntrospectiveGrape::Formatter::CamelJson
9
9
  default_format :json
10
10
 
11
11
  include ErrorHandlers
12
12
  helpers PermissionsHelper
13
13
  helpers ApiHelpers
14
14
 
15
- USER_NOT_CONFIRMED = 'user_not_confirmed' # "Your account must be confirmed, please check your email inbox."
16
- BAD_LOGIN = 'bad_login' # incorrect username or password'
15
+ USER_NOT_CONFIRMED = 'user_not_confirmed'.freeze
16
+ BAD_LOGIN = 'bad_login'.freeze
17
17
 
18
18
  before do
19
19
  # sets server date in response header. This can be used on the client side
20
- header "X-Server-Date", "#{Time.now.to_i}"
20
+ header "X-Server-Date", Time.now.to_i.to_s
21
21
  header "Expires", 1.year.ago.httpdate
22
22
  # Convert incoming camel case params to snake case: grape will totally blow this
23
23
  # if the params hash is not a Hashie::Mash, so make it one of those:
24
- #@params = Hashie::Mash.new(snake_keys(params))
24
+ #@params = Hashie::Mash.new(params.with_snake_keys)
25
25
  end
26
26
 
27
27
  before_validation do
@@ -17,11 +17,11 @@ module ErrorHandlers
17
17
  error_response message: "Join record not found! #{e.message}", status: 404
18
18
  end
19
19
 
20
- m.rescue_from Pundit::NotAuthorizedError do |e|
20
+ m.rescue_from Pundit::NotAuthorizedError do
21
21
  error_response message: "Forbidden", status: 403
22
22
  end
23
23
 
24
- m.rescue_from Pundit::NotDefinedError do |e|
24
+ m.rescue_from Pundit::NotDefinedError do
25
25
  error_response message: "Policy not implemented", status: 501
26
26
  end
27
27
  end
@@ -10,7 +10,7 @@ class ChatUser < AbstractAdapter
10
10
  validate :user_not_already_active, on: :create
11
11
 
12
12
  def user_not_already_active
13
- errors[:base] << "#{user.name} is already present in this chat." if chat.chat_users.where(user_id: user.id, departed_at: nil).count > 0 if user.persisted?
13
+ errors[:base] << "#{user.name} is already present in this chat." if chat.chat_users.where(user_id: user.id, departed_at: nil).count > 0 && user.persisted?
14
14
  end
15
15
 
16
16
  end
@@ -11,10 +11,10 @@ class Image < ActiveRecord::Base
11
11
 
12
12
  #process_in_background :file, processing_image_url: 'empty_avatar.png'
13
13
 
14
- Paperclip.interpolates :imageable_type do |attachment, style|
14
+ Paperclip.interpolates :imageable_type do |attachment, _style|
15
15
  attachment.instance.imageable_type.try(:pluralize)
16
16
  end
17
- Paperclip.interpolates :imageable_id do |attachment, style|
17
+ Paperclip.interpolates :imageable_id do |attachment, _style|
18
18
  attachment.instance.imageable_id
19
19
  end
20
20
 
@@ -15,7 +15,7 @@ class Role < AbstractAdapter
15
15
  ownable_type == 'SuperUser' ? SuperUser.new : super
16
16
  end
17
17
 
18
- def self.ownable_assign_options(model=nil)
18
+ def self.ownable_assign_options(_model=nil)
19
19
  ([SuperUser.new] + Company.all + Project.all).map { |i| [ "#{i.class}: #{i.name}", "#{i.class}-#{i.id}"] }
20
20
  end
21
21
 
@@ -2,15 +2,15 @@ module User::Chatter
2
2
 
3
3
  def message_query(chat_id, new = true)
4
4
  messages.joins(:chat_message_users)
5
- .where('chat_message_users.user_id'=> id)
6
- .where(new ? {'chat_message_users.read_at'=>nil} : '')
7
- .where(chat_id ? {'chat_messages.chat_id'=> chat_id} : '')
8
- .order('') # or it will add an order by id clause that breaks the count query.
5
+ .where('chat_message_users.user_id'=> id)
6
+ .where(new ? {'chat_message_users.read_at'=>nil} : '')
7
+ .where(chat_id ? {'chat_messages.chat_id'=> chat_id} : '')
8
+ .order('') # or it will add an order by id clause that breaks the count query.
9
9
  end
10
10
 
11
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
- new = message_query(chat_id, new = true)
13
+ new = message_query(chat_id)
14
14
  .select("chat_messages.chat_id, count(chat_messages.id) as count")
15
15
  .group('chat_id')
16
16
 
@@ -20,7 +20,7 @@ module User::Chatter
20
20
  def read_messages(chat= nil, mark_as_read= false, new= true)
21
21
  chat_id = chat.kind_of?(Chat) ? chat.id : chat
22
22
  new = message_query(chat_id, new).order('chat_messages.created_at').includes(:author) # :chat?
23
- new.map(&:chat).uniq.each {|chat| mark_as_read(chat) } if mark_as_read
23
+ new.map(&:chat).uniq.each {|c| mark_as_read(c) } if mark_as_read
24
24
  new
25
25
  end
26
26
 
@@ -5,9 +5,9 @@ class UserProjectJob < AbstractAdapter
5
5
 
6
6
  validates_inclusion_of :job, in: proc {|r| r.project.try(:jobs) || [] }
7
7
 
8
- delegate :email, :avatar_url, to: :user
9
- delegate :title, to: :job
10
- delegate :name, to: :project
8
+ delegate :email, :avatar_url, to: :user, allow_nil: true
9
+ delegate :title, to: :job, allow_nil: true
10
+ delegate :name, to: :project, allow_nil: true
11
11
 
12
12
  def self.options_for_job(project=nil)
13
13
  project.jobs
@@ -5,7 +5,7 @@ require "active_record/railtie"
5
5
  require "action_controller/railtie"
6
6
  require "action_mailer/railtie"
7
7
  require "action_view/railtie"
8
- require "sprockets/railtie"
8
+ #require "sprockets/railtie"
9
9
  require 'activerecord-tableless'
10
10
  require 'devise'
11
11
  require 'devise/async'
@@ -4,10 +4,10 @@ class CreateImages < ActiveRecord::Migration
4
4
  t.references :imageable, polymorphic: true, index: true
5
5
  t.attachment :file
6
6
  t.boolean :file_processing, null: false, default: false
7
- t.json :meta
7
+ t.json :meta
8
8
  t.string :source
9
- t.float :lat
10
- t.float :lng
9
+ t.float :lat
10
+ t.float :lng
11
11
  t.timestamp :taken_at
12
12
  t.timestamps null: false
13
13
  end
@@ -102,7 +102,7 @@ ActiveRecord::Schema.define(version: 20150909225019) do
102
102
  t.integer "file_file_size"
103
103
  t.datetime "file_updated_at"
104
104
  t.boolean "file_processing", default: false, null: false
105
- t.text "meta"
105
+ t.text "meta"
106
106
  t.string "source"
107
107
  t.float "lat"
108
108
  t.float "lng"
@@ -6,7 +6,7 @@ RSpec.describe Image, type: :model do
6
6
 
7
7
  it { should have_attached_file(:file) }
8
8
  it { should validate_attachment_content_type(:file).
9
- allowing('image/png', 'image/gif', 'image/jpeg')
9
+ allowing('image/png', 'image/gif', 'image/jpeg')
10
10
  }
11
11
  it { should validate_attachment_size(:file).less_than(2.megabytes) }
12
12
 
@@ -25,35 +25,35 @@ RSpec.describe Role, type: :model do
25
25
  context "User helper methods" do
26
26
  it "should register a user as a super user" do
27
27
  user.superuser?.should == false
28
- ur = Role.create!(user:user, ownable: SuperUser.new)
28
+ Role.create!(user:user, ownable: SuperUser.new)
29
29
  user.reload
30
30
  user.superuser?.should == true
31
31
  end
32
32
 
33
33
  it "should register a company admin" do
34
34
  user.admin?(company).should == false
35
- ur = Role.create!(user:user, ownable: company)
35
+ Role.create!(user:user, ownable: company)
36
36
  user.reload
37
37
  user.admin?(company).should == true
38
38
  end
39
39
 
40
40
  it "should register a project administrator" do
41
41
  user.admin?(project).should == false
42
- ur = Role.create!(user:user, ownable: project)
42
+ Role.create!(user:user, ownable: project)
43
43
  user.reload
44
44
  user.admin?(project).should == true
45
45
  end
46
46
 
47
47
  it "should register a user a company admin if admin of any company" do
48
48
  user.company_admin?.should == false
49
- ur = Role.create!(user:user, ownable: company)
49
+ Role.create!(user:user, ownable: company)
50
50
  user.reload
51
51
  user.company_admin?.should == true
52
52
  end
53
53
 
54
54
  it "should register a user as a project admin if admin of any project" do
55
55
  user.project_admin?.should == false
56
- ur = Role.create!(user:user, ownable: project)
56
+ Role.create!(user:user, ownable: project)
57
57
  user.reload
58
58
  user.project_admin?.should == true
59
59
  end
@@ -16,7 +16,7 @@ RSpec.describe UserLocation, type: :model do
16
16
 
17
17
  it "logs a user's locations by beacon" do
18
18
  beacon = LocationBeacon.last
19
- p1 = user.user_locations.build(location: beacon.location, detectable: beacon, coords: rand_coords)
19
+ user.user_locations.build(location: beacon.location, detectable: beacon, coords: rand_coords)
20
20
  user.save.should == true
21
21
  p2 = user.user_locations.build(location: beacon.location, detectable: beacon, coords: rand_coords)
22
22
  user.save.should == true
@@ -25,7 +25,7 @@ RSpec.describe UserLocation, type: :model do
25
25
 
26
26
  it "logs a user's beacon location by gps" do
27
27
  gps = LocationGps.last
28
- p1 = user.user_locations.build(location: gps.location, detectable: gps, coords: rand_coords)
28
+ user.user_locations.build(location: gps.location, detectable: gps, coords: rand_coords)
29
29
  user.save.should == true
30
30
  p2 = user.user_locations.build(location: gps.location, detectable: gps, coords: rand_coords)
31
31
  user.save.should == true
@@ -22,7 +22,7 @@ RSpec.describe UserProjectJob, type: :model do
22
22
  j = Job.make!
23
23
  p.jobs.push j
24
24
  p.save
25
- r = UserProjectJob.make!(project: p, job: j)
25
+ UserProjectJob.make!(project: p, job: j)
26
26
  UserProjectJob.options_for_job(p).should == p.jobs
27
27
  end
28
28
 
data/spec/rails_helper.rb CHANGED
@@ -1,4 +1,6 @@
1
- ENV["RAILS_ENV"] ||= 'test'
1
+ require 'coveralls'
2
+ Coveralls.wear!('rails')
3
+ ENV["RAILS_ENV"] = 'test'
2
4
  require File.expand_path("../dummy/config/environment", __FILE__)
3
5
  require 'rspec/rails'
4
6
  require 'support/request_helpers'