quiver 0.21.0

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 (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +6 -0
  6. data/README.md +22 -0
  7. data/Rakefile +17 -0
  8. data/bin/quiver +9 -0
  9. data/lib/quiver.rb +46 -0
  10. data/lib/quiver/abstract_action.rb +31 -0
  11. data/lib/quiver/action.rb +208 -0
  12. data/lib/quiver/action/filter_error.rb +33 -0
  13. data/lib/quiver/action/filter_value.rb +152 -0
  14. data/lib/quiver/action/invalid_request_body_error.rb +30 -0
  15. data/lib/quiver/action/pagination_link_builder.rb +67 -0
  16. data/lib/quiver/adapter.rb +51 -0
  17. data/lib/quiver/adapter/active_record_adapter_filter.rb +102 -0
  18. data/lib/quiver/adapter/active_record_helpers.rb +258 -0
  19. data/lib/quiver/adapter/arec_low_level_creator.rb +82 -0
  20. data/lib/quiver/adapter/arec_low_level_deleter.rb +74 -0
  21. data/lib/quiver/adapter/arec_low_level_updater.rb +105 -0
  22. data/lib/quiver/adapter/filter_helpers.rb +58 -0
  23. data/lib/quiver/adapter/helpers_helpers.rb +53 -0
  24. data/lib/quiver/adapter/memory_adapter_filter.rb +71 -0
  25. data/lib/quiver/adapter/memory_adapter_store.rb +34 -0
  26. data/lib/quiver/adapter/memory_helpers.rb +182 -0
  27. data/lib/quiver/adapter/memory_uuid_primary_key.rb +25 -0
  28. data/lib/quiver/application.rb +128 -0
  29. data/lib/quiver/cli/app.rb +25 -0
  30. data/lib/quiver/cli/generators/endpoint.rb +17 -0
  31. data/lib/quiver/cli/generators/new_application.rb +166 -0
  32. data/lib/quiver/cli/generators/new_application_cli.rb +25 -0
  33. data/lib/quiver/cli/server.rb +37 -0
  34. data/lib/quiver/cli/templates/Gemfile.tt +8 -0
  35. data/lib/quiver/cli/templates/Rakefile.tt +12 -0
  36. data/lib/quiver/cli/templates/config.tt +3 -0
  37. data/lib/quiver/cli/templates/config/database.tt +21 -0
  38. data/lib/quiver/cli/templates/gemspec.tt +33 -0
  39. data/lib/quiver/cli/templates/gitignore.tt +10 -0
  40. data/lib/quiver/cli/templates/lib/application.tt +14 -0
  41. data/lib/quiver/cli/templates/lib/application/config/router.tt +11 -0
  42. data/lib/quiver/cli/templates/lib/application/version.tt +3 -0
  43. data/lib/quiver/cli/templates/spec/spec_helper.tt +19 -0
  44. data/lib/quiver/duty.rb +34 -0
  45. data/lib/quiver/duty_master.rb +23 -0
  46. data/lib/quiver/duty_master/delayed_job_adapter.rb +15 -0
  47. data/lib/quiver/duty_master/memory_adapter.rb +18 -0
  48. data/lib/quiver/duty_test_helper.rb +23 -0
  49. data/lib/quiver/duty_test_helper/delayed_job_helper.rb +9 -0
  50. data/lib/quiver/duty_test_helper/memory_helper.rb +15 -0
  51. data/lib/quiver/error.rb +24 -0
  52. data/lib/quiver/error_collection.rb +60 -0
  53. data/lib/quiver/json_parser.rb +17 -0
  54. data/lib/quiver/logger.rb +26 -0
  55. data/lib/quiver/mapper.rb +311 -0
  56. data/lib/quiver/mapper/hook.rb +21 -0
  57. data/lib/quiver/mapper/mapper_result.rb +7 -0
  58. data/lib/quiver/mapper/not_found_error.rb +27 -0
  59. data/lib/quiver/mapper/simple_query_builder.rb +70 -0
  60. data/lib/quiver/mapper/soft_delete.rb +15 -0
  61. data/lib/quiver/mappers.rb +75 -0
  62. data/lib/quiver/middleware_stack.rb +35 -0
  63. data/lib/quiver/model.rb +63 -0
  64. data/lib/quiver/model/soft_delete.rb +14 -0
  65. data/lib/quiver/model/validation_error.rb +27 -0
  66. data/lib/quiver/model/validations.rb +45 -0
  67. data/lib/quiver/patcher.rb +94 -0
  68. data/lib/quiver/result.rb +44 -0
  69. data/lib/quiver/route_helper.rb +16 -0
  70. data/lib/quiver/router.rb +37 -0
  71. data/lib/quiver/serialization.rb +6 -0
  72. data/lib/quiver/serialization/json_api.rb +7 -0
  73. data/lib/quiver/serialization/json_api/item_type_handler.rb +96 -0
  74. data/lib/quiver/serialization/json_api/serializer.rb +77 -0
  75. data/lib/quiver/tasks.rb +31 -0
  76. data/lib/quiver/validator.rb +83 -0
  77. data/lib/quiver/validators/base.rb +21 -0
  78. data/lib/quiver/validators/presence.rb +34 -0
  79. data/lib/quiver/validators/unique.rb +33 -0
  80. data/lib/quiver/version.rb +3 -0
  81. data/quiver.gemspec +42 -0
  82. metadata +393 -0
@@ -0,0 +1,82 @@
1
+ module Quiver
2
+ module Adapter
3
+ module ActiveRecord
4
+ class ARecLowLevelCreator
5
+ attr_reader :primary_key
6
+
7
+ def initialize(adapter_klass, original_attributes)
8
+ self.adapter_klass = adapter_klass
9
+ self.failed = false
10
+ self.original_attributes = original_attributes
11
+ self.attrs = {}
12
+ end
13
+
14
+ def map(attributes, opts)
15
+ if opts[:foreign_key]
16
+ attributes.merge!(opts[:foreign_key])
17
+ end
18
+
19
+ if opts[:primary] && original_attributes[:__type__]
20
+ attributes.merge!(
21
+ original_attributes[:__type__][:name] => original_attributes[:__type__][:value]
22
+ )
23
+ end
24
+
25
+ record = record_class(opts[:to]).create(attributes)
26
+
27
+ if record.persisted?
28
+ attrs.merge!(record.attributes)
29
+
30
+ if opts[:primary]
31
+ self.primary_key = record.send(adapter_klass.primary_key_name)
32
+ end
33
+ else
34
+ self.failed = true
35
+ end
36
+ end
37
+
38
+ def map_array(h, opts)
39
+ h.each do |key, items|
40
+ attrs[key] = items.map do |attributes|
41
+ if opts[:foreign_key]
42
+ attributes.merge!(opts[:foreign_key])
43
+ end
44
+
45
+ record = record_class(opts[:to]).create(attributes)
46
+
47
+ if record.persisted?
48
+ attributes.merge(id: record.id)
49
+ else
50
+ self.failed = true
51
+ {}
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def success?
58
+ !failed
59
+ end
60
+
61
+ def failed!
62
+ self.failed = true
63
+ end
64
+
65
+ def result
66
+ original_attributes.symbolize_keys.merge(attrs.merge(
67
+ adapter_klass.primary_key_name => primary_key
68
+ ).symbolize_keys)
69
+ end
70
+
71
+ private
72
+
73
+ attr_accessor :adapter_klass, :failed, :original_attributes, :attrs, :mapper_klass
74
+ attr_writer :primary_key
75
+
76
+ def record_class(name)
77
+ adapter_klass.record_classes[name]
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,74 @@
1
+ module Quiver
2
+ module Adapter
3
+ module ActiveRecord
4
+ class ARecLowLevelDeleter
5
+ def initialize(adapter_klass, original_attributes)
6
+ self.adapter_klass = adapter_klass
7
+ self.failed = false
8
+ self.original_attributes = original_attributes
9
+ self.attrs = {}
10
+ self.calls = []
11
+ end
12
+
13
+ def map(attributes, opts)
14
+ record = record_class(opts[:to])
15
+
16
+ if opts[:foreign_key]
17
+ record = record.where(opts[:foreign_key])
18
+ end
19
+
20
+ if opts[:primary]
21
+ record = record.where(
22
+ adapter_klass.primary_key_name => primary_key
23
+ )
24
+ end
25
+
26
+ calls.unshift -> {
27
+ record.delete_all == 1
28
+ }
29
+ end
30
+
31
+ def map_array(h, opts)
32
+ raise ArgumentError, 'map_array requires opts[foreign_key] to be set' unless opts[:foreign_key]
33
+
34
+ h.each do |key, items|
35
+ record = record_class(opts[:to])
36
+ query = record.where(opts[:foreign_key])
37
+
38
+ remove_ids = record.pluck(:id)
39
+
40
+ calls.unshift -> {
41
+ query.where(id: remove_ids).delete_all == remove_ids.count
42
+ }
43
+ end
44
+ end
45
+
46
+ def success?
47
+ calls.all? do |call|
48
+ call.call
49
+ end && !failed
50
+ end
51
+
52
+ def failed!
53
+ self.failed = true
54
+ end
55
+
56
+ def result
57
+ {}
58
+ end
59
+
60
+ def primary_key
61
+ original_attributes[adapter_klass.primary_key_name]
62
+ end
63
+
64
+ private
65
+
66
+ attr_accessor :adapter_klass, :failed, :mapper_klass, :original_attributes, :attrs, :calls
67
+
68
+ def record_class(name)
69
+ adapter_klass.record_classes[name]
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,105 @@
1
+ module Quiver
2
+ module Adapter
3
+ module ActiveRecord
4
+ class ARecLowLevelUpdater
5
+ def initialize(adapter_klass, original_attributes)
6
+ self.adapter_klass = adapter_klass
7
+ self.failed = false
8
+ self.original_attributes = original_attributes
9
+ self.attrs = {}
10
+ end
11
+
12
+ def map(attributes, opts)
13
+ record = record_class(opts[:to])
14
+
15
+ if opts[:foreign_key]
16
+ record = record.where(opts[:foreign_key])
17
+ end
18
+
19
+ if opts[:primary]
20
+ record = record.where(
21
+ adapter_klass.primary_key_name => primary_key
22
+ )
23
+ end
24
+
25
+ result = record.update_all(attributes)
26
+
27
+ if result == 0
28
+ self.failed = true
29
+ end
30
+ end
31
+
32
+ def map_array(h, opts)
33
+ raise ArgumentError, 'map_array requires opts[foreign_key] to be set' unless opts[:foreign_key]
34
+
35
+ h.each do |key, items|
36
+ record = record_class(opts[:to])
37
+ query = record.where(opts[:foreign_key])
38
+
39
+ ids = record.pluck(:id)
40
+ remaining_ids = items.map { |i| i[:id] }.compact
41
+ remove_ids = ids - remaining_ids
42
+
43
+ query.where(id: remove_ids).delete_all
44
+
45
+ attrs[key] = items.map do |item|
46
+ item = item.merge(opts[:foreign_key])
47
+
48
+ if item[:id]
49
+ result = query.where(id: item[:id]).update_all(item)
50
+
51
+ if result != 1
52
+ self.failed = true
53
+ else
54
+ item
55
+ end
56
+ else
57
+ result = record.create(item)
58
+
59
+ if !result.persisted?
60
+ self.failed = true
61
+ else
62
+ result.attributes.symbolize_keys
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def success?
70
+ !failed
71
+ end
72
+
73
+ def failed!
74
+ self.failed = true
75
+ end
76
+
77
+ def result
78
+ r = original_attributes.symbolize_keys.merge(attrs.merge(
79
+ adapter_klass.primary_key_name => primary_key
80
+ ).symbolize_keys)
81
+
82
+ if original_attributes[:__type__]
83
+ r.merge!(
84
+ original_attributes[:__type__][:name] => original_attributes[:__type__][:value]
85
+ )
86
+ end
87
+
88
+ r
89
+ end
90
+
91
+ def primary_key
92
+ original_attributes[adapter_klass.primary_key_name]
93
+ end
94
+
95
+ private
96
+
97
+ attr_accessor :adapter_klass, :failed, :mapper_klass, :original_attributes, :attrs
98
+
99
+ def record_class(name)
100
+ adapter_klass.record_classes[name]
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,58 @@
1
+ module Quiver
2
+ module Adapter
3
+ module FilterHelpers
4
+ def initialize(memo, filter)
5
+ self.memo = memo
6
+ self.filter_params = filter
7
+ end
8
+
9
+ def filter
10
+ filter_params.inject(memo) do |memo, (attr, filter)|
11
+ filter_attributes = filter.is_a?(Hash) ? filter : filter.filter_attributes
12
+ filter_attributes.inject(memo) do |memo, (comparator, value)|
13
+ if value.nil?
14
+ memo
15
+ else
16
+ case comparator.to_s.downcase
17
+ when 'eq'
18
+ equal_filter(memo, attr, value)
19
+ when 'not_eq'
20
+ not_equal_filter(memo, attr, value)
21
+ when 'in'
22
+ in_filter(memo, attr, value)
23
+ when 'not_in'
24
+ not_in_filter(memo, attr, value)
25
+ when 'lt'
26
+ less_than_filter(memo, attr, value)
27
+ when 'gt'
28
+ greater_than_filter(memo, attr, value)
29
+ when 'lte'
30
+ less_than_or_equal_filter(memo, attr, value)
31
+ when 'gte'
32
+ greater_than_or_equal_filter(memo, attr, value)
33
+ when 'not_lt'
34
+ greater_than_or_equal_filter(memo, attr, value)
35
+ when 'not_gt'
36
+ less_than_or_equal_filter(memo, attr, value)
37
+ when 'not_lte'
38
+ greater_than_filter(memo, attr, value)
39
+ when 'not_gte'
40
+ less_than_filter(memo, attr, value)
41
+ else
42
+ if respond_to?("#{comparator.to_s.downcase}_filter", true)
43
+ send("#{comparator.to_s.downcase}_filter", memo, attr, value)
44
+ else
45
+ memo
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ attr_accessor :memo, :filter_params
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,53 @@
1
+ module Quiver
2
+ module Adapter
3
+ module HelpersHelpers
4
+ def self.included(host)
5
+ host.send(:extend, SelfMethods)
6
+ end
7
+
8
+ module SelfMethods
9
+ def included(host)
10
+ if !host.is_a?(Quiver::Adapter)
11
+ host.send(:include, Quiver::Adapter)
12
+ end
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def mapper_name
19
+ @mapper_name ||= self.class.parent.name.split('::').last.underscore
20
+ end
21
+
22
+ def when_valid(model, adapter_op)
23
+ raise ArgumentError, "requires block" unless block_given?
24
+
25
+ errors = model.validate(
26
+ tags: [adapter_op],
27
+ mapper: mapper_klass.new,
28
+ model: model,
29
+ adapter: self
30
+ )
31
+
32
+ if errors.success?
33
+ current_time = Time.now.utc
34
+ model.updated_at = current_time if model.respond_to?(:updated_at=)
35
+
36
+ if adapter_op == :create
37
+ model.created_at ||= current_time if model.respond_to?(:created_at)
38
+ end
39
+
40
+ object = yield(model, errors)
41
+ end
42
+
43
+ Quiver::Mapper::MapperResult.new(object, errors, adapter_op: adapter_op)
44
+ end
45
+
46
+ def hydrate(attributes)
47
+ mapper_klass.hydrate(attributes).tap do |obj|
48
+ obj.persisted_by!(adapter_type)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,71 @@
1
+ module Quiver
2
+ module Adapter
3
+ module MemoryAdapterFilterDefaults
4
+ include FilterHelpers
5
+
6
+ def equal_filter(memo, attr, value)
7
+ memo.select do |obj|
8
+ obj[attr.to_sym] == value
9
+ end
10
+ end
11
+
12
+ def not_equal_filter(memo, attr, value)
13
+ memo.select do |obj|
14
+ obj[attr.to_sym] != value
15
+ end
16
+ end
17
+
18
+ def in_filter(memo, attr, value)
19
+ memo.select do |obj|
20
+ value.include?(obj[attr.to_sym])
21
+ end
22
+ end
23
+
24
+ def not_in_filter(memo, attr, value)
25
+ memo.select do |obj|
26
+ !value.include?(obj[attr.to_sym])
27
+ end
28
+ end
29
+
30
+ def less_than_filter(memo, attr, value)
31
+ memo.select do |obj|
32
+ obj[attr.to_sym] < value
33
+ end
34
+ end
35
+
36
+ def greater_than_filter(memo, attr, value)
37
+ memo.select do |obj|
38
+ obj[attr.to_sym] > value
39
+ end
40
+ end
41
+
42
+ def less_than_or_equal_filter(memo, attr, value)
43
+ memo.select do |obj|
44
+ obj[attr.to_sym] <= value
45
+ end
46
+ end
47
+
48
+ def greater_than_or_equal_filter(memo, attr, value)
49
+ memo.select do |obj|
50
+ obj[attr.to_sym] >= value
51
+ end
52
+ end
53
+
54
+ def nil_filter(memo, attr, value)
55
+ memo.select do |obj|
56
+ obj[attr.to_sym].nil? == (value == 'true' || value == true)
57
+ end
58
+ end
59
+
60
+ def not_nil_filter(memo, attr, value)
61
+ memo.select do |obj|
62
+ obj[attr.to_sym].nil? != (value == 'true' || value == true)
63
+ end
64
+ end
65
+ end
66
+
67
+ class MemoryAdapterFilter
68
+ include MemoryAdapterFilterDefaults
69
+ end
70
+ end
71
+ end