shamu 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +26 -0
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +89 -30
  5. data/.yardopts +4 -5
  6. data/Gemfile +24 -12
  7. data/Guardfile +5 -0
  8. data/LABELS.md +22 -0
  9. data/README.md +41 -0
  10. data/Rakefile +12 -0
  11. data/circle.yml +7 -3
  12. data/config.ru +7 -0
  13. data/lib/shamu/active_record.rb +7 -0
  14. data/lib/shamu/attributes/assignment.rb +114 -0
  15. data/lib/shamu/attributes/equality.rb +40 -0
  16. data/lib/shamu/attributes/fluid_assignment.rb +49 -0
  17. data/lib/shamu/attributes/validation.rb +74 -0
  18. data/lib/shamu/attributes.rb +255 -0
  19. data/lib/shamu/auditing/README.md +0 -0
  20. data/lib/shamu/auditing/audit_record.rb +32 -0
  21. data/lib/shamu/auditing/auditing_service.rb +32 -0
  22. data/lib/shamu/auditing/list_scope.rb +22 -0
  23. data/lib/shamu/auditing/logging_auditing_service.rb +16 -0
  24. data/lib/shamu/auditing/support.rb +75 -0
  25. data/lib/shamu/auditing/transaction.rb +58 -0
  26. data/lib/shamu/auditing.rb +12 -0
  27. data/lib/shamu/entities/README.md +1 -0
  28. data/lib/shamu/entities/active_record.rb +123 -0
  29. data/lib/shamu/entities/active_record_soft_destroy.rb +91 -0
  30. data/lib/shamu/entities/entity.rb +196 -0
  31. data/lib/shamu/entities/entity_path.rb +87 -0
  32. data/lib/shamu/entities/identity_cache.rb +64 -0
  33. data/lib/shamu/entities/list.rb +54 -0
  34. data/lib/shamu/entities/list_scope/dates.rb +57 -0
  35. data/lib/shamu/entities/list_scope/paging.rb +51 -0
  36. data/lib/shamu/entities/list_scope/scoped_paging.rb +65 -0
  37. data/lib/shamu/entities/list_scope/sorting.rb +76 -0
  38. data/lib/shamu/entities/list_scope.rb +105 -0
  39. data/lib/shamu/entities/null_entity.rb +88 -0
  40. data/lib/shamu/entities.rb +11 -0
  41. data/lib/shamu/error.rb +23 -5
  42. data/lib/shamu/events/README.md +0 -0
  43. data/lib/shamu/events/active_record/channel.rb +36 -0
  44. data/lib/shamu/events/active_record/message.rb +52 -0
  45. data/lib/shamu/events/active_record/migration.rb +49 -0
  46. data/lib/shamu/events/active_record/runner.rb +28 -0
  47. data/lib/shamu/events/active_record/service.rb +174 -0
  48. data/lib/shamu/events/active_record.rb +13 -0
  49. data/lib/shamu/events/channel_stats.rb +23 -0
  50. data/lib/shamu/events/error.rb +24 -0
  51. data/lib/shamu/events/events_service.rb +136 -0
  52. data/lib/shamu/events/in_memory/async_service.rb +48 -0
  53. data/lib/shamu/events/in_memory/service.rb +97 -0
  54. data/lib/shamu/events/in_memory.rb +10 -0
  55. data/lib/shamu/events/message.rb +38 -0
  56. data/lib/shamu/events/support.rb +60 -0
  57. data/lib/shamu/events.rb +12 -0
  58. data/lib/shamu/features/README.md +0 -0
  59. data/lib/shamu/features/conditions/condition.rb +39 -0
  60. data/lib/shamu/features/conditions/env.rb +37 -0
  61. data/lib/shamu/features/conditions/hosts.rb +25 -0
  62. data/lib/shamu/features/conditions/matching.rb +16 -0
  63. data/lib/shamu/features/conditions/not_matching.rb +16 -0
  64. data/lib/shamu/features/conditions/percentage.rb +44 -0
  65. data/lib/shamu/features/conditions/proc.rb +54 -0
  66. data/lib/shamu/features/conditions/roles.rb +23 -0
  67. data/lib/shamu/features/conditions/schedule_at.rb +27 -0
  68. data/lib/shamu/features/conditions.rb +18 -0
  69. data/lib/shamu/features/config_service.rb +10 -0
  70. data/lib/shamu/features/context.rb +80 -0
  71. data/lib/shamu/features/env_store.rb +88 -0
  72. data/lib/shamu/features/errors.rb +29 -0
  73. data/lib/shamu/features/features_service.rb +168 -0
  74. data/lib/shamu/features/list_scope.rb +30 -0
  75. data/lib/shamu/features/selector.rb +50 -0
  76. data/lib/shamu/features/support.rb +51 -0
  77. data/lib/shamu/features/toggle.rb +149 -0
  78. data/lib/shamu/features/toggle_codec.rb +69 -0
  79. data/lib/shamu/features.rb +16 -0
  80. data/lib/shamu/locale/en.yml +22 -2
  81. data/lib/shamu/logger.rb +13 -0
  82. data/lib/shamu/rack/README.md +0 -0
  83. data/lib/shamu/rack/cookies.rb +115 -0
  84. data/lib/shamu/rack/cookies_middleware.rb +26 -0
  85. data/lib/shamu/rack/query_params.rb +41 -0
  86. data/lib/shamu/rack/query_params_middleware.rb +24 -0
  87. data/lib/shamu/rack.rb +12 -0
  88. data/lib/shamu/rails/controller.rb +131 -0
  89. data/lib/shamu/rails/entity.rb +168 -0
  90. data/lib/shamu/rails/features.rb +13 -0
  91. data/lib/shamu/rails/railtie.rb +30 -0
  92. data/lib/shamu/rails.rb +10 -0
  93. data/lib/shamu/rspec/matchers.rb +44 -0
  94. data/lib/shamu/rspec.rb +1 -0
  95. data/lib/shamu/security/README.md +0 -0
  96. data/lib/shamu/security/active_record_policy.rb +106 -0
  97. data/lib/shamu/security/error.rb +65 -0
  98. data/lib/shamu/security/hashed_value.rb +71 -0
  99. data/lib/shamu/security/no_policy.rb +15 -0
  100. data/lib/shamu/security/policy.rb +289 -0
  101. data/lib/shamu/security/policy_refinement.rb +50 -0
  102. data/lib/shamu/security/policy_rule.rb +59 -0
  103. data/lib/shamu/security/principal.rb +72 -0
  104. data/lib/shamu/security/roles.rb +62 -0
  105. data/lib/shamu/security/roles_service.rb +30 -0
  106. data/lib/shamu/security/support.rb +83 -0
  107. data/lib/shamu/security.rb +43 -0
  108. data/lib/shamu/services/README.md +2 -0
  109. data/lib/shamu/services/active_record.rb +58 -0
  110. data/lib/shamu/services/active_record_crud.rb +378 -0
  111. data/lib/shamu/services/error.rb +24 -0
  112. data/lib/shamu/services/lazy_association.rb +31 -0
  113. data/lib/shamu/services/lazy_transform.rb +97 -0
  114. data/lib/shamu/services/request.rb +122 -0
  115. data/lib/shamu/services/request_support.rb +124 -0
  116. data/lib/shamu/services/result.rb +75 -0
  117. data/lib/shamu/services/service.rb +355 -0
  118. data/lib/shamu/services.rb +12 -0
  119. data/lib/shamu/sessions/README.md +2 -0
  120. data/lib/shamu/sessions/cookie_store.rb +79 -0
  121. data/lib/shamu/sessions/session_store.rb +42 -0
  122. data/lib/shamu/sessions.rb +8 -0
  123. data/lib/shamu/to_bool_extension.rb +57 -0
  124. data/lib/shamu/to_model_id_extension.rb +50 -0
  125. data/lib/shamu/version.rb +10 -4
  126. data/lib/shamu.rb +18 -6
  127. data/shamu.gemspec +21 -10
  128. data/spec/internal/README.md +4 -0
  129. data/spec/internal/config/database.yml +3 -0
  130. data/spec/internal/config/routes.rb +3 -0
  131. data/spec/internal/db/schema.rb +3 -0
  132. data/spec/internal/log/.gitignore +1 -0
  133. data/spec/internal/public/favicon.ico +0 -0
  134. data/spec/lib/shamu/active_record_support.rb +32 -0
  135. data/spec/lib/shamu/attributes/assignment_spec.rb +129 -0
  136. data/spec/lib/shamu/attributes/equality_spec.rb +63 -0
  137. data/spec/lib/shamu/attributes/fluid_assignment_spec.rb +31 -0
  138. data/spec/lib/shamu/attributes/validation_spec.rb +53 -0
  139. data/spec/lib/shamu/attributes_spec.rb +331 -0
  140. data/spec/lib/shamu/auditing/logging_auditing_service_spec.rb +18 -0
  141. data/spec/lib/shamu/auditing/support_spec.rb +41 -0
  142. data/spec/lib/shamu/entities/active_record_soft_destroy_spec.rb +82 -0
  143. data/spec/lib/shamu/entities/active_record_spec.rb +66 -0
  144. data/spec/lib/shamu/entities/entity_path_spec.rb +40 -0
  145. data/spec/lib/shamu/entities/entity_spec.rb +56 -0
  146. data/spec/lib/shamu/entities/identity_cache_spec.rb +69 -0
  147. data/spec/lib/shamu/entities/list_scope/dates_spec.rb +47 -0
  148. data/spec/lib/shamu/entities/list_scope/paging_spec.rb +41 -0
  149. data/spec/lib/shamu/entities/list_scope/scoped_paging_spec.rb +40 -0
  150. data/spec/lib/shamu/entities/list_scope/sorting_spec.rb +59 -0
  151. data/spec/lib/shamu/entities/list_scope_spec.rb +127 -0
  152. data/spec/lib/shamu/entities/list_spec.rb +60 -0
  153. data/spec/lib/shamu/entities/null_entity_spec.rb +94 -0
  154. data/spec/lib/shamu/events/active_record/migration_spec.rb +11 -0
  155. data/spec/lib/shamu/events/active_record/service_spec.rb +139 -0
  156. data/spec/lib/shamu/events/events_service_spec.rb +57 -0
  157. data/spec/lib/shamu/events/in_memory/async_service_spec.rb +37 -0
  158. data/spec/lib/shamu/events/in_memory/service_spec.rb +36 -0
  159. data/spec/lib/shamu/events/message_spec.rb +7 -0
  160. data/spec/lib/shamu/events/support_spec.rb +44 -0
  161. data/spec/lib/shamu/features/conditions/condition_spec.rb +8 -0
  162. data/spec/lib/shamu/features/conditions/env_spec.rb +29 -0
  163. data/spec/lib/shamu/features/conditions/hosts_spec.rb +21 -0
  164. data/spec/lib/shamu/features/conditions/matching_spec.rb +23 -0
  165. data/spec/lib/shamu/features/conditions/percentage_spec.rb +71 -0
  166. data/spec/lib/shamu/features/conditions/proc_spec.rb +28 -0
  167. data/spec/lib/shamu/features/env_store_spec.rb +48 -0
  168. data/spec/lib/shamu/features/features.yml +34 -0
  169. data/spec/lib/shamu/features/features_service_spec.rb +109 -0
  170. data/spec/lib/shamu/features/secondary.yml +5 -0
  171. data/spec/lib/shamu/features/selector_spec.rb +17 -0
  172. data/spec/lib/shamu/features/support_spec.rb +45 -0
  173. data/spec/lib/shamu/features/toggle_codec_spec.rb +28 -0
  174. data/spec/lib/shamu/features/toggle_spec.rb +42 -0
  175. data/spec/lib/shamu/rack/cookies_middleware_spec.rb +33 -0
  176. data/spec/lib/shamu/rack/cookies_spec.rb +43 -0
  177. data/spec/lib/shamu/rack/query_params_middleware_spec.rb +33 -0
  178. data/spec/lib/shamu/rack/query_params_spec.rb +23 -0
  179. data/spec/lib/shamu/rails/controller_spec.rb +74 -0
  180. data/spec/lib/shamu/rails/entity_spec.rb +150 -0
  181. data/spec/lib/shamu/rails/features.yml +13 -0
  182. data/spec/lib/shamu/rails/features_spec.rb +45 -0
  183. data/spec/lib/shamu/security/active_record_policy_spec.rb +38 -0
  184. data/spec/lib/shamu/security/hashed_value_spec.rb +41 -0
  185. data/spec/lib/shamu/security/policy_refinement_spec.rb +61 -0
  186. data/spec/lib/shamu/security/policy_rule_spec.rb +60 -0
  187. data/spec/lib/shamu/security/policy_spec.rb +158 -0
  188. data/spec/lib/shamu/security/roles_spec.rb +46 -0
  189. data/spec/lib/shamu/services/active_record_crud_spec.rb +460 -0
  190. data/spec/lib/shamu/services/active_record_spec.rb +92 -0
  191. data/spec/lib/shamu/services/lazy_association_spec.rb +31 -0
  192. data/spec/lib/shamu/services/lazy_transform_spec.rb +96 -0
  193. data/spec/lib/shamu/services/request_spec.rb +58 -0
  194. data/spec/lib/shamu/services/request_support_spec.rb +129 -0
  195. data/spec/lib/shamu/services/result_spec.rb +37 -0
  196. data/spec/lib/shamu/services/service_spec.rb +307 -0
  197. data/spec/lib/shamu/sessions/cookie_store_spec.rb +44 -0
  198. data/spec/lib/shamu/to_bool_extension_spec.rb +67 -0
  199. data/spec/lib/shamu/to_model_id_extension_spec.rb +54 -0
  200. data/spec/rails_helper.rb +13 -0
  201. data/spec/spec_helper.rb +17 -12
  202. data/spec/support/active_record.rb +17 -0
  203. data/spec/support/database.rb +14 -0
  204. data/spec/support/logger.rb +0 -0
  205. metadata +383 -9
  206. data/spec/lib/shamu_spec.rb +0 -5
  207. /data/{spec/internal/log/test.log → lib/shamu/attributes/README.md} +0 -0
