riveter 0.0.1

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 (174) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +17 -0
  7. data/Gemfile +4 -0
  8. data/Gemfile.lock +147 -0
  9. data/LICENSE.txt +23 -0
  10. data/README.md +77 -0
  11. data/Rakefile +7 -0
  12. data/app/helpers/riveter/command_form_helper.rb +15 -0
  13. data/app/helpers/riveter/enquiry_form_helper.rb +16 -0
  14. data/app/helpers/riveter/query_filter_form_helper.rb +16 -0
  15. data/config/locales/forms.en.yml +25 -0
  16. data/config/locales/validators.en.yml +26 -0
  17. data/init.rb +25 -0
  18. data/lib/generators/erb/TODO +1 -0
  19. data/lib/generators/haml/command_controller/USAGE +0 -0
  20. data/lib/generators/haml/command_controller/command_controller_generator.rb +56 -0
  21. data/lib/generators/haml/command_controller/templates/new.html.haml +26 -0
  22. data/lib/generators/haml/enquiry_controller/USAGE +0 -0
  23. data/lib/generators/haml/enquiry_controller/enquiry_controller_generator.rb +56 -0
  24. data/lib/generators/haml/enquiry_controller/templates/index.html.haml +57 -0
  25. data/lib/generators/riveter/command/USAGE +0 -0
  26. data/lib/generators/riveter/command/command_generator.rb +55 -0
  27. data/lib/generators/riveter/command/templates/command.rb +40 -0
  28. data/lib/generators/riveter/command/templates/commands.en.yml +57 -0
  29. data/lib/generators/riveter/command/templates/module.rb +4 -0
  30. data/lib/generators/riveter/command_controller/USAGE +0 -0
  31. data/lib/generators/riveter/command_controller/command_controller_generator.rb +40 -0
  32. data/lib/generators/riveter/command_controller/templates/command_controller.rb +18 -0
  33. data/lib/generators/riveter/command_controller/templates/module.rb +4 -0
  34. data/lib/generators/riveter/enquiry/USAGE +0 -0
  35. data/lib/generators/riveter/enquiry/enquiry_generator.rb +29 -0
  36. data/lib/generators/riveter/enquiry/templates/enquiry.rb +11 -0
  37. data/lib/generators/riveter/enquiry/templates/module.rb +4 -0
  38. data/lib/generators/riveter/enquiry_controller/USAGE +0 -0
  39. data/lib/generators/riveter/enquiry_controller/enquiry_controller_generator.rb +34 -0
  40. data/lib/generators/riveter/enquiry_controller/templates/enquiry_controller.rb +9 -0
  41. data/lib/generators/riveter/enquiry_controller/templates/module.rb +4 -0
  42. data/lib/generators/riveter/enum/USAGE +41 -0
  43. data/lib/generators/riveter/enum/enum_generator.rb +51 -0
  44. data/lib/generators/riveter/enum/templates/enum.rb +17 -0
  45. data/lib/generators/riveter/enum/templates/enums.en.yml +35 -0
  46. data/lib/generators/riveter/enum/templates/module.rb +4 -0
  47. data/lib/generators/riveter/install/USAGE +0 -0
  48. data/lib/generators/riveter/install/install_generator.rb +14 -0
  49. data/lib/generators/riveter/presenter/USAGE +0 -0
  50. data/lib/generators/riveter/presenter/presenter_generator.rb +20 -0
  51. data/lib/generators/riveter/presenter/templates/module.rb +4 -0
  52. data/lib/generators/riveter/presenter/templates/presenter.rb +7 -0
  53. data/lib/generators/riveter/query/USAGE +22 -0
  54. data/lib/generators/riveter/query/query_generator.rb +20 -0
  55. data/lib/generators/riveter/query/templates/module.rb +4 -0
  56. data/lib/generators/riveter/query/templates/query.rb +31 -0
  57. data/lib/generators/riveter/query_filter/USAGE +0 -0
  58. data/lib/generators/riveter/query_filter/query_filter_generator.rb +52 -0
  59. data/lib/generators/riveter/query_filter/templates/module.rb +4 -0
  60. data/lib/generators/riveter/query_filter/templates/query_filter.rb +40 -0
  61. data/lib/generators/riveter/query_filter/templates/query_filters.en.yml +49 -0
  62. data/lib/generators/riveter/service/USAGE +0 -0
  63. data/lib/generators/riveter/service/service_generator.rb +20 -0
  64. data/lib/generators/riveter/service/templates/module.rb +4 -0
  65. data/lib/generators/riveter/service/templates/service.rb +12 -0
  66. data/lib/generators/riveter/worker/USAGE +0 -0
  67. data/lib/generators/riveter/worker/templates/module.rb +4 -0
  68. data/lib/generators/riveter/worker/templates/worker.rb +7 -0
  69. data/lib/generators/riveter/worker/worker_generator.rb +20 -0
  70. data/lib/generators/rspec/command/USAGE +0 -0
  71. data/lib/generators/rspec/command/command_generator.rb +11 -0
  72. data/lib/generators/rspec/command/templates/command_spec.rb +8 -0
  73. data/lib/generators/rspec/command_controller/USAGE +0 -0
  74. data/lib/generators/rspec/command_controller/command_controller_generator.rb +21 -0
  75. data/lib/generators/rspec/command_controller/templates/command_controller_spec.rb +70 -0
  76. data/lib/generators/rspec/enquiry/USAGE +0 -0
  77. data/lib/generators/rspec/enquiry/enquiry_generator.rb +11 -0
  78. data/lib/generators/rspec/enquiry/templates/enquiry_spec.rb +69 -0
  79. data/lib/generators/rspec/enquiry_controller/USAGE +0 -0
  80. data/lib/generators/rspec/enquiry_controller/enquiry_controller_generator.rb +16 -0
  81. data/lib/generators/rspec/enquiry_controller/templates/enquiry_controller_spec.rb +32 -0
  82. data/lib/generators/rspec/enum/USAGE +0 -0
  83. data/lib/generators/rspec/enum/enum_generator.rb +11 -0
  84. data/lib/generators/rspec/enum/templates/enum_spec.rb +8 -0
  85. data/lib/generators/rspec/presenter/USAGE +0 -0
  86. data/lib/generators/rspec/presenter/presenter_generator.rb +11 -0
  87. data/lib/generators/rspec/presenter/templates/presenter_spec.rb +8 -0
  88. data/lib/generators/rspec/query/USAGE +0 -0
  89. data/lib/generators/rspec/query/query_generator.rb +11 -0
  90. data/lib/generators/rspec/query/templates/query_spec.rb +41 -0
  91. data/lib/generators/rspec/query_filter/USAGE +0 -0
  92. data/lib/generators/rspec/query_filter/query_filter_generator.rb +11 -0
  93. data/lib/generators/rspec/query_filter/templates/query_filter_spec.rb +8 -0
  94. data/lib/generators/rspec/service/USAGE +0 -0
  95. data/lib/generators/rspec/service/service_generator.rb +11 -0
  96. data/lib/generators/rspec/service/templates/service_spec.rb +8 -0
  97. data/lib/generators/rspec/worker/USAGE +0 -0
  98. data/lib/generators/rspec/worker/templates/worker_spec.rb +8 -0
  99. data/lib/generators/rspec/worker/worker_generator.rb +11 -0
  100. data/lib/generators/test_unit/TODO +1 -0
  101. data/lib/riveter/associated_type_registry.rb +63 -0
  102. data/lib/riveter/attribute_default_values.rb +67 -0
  103. data/lib/riveter/attributes.rb +443 -0
  104. data/lib/riveter/booleaness_validator.rb +20 -0
  105. data/lib/riveter/command.rb +59 -0
  106. data/lib/riveter/command_controller.rb +93 -0
  107. data/lib/riveter/command_routes.rb +73 -0
  108. data/lib/riveter/core_extensions.rb +246 -0
  109. data/lib/riveter/email_validator.rb +20 -0
  110. data/lib/riveter/enquiry.rb +137 -0
  111. data/lib/riveter/enquiry_controller.rb +80 -0
  112. data/lib/riveter/enquiry_routes.rb +69 -0
  113. data/lib/riveter/enumerated.rb +107 -0
  114. data/lib/riveter/errors.rb +11 -0
  115. data/lib/riveter/form_builder_extensions.rb +21 -0
  116. data/lib/riveter/hash_with_dependency.rb +12 -0
  117. data/lib/riveter/presenter.rb +73 -0
  118. data/lib/riveter/query.rb +45 -0
  119. data/lib/riveter/query_filter.rb +22 -0
  120. data/lib/riveter/rails/engine.rb +6 -0
  121. data/lib/riveter/rails/railtie.rb +50 -0
  122. data/lib/riveter/service.rb +45 -0
  123. data/lib/riveter/spec_helper.rb +55 -0
  124. data/lib/riveter/tasks/.keep +0 -0
  125. data/lib/riveter/version.rb +3 -0
  126. data/lib/riveter/worker.rb +20 -0
  127. data/lib/riveter.rb +47 -0
  128. data/riveter.gemspec +40 -0
  129. data/spec/examples/attribute_examples.rb +57 -0
  130. data/spec/generators/haml/command_controller/command_controller_generator_spec.rb +34 -0
  131. data/spec/generators/haml/enquiry_controller/enquiry_controller_generator_spec.rb +34 -0
  132. data/spec/generators/riveter/command/command_generator_spec.rb +58 -0
  133. data/spec/generators/riveter/command_controller/command_controller_generator_spec.rb +0 -0
  134. data/spec/generators/riveter/enquiry/enquiry_generator_spec.rb +0 -0
  135. data/spec/generators/riveter/query_filter/query_filter_generator_spec.rb +58 -0
  136. data/spec/riveter/associated_type_registry_spec.rb +158 -0
  137. data/spec/riveter/attribute_default_value_spec.rb +69 -0
  138. data/spec/riveter/attributes_spec.rb +228 -0
  139. data/spec/riveter/command_controller_spec.rb +116 -0
  140. data/spec/riveter/command_routes_spec.rb +116 -0
  141. data/spec/riveter/command_spec.rb +66 -0
  142. data/spec/riveter/core_extensions_spec.rb +209 -0
  143. data/spec/riveter/enquiry_controller_spec.rb +128 -0
  144. data/spec/riveter/enquiry_routes_spec.rb +101 -0
  145. data/spec/riveter/enquiry_spec.rb +299 -0
  146. data/spec/riveter/enumerated_spec.rb +47 -0
  147. data/spec/riveter/form_builder_extensions_spec.rb +28 -0
  148. data/spec/riveter/presenter_spec.rb +131 -0
  149. data/spec/riveter/query_filter_spec.rb +19 -0
  150. data/spec/riveter/query_spec.rb +72 -0
  151. data/spec/riveter/service_spec.rb +49 -0
  152. data/spec/riveter/spec_helper_spec.rb +21 -0
  153. data/spec/riveter/worker_spec.rb +11 -0
  154. data/spec/spec_helper.rb +54 -0
  155. data/spec/support/test_associated_class.rb +2 -0
  156. data/spec/support/test_class_with_attributes.rb +17 -0
  157. data/spec/support/test_command.rb +4 -0
  158. data/spec/support/test_command_controller.rb +12 -0
  159. data/spec/support/test_command_routes.rb +3 -0
  160. data/spec/support/test_enquiry.rb +7 -0
  161. data/spec/support/test_enquiry_controller.rb +12 -0
  162. data/spec/support/test_enquiry_routes.rb +3 -0
  163. data/spec/support/test_enum.rb +8 -0
  164. data/spec/support/test_form_builder.rb +3 -0
  165. data/spec/support/test_model.rb +2 -0
  166. data/spec/support/test_model_with_attribute_default_values.rb +29 -0
  167. data/spec/support/test_presenter.rb +2 -0
  168. data/spec/support/test_query.rb +5 -0
  169. data/spec/support/test_query_filter.rb +4 -0
  170. data/spec/support/test_service.rb +7 -0
  171. data/spec/support/validate_booleaness_of_matcher.rb +17 -0
  172. data/spec/support/validate_timeliness_of_matcher.rb +17 -0
  173. data/spec/support/validator_detector.rb +48 -0
  174. metadata +487 -0
