quiver 0.21.0

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