@@ -0,0 +1,79 @@
1
+ require "shamu/rack/cookies"
2
+
3
+ module Shamu
4
+ module Sessions
5
+
6
+ # Track persistent values in a cookie stored on the user's machine. Values
7
+ # kept in the CookieStore are not encrypted but they are protected by HMAC
8
+ # hashing to ensure that they have not been modified.
9
+ #
10
+ # To support cookies, in your service it must be instantiated as part of a
11
+ # Rack request and you must add {Shamu::Rack::CookieMiddleware} to your app.
12
+ #
13
+ # ## Adding support to a Rails app
14
+ #
15
+ # ```
16
+ # # application.rb
17
+ #
18
+ # config.middleware.use Shamu::Rack::CookiesMiddleware
19
+ # ```
20
+ #
21
+ # ## In a standalone Rack app
22
+ #
23
+ # ```
24
+ # require "shamu/rack"
25
+ #
26
+ # app = Rack::Builder.new do
27
+ # use Shamu::Rack::CookiesMiddleware
28
+ #
29
+ # end
30
+ #
31
+ # run app
32
+ # ```
33
+ class CookieStore < Services::Service
34
+ include Sessions::SessionStore
35
+ include Shamu::Security::HashedValue
36
+
37
+ # How long cookies should be kept.
38
+ TTL = ( 30 * 24 * 60 * 60 ).freeze
39
+
40
+ # ============================================================================
41
+ # @!group Dependencies
42
+ #
43
+
44
+ # @!attribute
45
+ # @return [Shamu::Rack::Cookies]
46
+ attr_dependency :cookies, Shamu::Rack::Cookies
47
+
48
+ #
49
+ # @!endgroup Dependencies
50
+ #
51
+
52
+ # @param [String] private_key the private key used to verify cookie
53
+ # values.
54
+ initialize do |private_key = Shamu::Security.private_key, **|
55
+ @private_key = private_key
56
+ end
57
+
58
+ # (see SessionStore#fetch)
59
+ def fetch( key, &block )
60
+ if cookies.key?( key )
61
+ verify_hash( cookies.get( key ) )
62
+ elsif block_given?
63
+ yield
64
+ end
65
+ end
66
+
67
+ # (see SessionStore#set)
68
+ def set( key, value )
69
+ cookies.set( key, value: hash_value( value ), secure: true, max_age: TTL )
70
+ end
71
+
72
+ # (see SessionStore#delete)
73
+ def delete( key )
74
+ cookies.delete( key )
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ module Shamu
2
+ module Sessions
3
+
4
+ # Exposes a persistent key/value store to track state across multiple
5
+ # requests.
6
+ module SessionStore
7
+
8
+ def self.create( scorpion, *args, **dependencies, &block )
9
+ return scorpion.fetch Shamu::Sessions::CookieStore, *args, **dependencies, &block if defined? Rack
10
+
11
+ fail "Configure a Shamu::Sessions::SessionStore in your scorpion setup."
12
+ end
13
+
14
+ # Fetch the value with the given key from the store. If they key does not
15
+ # yet exist, yields to the block and caches the result.
16
+ #
17
+ # @param [String] key
18
+ # @yieldreturn The calculated value of the key.
19
+ # @return [Object]
20
+ def fetch( key, &block )
21
+ fail NotImplementedError
22
+ end
23
+
24
+ # Save a named value in the session.
25
+ #
26
+ # @param [String] key
27
+ # @param [Object] value. Must be a primitive (String, Number, Hash, Array).
28
+ # @return [value]
29
+ def set( key, value )
30
+ fail NotImplementedError
31
+ end
32
+
33
+ # Remove the value with the given key.
34
+ # @param [String] key
35
+ # @return [nil]
36
+ def delete( key )
37
+ fail NotImplementedError
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,8 @@
1
+ module Shamu
2
+
3
+ # {include:file:lib/shamu/sessions/README.md}
4
+ module Sessions
5
+ require "shamu/sessions/session_store"
6
+ require "shamu/sessions/cookie_store"
7
+ end
8
+ end
@@ -0,0 +1,57 @@
1
+ module Shamu
2
+
3
+ # Adds `to_bool` to strings, numbers, booleans and nil class to provide a
4
+ # consistent means of parsing values to a Boolean type.
5
+ module ToBoolExtension
6
+
7
+ # Extend common classes to add `to_model_id` method.
8
+ def self.extend!
9
+ String.include Strings
10
+ Integer.include Integers
11
+ TrueClass.include Boolean
12
+ FalseClass.include Boolean
13
+ NilClass.include Nil
14
+ end
15
+
16
+ # Add `to_model_id` to String types.
17
+ module Strings
18
+ def to_bool( default = false )
19
+ case self
20
+ when "1", /\At(rue)?\z/i, /\Ay(es)?\z/i then true
21
+ when "0", "", /\Af(alse)?\z/i, /\An(o)?\z/i then false
22
+ else default
23
+ end
24
+ end
25
+ end
26
+
27
+ # Add `to_model_id` to Integer types.
28
+ module Integers
29
+ def to_bool( default = false )
30
+ case self
31
+ when 1 then true
32
+ when 0 then false
33
+ else default
34
+ end
35
+ end
36
+ end
37
+
38
+ # Add `to_model_id` to Boolean types.
39
+ module Boolean
40
+ def to_bool( default = self )
41
+ self
42
+ end
43
+ end
44
+
45
+ # Add `to_model_id` to nil.
46
+ module Nil
47
+ def to_bool( default = self )
48
+ default
49
+ end
50
+ end
51
+
52
+
53
+ end
54
+ end
55
+
56
+
57
+ Shamu::ToBoolExtension.extend!
@@ -0,0 +1,50 @@
1
+ require "active_model"
2
+
3
+ module Shamu
4
+
5
+ # Adds `to_model_id` to several classes that are often used to look up
6
+ # models by id.
7
+ module ToModelIdExtension
8
+
9
+ # Extend common classes to add `to_model_id` method.
10
+ def self.extend!
11
+ Integer.include Integers
12
+ String.include Strings
13
+ Array.include Enumerables
14
+
15
+ ActiveRecord::Base.include Models if defined? ActiveRecord::Base
16
+ end
17
+
18
+ # Add `to_model_id` to String types.
19
+ module Strings
20
+ NUMERIC_PATTERN = /\A\s*[0-9]+\z/
21
+
22
+ def to_model_id
23
+ self =~ NUMERIC_PATTERN ? to_i : nil
24
+ end
25
+ end
26
+
27
+ # Add `to_model_id` to Integer types.
28
+ module Integers
29
+ def to_model_id
30
+ self
31
+ end
32
+ end
33
+
34
+ # Add `to_model_id` to Enumerable types.
35
+ module Enumerables
36
+ def to_model_id
37
+ map( &:to_model_id )
38
+ end
39
+ end
40
+
41
+ # Add `to_model_id` to ActiveModel types.
42
+ module Models
43
+ def to_model_id
44
+ id
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Shamu::ToModelIdExtension.extend!
data/lib/shamu/version.rb CHANGED
@@ -1,5 +1,11 @@
1
- module Scorpion
2
- VERSION_NUMBER = "0.0.1"
3
- VERSION_SUFFIX = ""
4
- VERSION = "#{VERSION_NUMBER}#{VERSION_SUFFIX}"
1
+ # frozen_string_literal: true
2
+ module Shamu
3
+ # The primary version number
4
+ VERSION_NUMBER = "0.0.2".freeze
5
+
6
+ # Version suffix such as 'beta' or 'alpha'
7
+ VERSION_SUFFIX = "".freeze
8
+
9
+ # Published version number
10
+ VERSION = "#{ VERSION_NUMBER }#{ VERSION_SUFFIX }".freeze
5
11
  end