@@ -0,0 +1,69 @@
1
+ require 'action_dispatch'
2
+
3
+ module Riveter
4
+ module EnquiryRoutes
5
+
6
+ #
7
+ # defines a route for the given enquiry
8
+ #
9
+ # by convention, the word "enquiry" is omitted
10
+ # from the name of the enquiry
11
+ #
12
+ # options include:
13
+ #
14
+ # :path overrides the path used.
15
+ # by default it is "<enquiry>_enquiry".
16
+ # E.g. for :active_portfolios the path is 'active_portfolios'
17
+ #
18
+ # :controller overrides the controller used.
19
+ # by default it is "<enquiry>_enquiry_controller"
20
+ #
21
+ # :as overrides the name of the route generated.
22
+ # by default it is "<enquiry>_enquiry"
23
+ #
24
+ # :action overrides the action name.
25
+ # by default is is ":index"
26
+ #
27
+ # E.g.
28
+ #
29
+ # enquiry :active_portfolios
30
+ #
31
+ # creates a route 'active_portfolios' named `active_portfolios_enquiry` to the
32
+ # `ActivePortfoliosEnquiryController` controller for the 'index' action
33
+ #
34
+ # enquiry :active_portfolios, :as => 'recent_portfolios'
35
+ #
36
+ # creates a route 'active_portfolios' named `recent_portfolios` to the
37
+ # `ActivePortfoliosEnquiryController` controller for the 'index' action
38
+ #
39
+ # enquiry :active_portfolios, :path => '/all_your_portfolios'
40
+ #
41
+ # creates a route 'all_your_portfolios' named `active_portfolios_enquiry` to the
42
+ # `ActivePortfoliosEnquiryController` controller for the 'index' action
43
+ #
44
+ # enquiry :active_portfolios, :controller => 'my_portfolios_controller'
45
+ #
46
+ # creates a route 'active_portfolios' named `active_portfolios_enquiry` to the
47
+ # `MyPortfoliosController` controller for the 'index' action
48
+ #
49
+ def enquiry(enquiry, options={})
50
+ raise ArgumentError, 'Expects a symbol for the enquiry.' unless enquiry.is_a?(Symbol)
51
+
52
+ path = options.delete(:path) || enquiry.to_s
53
+ action = options.delete(:action) || :index
54
+
55
+ options = {
56
+ :controller => :"#{enquiry}_enquiry",
57
+ :as => :"#{enquiry}_enquiry"
58
+ }.merge(options)
59
+
60
+ # define GET 'index' route
61
+ get path, options.merge(:action => action)
62
+
63
+ # define POST 'index' route
64
+ post path, options.merge(:action => action, :as => nil)
65
+ end
66
+ end
67
+ end
68
+
69
+ ActionDispatch::Routing::Mapper.send :include, Riveter::EnquiryRoutes
@@ -0,0 +1,107 @@
1
+ module Riveter
2
+ module Enumerated
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ const_names = self.constants(false)
8
+ const_values = const_names.collect {|name| self.const_get(name) }
9
+
10
+ # create hashes for decoding names and values
11
+ const_value_lookup ||= const_names.inject({}) {|list, name|
12
+ list[name] = self.const_get(name)
13
+ list
14
+ }.with_indifferent_access
15
+
16
+ const_name_lookup ||= const_names.inject({}) {|list, name|
17
+ list[self.const_get(name)] = name
18
+ list
19
+ }
20
+
21
+ # define helper methods
22
+
23
+ # returns an array of the constant names as symbols
24
+ define_singleton_method :names do
25
+ const_names
26
+ end
27
+
28
+ # returns an array of constant values
29
+ define_singleton_method :all do
30
+ const_values
31
+ end
32
+
33
+ # given a value, returns the name of the constant as a symbol
34
+ define_singleton_method :name_for do |value|
35
+ const_name_lookup[value]
36
+ end
37
+
38
+ # given a name, returns the value of the constant
39
+ # accepts a string or symbol for the constants name
40
+ define_singleton_method :value_for do |name|
41
+ const_value_lookup[name]
42
+ end
43
+
44
+ # returns the human name for the given constant name or value
45
+ # it uses the locale to lookup the translation
46
+ # and defaults to the capitalized name of the constant
47
+ define_singleton_method :human_name_for do |name_or_value, options={}|
48
+ const_name = name_or_value.is_a?(Symbol) ?
49
+ name_or_value :
50
+ value_for(name_or_value)
51
+
52
+ options = {
53
+ :scope => [:enums, self.to_s.underscore],
54
+ :default => const_name.to_s.titleize
55
+ }.merge!(options)
56
+
57
+ I18n.translate(const_name, options)
58
+ end
59
+
60
+ # defines the "All" constant
61
+ # which is array like object that can be used to loop
62
+ # over the set of constants and provides some helper methods
63
+ self.const_set :All, Enumeration.new(self, const_values)
64
+
65
+ # for use within form select inputs
66
+ define_singleton_method :collection do
67
+ self.const_get(:All).collect {|m| [m.human, m.value] }
68
+ end
69
+ end
70
+
71
+ module ClassMethods
72
+ def human(options={})
73
+ options = {
74
+ :scope => [:enums, self.to_s.underscore],
75
+ :default => self.name.titleize
76
+ }.merge!(options)
77
+
78
+ I18n.translate(:human, options)
79
+ end
80
+ end
81
+
82
+ class Enumeration < Array
83
+ attr_reader :enum
84
+
85
+ delegate :names, :values, :human, :to => :enum
86
+
87
+ def initialize(enum, values)
88
+ @enum = enum
89
+ super(values.collect {|value| Member.new(enum, value) })
90
+ end
91
+ end
92
+
93
+ class Member
94
+ attr_reader :name, :value
95
+
96
+ def initialize(enum, value)
97
+ @enum = enum
98
+ @name = enum.name_for(value)
99
+ @value = value
100
+ end
101
+
102
+ def human(options={})
103
+ @enum.human_name_for(name, options)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,11 @@
1
+ module Riveter
2
+ class UnknownAttributeError < NoMethodError
3
+ attr_reader :instance, :attribute
4
+
5
+ def initialize(instance, attribute)
6
+ @instance = instance
7
+ @attribute = attribute.to_s
8
+ super("unknown attribute: #{attribute}")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ require 'action_view'
2
+
3
+ module Riveter
4
+ module FormBuilderExtensions
5
+
6
+ def search
7
+ submit I18n.translate(:search, :scope => [:forms]), :name => :search
8
+ end
9
+
10
+ def reset
11
+ submit I18n.translate(:reset, :scope => [:forms]), :name => :reset
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ module ActionView::Helpers
18
+ class FormBuilder
19
+ include Riveter::FormBuilderExtensions
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ module Riveter
2
+ # See http://ruby-doc.org/stdlib-2.0/libdoc/tsort/rdoc/TSort.html for details
3
+ class HashWithDependency < Hash
4
+ include TSort
5
+
6
+ alias tsort_each_node each_key
7
+
8
+ def tsort_each_child(node, &block)
9
+ fetch(node).each(&block)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,73 @@
1
+ module Riveter
2
+ module Presenter
3
+ module Object
4
+ extend ActiveSupport::Concern
5
+
6
+ def to_presenter(klass)
7
+ raise ArgumentError, 'klass argument cannot be nil' if klass.nil?
8
+ raise ArgumentError, "#{klass} is not a valid presenter class" unless klass <= Presenter::Base
9
+ klass.new(self)
10
+ end
11
+ end
12
+
13
+ module Enumerator
14
+ extend ActiveSupport::Concern
15
+
16
+ def with_presenter(klass, &block)
17
+ raise ArgumentError, 'klass argument cannot be nil' if klass.nil?
18
+ raise ArgumentError, "#{klass} is not a valid presenter class" unless klass <= Presenter::Base
19
+ return to_enum(__method__, klass) unless block_given?
20
+
21
+ ##
22
+ # some magic!
23
+ # assuming that this method is used within the view
24
+ # the block which is supplied will be in the scope of the view
25
+ # therefore, getting it's binding and evaluating self will
26
+ # get us the view object
27
+ ##
28
+ view = block.binding.eval('self')
29
+ is_a_view = view.is_a?(ActionView::Base)
30
+
31
+ self.each do |item|
32
+ yield klass.new(item, (is_a_view ? view : nil))
33
+ end
34
+ end
35
+ end
36
+
37
+ class Base < SimpleDelegator
38
+ def item
39
+ __getobj__
40
+ end
41
+
42
+ def initialize(item, view=nil)
43
+ super(item)
44
+ @view = view
45
+ end
46
+
47
+ def method_missing(method, *args, &block)
48
+ return super if @view.nil?
49
+
50
+ if respond_to_without_view?(method)
51
+ super
52
+ elsif @view.respond_to?(method)
53
+ @view.send(method, *args, &block)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def respond_to_with_view?(method)
60
+ respond_to_without_view?(method) || (!@view.nil? && @view.respond_to?(method))
61
+ end
62
+ alias_method_chain :respond_to?, :view
63
+ end
64
+ end
65
+ end
66
+
67
+ class Object
68
+ include Riveter::Presenter::Object
69
+ end
70
+
71
+ class Enumerator
72
+ include Riveter::Presenter::Enumerator
73
+ end
@@ -0,0 +1,45 @@
1
+ module Riveter
2
+ module Query
3
+ extend ActiveSupport::Concern
4
+
5
+ attr_reader :query_filter
6
+ attr_reader :options
7
+ attr_reader :relation
8
+
9
+ def initialize(query_filter, options={})
10
+ @query_filter = query_filter
11
+ @options = options
12
+ @relation = build_relation(@query_filter)
13
+ end
14
+
15
+ # enumerates the resultset in batch mode
16
+ def find_each(&block)
17
+ relation.find_each_with_order(&block) if has_data?
18
+ end
19
+
20
+ # override if necessary in derived classes
21
+ def has_data?
22
+ @has_data ||= relation.count() > 0
23
+ end
24
+
25
+ protected
26
+
27
+ # override in derived classes
28
+ def build_relation(filter)
29
+
30
+ #
31
+ # use the given filter to add conditions
32
+ # to produce an ActiveRelation as the query
33
+ #
34
+ # E.g. filter.page #=> Model.all.page(filter.page)
35
+ #
36
+
37
+ raise NotImplementedError
38
+ end
39
+
40
+ # helper class
41
+ class Base
42
+ include Query
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ module Riveter
2
+ module QueryFilter
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include Riveter::Attributes
7
+
8
+ class << self
9
+ alias_method :filter_name, :model_name
10
+
11
+ def i18n_scope
12
+ :query_filters
13
+ end
14
+ end
15
+ end
16
+
17
+ # helper class
18
+ class Base
19
+ include QueryFilter
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,6 @@
1
+ module Riveter
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ module Riveter
2
+ module Rails
3
+ class Railtie < ::Rails::Railtie
4
+ initializer 'riveter.initialize' do
5
+ require 'riveter/form_builder_extensions'
6
+ require 'riveter/command_routes'
7
+ require 'riveter/enquiry_routes'
8
+ end
9
+
10
+ initializer 'riveter.set_autoload_paths', :before => :set_autoload_paths do |app|
11
+ config = app.config
12
+
13
+ # add paths to auto load path
14
+ %w{
15
+ commands
16
+ enquiries
17
+ enums
18
+ presenters
19
+ queries
20
+ query_filters
21
+ services
22
+ workers
23
+ }.each do |path|
24
+ config.autoload_paths += %W(#{config.root}/app/#{path})
25
+ config.autoload_paths += %W(#{config.root}/app/#{path}/concerns)
26
+ end
27
+ end
28
+
29
+ initializer "riveter.load_services" do |app|
30
+ ActiveSupport.on_load :after_initialize do |app|
31
+ #
32
+ # services need to be loaded manually since they aren't referenced
33
+ # directly and therefore cannot be autoloaded
34
+ #
35
+ # also, when the class is loaded, it registers itself as the service for a command
36
+ #
37
+ Dir[File.join(app.config.root, 'app', 'services', '**/*_service.rb')].each {|file| require file }
38
+ end
39
+ end
40
+
41
+ console do
42
+ # TODO
43
+ end
44
+
45
+ rake_tasks do
46
+ Dir[File.join(File.dirname(__FILE__), 'tasks/*.rake')].each { |file| load file }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ module Riveter
2
+ module Service
3
+ extend ActiveSupport::Concern
4
+ include AssociatedTypeRegistry
5
+
6
+ module ClassMethods
7
+ def register_as_handler_for(command_type)
8
+ register_type self, command_type
9
+ end
10
+ end
11
+
12
+ # override in derived classes
13
+ def perform(command, *args)
14
+
15
+ #
16
+ # use the given command's attributes to perform the action
17
+ #
18
+
19
+ raise NotImplementedError
20
+ end
21
+
22
+ # helper class
23
+ class Base
24
+ include Service
25
+
26
+ class << self
27
+ def inherited(klass)
28
+ #
29
+ # attempt to get the name of the command
30
+ # from the derived classes name and register
31
+ # it as the service handler for that command
32
+ #
33
+ # e.g. CreatePortfolioCommand ==> CreatePortfolioService
34
+ #
35
+ command_type = klass.name.gsub(/Service$/, 'Command').constantize rescue nil
36
+ register_type klass, command_type unless command_type.nil?
37
+ end
38
+ end
39
+
40
+ # NOTE: associated commands will be registered on this class!
41
+ # use the respective resolve methods with the Riveter::Service::Base in this case
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,55 @@
1
+ # helpers for use in testing
2
+
3
+ module Mock
4
+ class Block
5
+ def to_proc
6
+ lambda { |*args| call(*args) }
7
+ end
8
+
9
+ # the call method must be provided by in specs
10
+ # E.g. using `expect(mock_block_instance).to receive(:call)` to assert that the "block" gets called
11
+ def call
12
+ raise NotImplementedError, "Expecting `call` method to have an expectation defined to assert."
13
+ end
14
+ end
15
+
16
+ module Valid
17
+ def valid?
18
+ true
19
+ end
20
+ end
21
+
22
+ module Invalid
23
+ def valid?
24
+ false
25
+ end
26
+ end
27
+
28
+ class ValidCommand < Riveter::Command::Base
29
+ include Valid
30
+ end
31
+
32
+ class InvalidCommand < Riveter::Command::Base
33
+ include Invalid
34
+ end
35
+
36
+ class ValidQueryFilter < Riveter::QueryFilter::Base
37
+ include Valid
38
+ end
39
+
40
+ class InvalidQueryFilter < Riveter::QueryFilter::Base
41
+ include Invalid
42
+ end
43
+
44
+ class QueryWithData < Riveter::Query::Base
45
+ def has_data?
46
+ true
47
+ end
48
+ end
49
+
50
+ class QueryWithoutData < Riveter::Query::Base
51
+ def has_data?
52
+ false
53
+ end
54
+ end
55
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ module Riveter
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ module Riveter
2
+ module Worker
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # TODO: define mixed in methods
7
+ end
8
+
9
+ module ClassMethods
10
+ # TODO: define class methods
11
+ end
12
+
13
+ # TODO: define instance methods
14
+
15
+ # helper class
16
+ class Base
17
+ include Worker
18
+ end
19
+ end
20
+ end
data/lib/riveter.rb ADDED
@@ -0,0 +1,47 @@
1
+ require "riveter/version"
2
+
3
+ require 'active_model'
4
+ require 'active_record'
5
+ require 'active_support'
6
+ require 'validates_timeliness'
7
+
8
+ require 'active_support/core_ext'
9
+ require 'active_support/inflector'
10
+ require 'active_support/inflector'
11
+
12
+ module Riveter
13
+ autoload :AttributeDefaultValues, 'riveter/attribute_default_values'
14
+ autoload :AssociatedTypeRegistry, 'riveter/associated_type_registry'
15
+ autoload :Attributes, 'riveter/attributes'
16
+ autoload :Command, 'riveter/command'
17
+ autoload :CommandController, 'riveter/command_controller'
18
+ autoload :Enquiry, 'riveter/enquiry'
19
+ autoload :EnquiryController, 'riveter/enquiry_controller'
20
+ autoload :Enumerated, 'riveter/enumerated'
21
+ autoload :HashWithDependency, 'riveter/hash_with_dependency'
22
+ autoload :Presenter, 'riveter/presenter'
23
+ autoload :Query, 'riveter/query'
24
+ autoload :QueryFilter, 'riveter/query_filter'
25
+ autoload :Service, 'riveter/service'
26
+ autoload :Worker, 'riveter/worker'
27
+ end
28
+
29
+ # add autoload's for validators
30
+ module ActiveModel
31
+ module Validations
32
+ autoload :BooleanessValidator, 'riveter/booleaness_validator'
33
+ autoload :EmailValidator, 'riveter/email_validator'
34
+ end
35
+ end
36
+
37
+ require 'riveter/errors'
38
+ require 'riveter/core_extensions'
39
+
40
+ # Rails bits...
41
+ require 'riveter/rails/railtie' if defined?(::Rails::Railtie)
42
+ require 'riveter/rails/engine' if defined?(::Rails)
43
+
44
+ # include locale in load path
45
+ Dir[File.join(File.dirname(__FILE__), '*.yml')].each do |file|
46
+ I18n.load_path << file
47
+ end
data/riveter.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'riveter/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'riveter'
8
+ spec.version = Riveter::VERSION
9
+ spec.authors = ['Chris Stefano']
10
+ spec.email = ['virtualstaticvoid@gmail.com']
11
+ spec.summary = %q{Provides several useful patterns, packaged in a gem, for use in Rails.}
12
+ spec.description = %q{Provides several useful patterns, such as Enumerated, Command, Enquiry, Query, QueryFilter, Service, Presenter and Worker, packaged in a gem, for use in Rails and other Ruby applications.}
13
+ spec.homepage = 'https://github.com/virtualstaticvoid/riveter'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.required_ruby_version = '>= 2.0.0'
22
+
23
+ spec.add_dependency 'railties', '~> 4.0.0'
24
+ spec.add_dependency 'actionpack'
25
+ spec.add_dependency 'activemodel'
26
+ spec.add_dependency 'activerecord'
27
+ spec.add_dependency 'activesupport'
28
+ spec.add_dependency 'validates_timeliness'
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.5'
31
+ spec.add_development_dependency 'rake'
32
+ spec.add_development_dependency 'rails', '~> 4.0.5'
33
+ spec.add_development_dependency 'haml-rails'
34
+ spec.add_development_dependency 'rspec-rails'
35
+ spec.add_development_dependency 'shoulda-matchers', '~> 2.6.1'
36
+ spec.add_development_dependency 'ammeter'
37
+ spec.add_development_dependency 'simplecov', '~> 0.7.1'
38
+ spec.add_development_dependency 'pry'
39
+ spec.add_development_dependency 'pry-byebug'
40
+ end