data/lib/shamu.rb CHANGED
@@ -1,10 +1,22 @@
1
- require 'i18n'
1
+ require "i18n"
2
2
 
3
- I18n.load_path += Dir[ File.expand_path( '../shamu/locale/*.yml', __FILE__ ) ]
3
+ I18n.load_path += Dir[ File.expand_path( "../shamu/locale/*.yml", __FILE__ ) ]
4
4
 
5
- module Scorpion
6
-
7
- require 'shamu/version'
8
- require 'shamu/error'
5
+ # {include:file:README.md}
6
+ module Shamu
7
+ require "shamu/version"
8
+ require "shamu/error"
9
+ require "shamu/attributes"
10
+ require "shamu/entities"
11
+ require "shamu/logger"
12
+ require "shamu/services"
13
+ require "shamu/security"
14
+ require "shamu/auditing"
15
+ require "shamu/events"
16
+ require "shamu/sessions"
17
+ require "shamu/features"
18
+ require "shamu/to_model_id_extension"
19
+ require "shamu/to_bool_extension"
9
20
 
21
+ require "shamu/rails" if defined? Rails
10
22
  end
data/shamu.gemspec CHANGED
@@ -1,14 +1,14 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path( "../lib", __FILE__ )
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'shamu/version'
4
+ require "shamu/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "shamu"
8
- spec.version = "#{Scorpion::VERSION}"
9
- spec.authors = ["Paul Alexander"]
10
- spec.email = ["me@phallguy.com"]
11
- spec.summary = %q{Have a whale of a good time adding Service Oriented Architecture to your ruby projects.}
8
+ spec.version = Shamu::VERSION
9
+ spec.authors = [ "Paul Alexander" ]
10
+ spec.email = [ "me@phallguy.com" ]
11
+ spec.summary = "Have a whale of a good time adding Service Oriented Architecture to your ruby projects."
12
12
  spec.homepage = "https://github.com/phallguy/shamu"
13
13
  spec.license = "MIT"
14
14
 
@@ -17,10 +17,21 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.required_ruby_version = '>= 2.3.0'
20
+ spec.required_ruby_version = ">= 2.3.0"
21
+
22
+
23
+ spec.add_dependency "activemodel", "~> 4.2"
24
+ spec.add_dependency "activesupport", "~> 4.2"
25
+ spec.add_dependency "scorpion-ioc", "~> 0.5.16"
26
+ spec.add_dependency "multi_json", "~> 1.11.2"
27
+ spec.add_dependency "rack", "~> 1"
28
+ spec.add_dependency "listen", "~> 3"
29
+ spec.add_dependency "crc32", "~> 1"
30
+
21
31
 
22
32
  spec.add_development_dependency "bundler", "~> 1.6"
23
- spec.add_development_dependency "rake", '~> 10'
24
- spec.add_development_dependency "rspec", '~> 3.00'
25
- spec.add_development_dependency "rspec-rails", '~> 3.00'
33
+ spec.add_development_dependency "i18n", "~> 0.7"
34
+ spec.add_development_dependency "rake", "~> 10"
35
+ spec.add_development_dependency "rspec", "~> 3.00"
36
+ spec.add_development_dependency "combustion", "~> 0.5"
26
37
  end
@@ -0,0 +1,4 @@
1
+ This is a dummy rails app used by the
2
+ [combustion](https://github.com/pat/combustion) gem to support rails
3
+ integration testing.
4
+
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/combustion_test.sqlite
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ #
3
+ end
@@ -0,0 +1,3 @@
1
+ ActiveRecord::Schema.define do
2
+ #
3
+ end
@@ -0,0 +1 @@
1
+ *.log
File without changes
@@ -0,0 +1,32 @@
1
+ require "active_record"
2
+ require "shamu/entities/active_record"
3
+
4
+ module ActiveRecordSpec
5
+ class Favorite < ::ActiveRecord::Base
6
+ self.table_name = "favorites"
7
+ extend Shamu::Entities::ActiveRecord
8
+ include Shamu::Entities::ActiveRecordSoftDestroy
9
+
10
+ scope :by_name, ->( name ) { where( name: name ) }
11
+ scope :by_label, ->( label ) { where( label: label ) }
12
+ end
13
+
14
+ class FavoriteMigration < ::ActiveRecord::Migration
15
+ def self.up
16
+ create_table :favorites do |t|
17
+ t.string :name
18
+ t.string :label
19
+
20
+ t.datetime :destroyed_at
21
+ end
22
+ end
23
+
24
+ def self.down
25
+ drop_table :favorites
26
+ end
27
+ end
28
+
29
+ class FavoriteScope < Shamu::Entities::ListScope
30
+ attribute :name
31
+ end
32
+ end
@@ -0,0 +1,129 @@
1
+ require "spec_helper"
2
+ require "shamu/attributes"
3
+
4
+ describe Shamu::Attributes::Assignment do
5
+ let( :base_klass ) do
6
+ Class.new do
7
+ include Shamu::Attributes
8
+ include Shamu::Attributes::Assignment
9
+
10
+ attribute :value
11
+ end
12
+ end
13
+
14
+ describe "arrays" do
15
+ let( :klass ) do
16
+ Class.new( base_klass ) do
17
+ attribute :tags, coerce: :to_s, array: true
18
+ end
19
+ end
20
+
21
+ it "converts a single value to an array" do
22
+ instance = klass.new( tags: "apple" )
23
+ expect( instance.tags ).to eq ["apple"]
24
+ end
25
+
26
+ it "coerces each item in the array" do
27
+ instance = klass.new( tags: [:orange] )
28
+ expect( instance.tags ).to eq ["orange"]
29
+ end
30
+ end
31
+
32
+ it "updates instance variable" do
33
+ instance = base_klass.new
34
+ instance.value = "abc"
35
+
36
+ expect( instance.instance_variable_get( :@value ) ).to eq "abc"
37
+ end
38
+
39
+ it "calls assignment methods on assign_attributes" do
40
+ klass = Class.new( base_klass ) do
41
+ attribute :attr
42
+ end
43
+
44
+ expect_any_instance_of( klass ).to receive( :assign_attr )
45
+
46
+ klass.new( attr: 1 )
47
+ end
48
+
49
+ it "creates aliased assignment" do
50
+ klass = Class.new do
51
+ include Shamu::Attributes
52
+ include Shamu::Attributes::Assignment
53
+
54
+ attribute :q, as: :query
55
+ end
56
+
57
+ instance = klass.new
58
+ instance.query = "ABC"
59
+ expect( instance.q ).to eq "ABC"
60
+ end
61
+
62
+ describe "coercion" do
63
+ it "coerces using given method name" do
64
+ klass = Class.new( base_klass ) do
65
+ attribute :count, coerce: :to_i
66
+ end
67
+
68
+ value = double
69
+ expect( value ).to receive( :to_i ).and_return( 5 )
70
+
71
+ instance = klass.new
72
+ instance.count = value
73
+
74
+ expect( instance.count ).to eq 5
75
+ end
76
+
77
+ it "coerces using given method proc" do
78
+ klass = Class.new( base_klass ) do
79
+ attribute :label, coerce: ->(_) { "coerced" }
80
+ end
81
+
82
+ instance = klass.new( label: "original" )
83
+ expect( instance.label ).to eq "coerced"
84
+ end
85
+
86
+ describe "smart" do
87
+ let( :klass ) do
88
+ Class.new( base_klass ) do
89
+ attribute :updated_at
90
+ attribute :expire_on
91
+
92
+ attribute :user_id
93
+ attribute :tag_ids
94
+ end
95
+ end
96
+ let( :instance ) { klass.new }
97
+
98
+ it "coerces nnn_at to timestamps" do
99
+ value = double
100
+ expect( value ).to receive( :to_datetime )
101
+
102
+ instance.updated_at = value
103
+ end
104
+
105
+ it "coerces nnn_on to timestamps" do
106
+ value = double
107
+ expect( value ).to receive( :to_datetime )
108
+
109
+ instance.expire_on = value
110
+ end
111
+
112
+ it "coerces nnn_id to an Integer" do
113
+ value = double
114
+ expect( value ).to receive( :to_i )
115
+
116
+ instance.user_id = value
117
+ end
118
+
119
+ it "coerces nnn_ids to an array of Integers" do
120
+ value = double
121
+ expect( value ).to receive( :to_i )
122
+
123
+ instance.tag_ids = value
124
+ end
125
+
126
+ end
127
+ end
128
+
129
+ end
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+ require "shamu/attributes"
3
+
4
+ describe Shamu::Attributes::Equality do
5
+ let( :klass ) do
6
+ Class.new do
7
+ include Shamu::Attributes
8
+ include Shamu::Attributes::Equality
9
+
10
+ attribute :name
11
+ attribute :random, ignore_inequality: true
12
+ end
13
+ end
14
+
15
+ let( :value ) { klass.new( name: "same" ) }
16
+ let( :same ) { klass.new( name: "same" ) }
17
+ let( :different ) { klass.new( name: "different" ) }
18
+
19
+
20
+ it "is eql? for the same attributes" do
21
+ expect( value ).to eq same
22
+ end
23
+
24
+ it "isn't eql? for different attributes" do
25
+ expect( value ).not_to eq different
26
+ end
27
+
28
+ it "isn't eql? for different types with the same attributes" do
29
+ other_klass = Class.new do
30
+ include Shamu::Attributes
31
+ include Shamu::Attributes::Equality
32
+
33
+ attribute :name
34
+ end
35
+
36
+ other = other_klass.new( name: value.name )
37
+
38
+ expect( value ).not_to eq other
39
+ end
40
+
41
+ it "is eql? for derived types with same attributes" do
42
+ derived_klass = Class.new( klass )
43
+ derived = derived_klass.new( name: value.name )
44
+
45
+ expect( value ).to eq derived
46
+ expect( derived ).to eq value
47
+ end
48
+
49
+ it "has the same hash for the same attributes" do
50
+ expect( value.hash ).to eq same.hash
51
+ end
52
+
53
+ it "has a different hash for different attributes" do
54
+ expect( value.hash ).not_to eq different.hash
55
+ end
56
+
57
+ it "ignores excluded attributes" do
58
+ v1 = klass.new( name: "same", random: 123 )
59
+ v2 = klass.new( name: "same", random: 456 )
60
+
61
+ expect( v1 ).to eq v2
62
+ end
63
+ end
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+ require "shamu/attributes"
3
+
4
+ describe Shamu::Attributes::FluidAssignment do
5
+ let( :klass ) do
6
+ Class.new do
7
+ include Shamu::Attributes
8
+ include Shamu::Attributes::Assignment
9
+ include Shamu::Attributes::FluidAssignment
10
+
11
+ attribute :value
12
+ end
13
+ end
14
+
15
+ it "returns the current value with no arguments" do
16
+ instance = klass.new( value: "one" )
17
+
18
+ expect( instance.value ).to eq "one"
19
+ end
20
+
21
+ it "assigns the value when arguments present" do
22
+ instance = klass.new
23
+ instance.value( "two" )
24
+ end
25
+
26
+ it "return self on assignment" do
27
+ instance = klass.new
28
+ expect( instance.value( "two" ) ).to be instance
29
+ end
30
+
31
+ end
@@ -0,0 +1,53 @@
1
+ require "spec_helper"
2
+ require "shamu/attributes"
3
+
4
+ describe Shamu::Attributes::Validation do
5
+ let( :klass ) do
6
+ Class.new do
7
+ include Shamu::Attributes
8
+ include Shamu::Attributes::Assignment
9
+ include Shamu::Attributes::Validation
10
+
11
+ attribute :name, presence: true
12
+
13
+ def self.name
14
+ "Example"
15
+ end
16
+ end
17
+ end
18
+
19
+ it "forwards unused options to .validates method" do
20
+ TestClass = Class.new do
21
+ include Shamu::Attributes
22
+ include Shamu::Attributes::Validation
23
+ end
24
+
25
+ expect( TestClass ).to receive( :validates ).with( :name, presence: true )
26
+ class TestClass
27
+ attribute :name, on: :user, presence: true
28
+ end
29
+ end
30
+
31
+ it "doesn't clear errors on call to valid?" do
32
+ instance = klass.new( {} )
33
+ instance.validate
34
+ expect( instance ).not_to be_valid
35
+
36
+ instance.name = "Something"
37
+ expect( instance ).not_to be_valid
38
+ end
39
+
40
+ it "validates methods on validate" do
41
+ instance = klass.new( {} )
42
+ instance.validate
43
+
44
+ expect( instance.errors ).to have_key :name
45
+ end
46
+
47
+ it "validates on first call to valid?" do
48
+ instance = klass.new( {} )
49
+ expect( instance ).to receive( :validate ).once.and_call_original
50
+ instance.valid?
51
+ instance.valid?
52
+ end
53
+ end