fmrest 0.10.0 → 0.13.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +194 -763
  5. metadata +70 -97
  6. data/.gitignore +0 -26
  7. data/.rspec +0 -3
  8. data/.travis.yml +0 -5
  9. data/Gemfile +0 -3
  10. data/Rakefile +0 -6
  11. data/fmrest.gemspec +0 -38
  12. data/lib/fmrest.rb +0 -29
  13. data/lib/fmrest/errors.rb +0 -28
  14. data/lib/fmrest/spyke.rb +0 -21
  15. data/lib/fmrest/spyke/base.rb +0 -23
  16. data/lib/fmrest/spyke/container_field.rb +0 -59
  17. data/lib/fmrest/spyke/model.rb +0 -36
  18. data/lib/fmrest/spyke/model/associations.rb +0 -82
  19. data/lib/fmrest/spyke/model/attributes.rb +0 -171
  20. data/lib/fmrest/spyke/model/auth.rb +0 -35
  21. data/lib/fmrest/spyke/model/connection.rb +0 -74
  22. data/lib/fmrest/spyke/model/container_fields.rb +0 -25
  23. data/lib/fmrest/spyke/model/global_fields.rb +0 -40
  24. data/lib/fmrest/spyke/model/http.rb +0 -37
  25. data/lib/fmrest/spyke/model/orm.rb +0 -212
  26. data/lib/fmrest/spyke/model/serialization.rb +0 -91
  27. data/lib/fmrest/spyke/model/uri.rb +0 -30
  28. data/lib/fmrest/spyke/portal.rb +0 -55
  29. data/lib/fmrest/spyke/relation.rb +0 -359
  30. data/lib/fmrest/spyke/spyke_formatter.rb +0 -273
  31. data/lib/fmrest/spyke/validation_error.rb +0 -25
  32. data/lib/fmrest/string_date.rb +0 -220
  33. data/lib/fmrest/token_store.rb +0 -6
  34. data/lib/fmrest/token_store/active_record.rb +0 -74
  35. data/lib/fmrest/token_store/base.rb +0 -25
  36. data/lib/fmrest/token_store/memory.rb +0 -26
  37. data/lib/fmrest/token_store/moneta.rb +0 -41
  38. data/lib/fmrest/token_store/redis.rb +0 -45
  39. data/lib/fmrest/v1.rb +0 -21
  40. data/lib/fmrest/v1/connection.rb +0 -89
  41. data/lib/fmrest/v1/container_fields.rb +0 -114
  42. data/lib/fmrest/v1/dates.rb +0 -81
  43. data/lib/fmrest/v1/paths.rb +0 -47
  44. data/lib/fmrest/v1/raise_errors.rb +0 -57
  45. data/lib/fmrest/v1/token_session.rb +0 -142
  46. data/lib/fmrest/v1/token_store/active_record.rb +0 -13
  47. data/lib/fmrest/v1/token_store/memory.rb +0 -13
  48. data/lib/fmrest/v1/type_coercer.rb +0 -192
  49. data/lib/fmrest/v1/utils.rb +0 -95
  50. data/lib/fmrest/version.rb +0 -5
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FmRest
4
- module Spyke
5
- # ActiveModel 4 doesn't include a ValidationError class, which we want to
6
- # raise when model.validate! fails.
7
- #
8
- # In order to break the least amount of code that uses AM5+, while still
9
- # supporting AM4 we use this proxy class that inherits from
10
- # AM::ValidationError if it's there, or reimplements it otherwise
11
- if defined?(::ActiveModel::ValidationError)
12
- class ValidationError < ::ActiveModel::ValidationError; end
13
- else
14
- class ValidationError < StandardError
15
- attr_reader :model
16
-
17
- def initialize(model)
18
- @model = model
19
- errors = @model.errors.full_messages.join(", ")
20
- super("Invalid model: #{errors}")
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,220 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "date"
4
-
5
- module FmRest
6
- # Gotchas:
7
- #
8
- # 1.
9
- #
10
- # Date === <StringDate instance> # => false
11
- #
12
- # The above can affect case conditions, as trying to match a StringDate
13
- # with:
14
- #
15
- # case obj
16
- # when Date
17
- # ...
18
- #
19
- # ...will not work.
20
- #
21
- # Instead one must specify the FmRest::StringDate class:
22
- #
23
- # case obj
24
- # when Date, FmRest::StringDate
25
- # ...
26
- #
27
- # 2.
28
- #
29
- # StringDate#eql? only matches other strings, not dates.
30
- #
31
- # This could affect hash indexing when a StringDate is used as a key.
32
- #
33
- # TODO: Verify the above
34
- #
35
- # 3.
36
- #
37
- # StringDate#succ and StringDate#next return a String, despite Date#succ
38
- # and Date#next also existing.
39
- #
40
- # Workaround: Use StringDate#next_day or strdate + 1
41
- #
42
- # 4.
43
- #
44
- # StringDate#to_s returns the original string, not the Date string
45
- # representation.
46
- #
47
- # Workaround: Use strdate.to_date.to_s
48
- #
49
- # 5.
50
- #
51
- # StringDate#hash returns the hash for the string (important when using
52
- # a StringDate as a hash key)
53
- #
54
- # 6.
55
- #
56
- # StringDate#as_json returns the string
57
- #
58
- # Workaround: Use strdate.to_date.as_json
59
- #
60
- # 7.
61
- #
62
- # Equality with Date is not reciprocal:
63
- #
64
- # str_date == date #=> true
65
- # date == str_date #=> false
66
- #
67
- # NOTE: Potential workaround: Inherit StringDate from Date instead of String
68
- #
69
- # 8.
70
- #
71
- # Calling string transforming methods (e.g. .upcase) returns a StringDate
72
- # instead of a String.
73
- #
74
- # NOTE: Potential workaround: Inherit StringDate from Date instead of String
75
- #
76
- class StringDate < String
77
- DELEGATE_CLASS = ::Date
78
-
79
- class InvalidDate < ArgumentError; end
80
-
81
- class << self
82
- def strptime(str, date_format, *_)
83
- begin
84
- date = self::DELEGATE_CLASS.strptime(str, date_format)
85
- rescue ArgumentError
86
- raise InvalidDate
87
- end
88
-
89
- new(str, date)
90
- end
91
- end
92
-
93
- def initialize(str, date, **str_args)
94
- raise ArgumentError, "str must be of class String" unless str.is_a?(String)
95
- raise ArgumentError, "date must be of class #{self.class::DELEGATE_CLASS.name}" unless date.is_a?(self.class::DELEGATE_CLASS)
96
-
97
- super(str, **str_args)
98
-
99
- @delegate = date
100
-
101
- freeze
102
- end
103
-
104
- def is_a?(klass)
105
- klass == ::Date || super
106
- end
107
- alias_method :kind_of?, :is_a?
108
-
109
- def to_date
110
- @delegate
111
- end
112
-
113
- def to_datetime
114
- @delegate.to_datetime
115
- end
116
-
117
- def to_time
118
- @delegate.to_time
119
- end
120
-
121
- # ActiveSupport method
122
- def in_time_zone(*_)
123
- @delegate.in_time_zone(*_)
124
- end
125
-
126
- def inspect
127
- "#<#{self.class.name} #{@delegate.inspect} - #{super}>"
128
- end
129
-
130
- def <=>(oth)
131
- return @delegate <=> oth if oth.is_a?(::Date) || oth.is_a?(Numeric)
132
- super
133
- end
134
-
135
- def +(val)
136
- return @delegate + val if val.kind_of?(Numeric)
137
- super
138
- end
139
-
140
- def <<(val)
141
- return @delegate << val if val.kind_of?(Numeric)
142
- super
143
- end
144
-
145
- def ==(oth)
146
- return @delegate == oth if oth.kind_of?(::Date) || oth.kind_of?(Numeric)
147
- super
148
- end
149
- alias_method :===, :==
150
-
151
- def upto(oth, &blk)
152
- return @delegate.upto(oth, &blk) if oth.kind_of?(::Date) || oth.kind_of?(Numeric)
153
- super
154
- end
155
-
156
- def between?(a, b)
157
- return @delegate.between?(a, b) if [a, b].any? {|o| o.is_a?(::Date) || o.is_a?(Numeric) }
158
- super
159
- end
160
-
161
- private
162
-
163
- def respond_to_missing?(name, include_private = false)
164
- @delegate.respond_to?(name, include_private)
165
- end
166
-
167
- def method_missing(method, *args, &block)
168
- @delegate.send(method, *args, &block)
169
- end
170
- end
171
-
172
- class StringDateTime < StringDate
173
- DELEGATE_CLASS = ::DateTime
174
-
175
- def is_a?(klass)
176
- klass == ::DateTime || super
177
- end
178
- alias_method :kind_of?, :is_a?
179
-
180
- def to_date
181
- @delegate.to_date
182
- end
183
-
184
- def to_datetime
185
- @delegate
186
- end
187
- end
188
-
189
- module StringDateAwareness
190
- def _parse(v, *_)
191
- if v.is_a?(StringDateTime)
192
- return { year: v.year, mon: v.month, mday: v.mday, hour: v.hour, min: v.min, sec: v.sec, sec_fraction: v.sec_fraction, offset: v.offset }
193
- end
194
- if v.is_a?(StringDate)
195
- return { year: v.year, mon: v.month, mday: v.mday }
196
- end
197
- super
198
- end
199
-
200
- def parse(v, *_)
201
- if v.is_a?(StringDate)
202
- return self == ::DateTime ? v.to_datetime : v.to_date
203
- end
204
- super
205
- end
206
-
207
- # Overriding case equality method so that it returns true for
208
- # `FmRest::StringDate` instances
209
- #
210
- # Calls superclass method
211
- #
212
- def ===(other)
213
- super || other.is_a?(StringDate)
214
- end
215
-
216
- def self.enable(classes: [Date, DateTime])
217
- classes.each { |klass| klass.singleton_class.prepend(self) }
218
- end
219
- end
220
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FmRest
4
- module TokenStore
5
- end
6
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fmrest/token_store/base"
4
- require "active_record"
5
-
6
- module FmRest
7
- module TokenStore
8
- # Heavily inspired by Moneta's ActiveRecord store:
9
- #
10
- # https://github.com/minad/moneta/blob/master/lib/moneta/adapters/activerecord.rb
11
- #
12
- class ActiveRecord < Base
13
- DEFAULT_TABLE_NAME = "fmrest_session_tokens".freeze
14
-
15
- @connection_lock = ::Mutex.new
16
- class << self
17
- attr_reader :connection_lock
18
- end
19
-
20
- attr_reader :connection_pool, :model
21
-
22
- delegate :with_connection, to: :connection_pool
23
-
24
- def initialize(options = {})
25
- super
26
-
27
- @connection_pool = ::ActiveRecord::Base.connection_pool
28
-
29
- create_table
30
-
31
- @model = Class.new(::ActiveRecord::Base)
32
- @model.table_name = table_name
33
- end
34
-
35
- def delete(key)
36
- model.where(scope: key).delete_all
37
- end
38
-
39
- def load(key)
40
- model.where(scope: key).pluck(:token).first
41
- end
42
-
43
- def store(key, value)
44
- record = model.find_or_initialize_by(scope: key)
45
- record.token = value
46
- record.save!
47
- value
48
- end
49
-
50
- private
51
-
52
- def create_table
53
- with_connection do |conn|
54
- return if conn.table_exists?(table_name)
55
-
56
- # Prevent multiple connections from attempting to create the table simultaneously.
57
- self.class.connection_lock.synchronize do
58
- conn.create_table(table_name, id: false) do |t|
59
- t.string :scope, null: false
60
- t.string :token, null: false
61
- t.datetime :updated_at
62
- end
63
- conn.add_index(table_name, :scope, unique: true)
64
- conn.add_index(table_name, [:scope, :token])
65
- end
66
- end
67
- end
68
-
69
- def table_name
70
- options[:table_name] || DEFAULT_TABLE_NAME
71
- end
72
- end
73
- end
74
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FmRest
4
- module TokenStore
5
- class Base
6
- attr_reader :options
7
-
8
- def initialize(options = {})
9
- @options = options
10
- end
11
-
12
- def load(key)
13
- raise "Not implemented"
14
- end
15
-
16
- def store(key, value)
17
- raise "Not implemented"
18
- end
19
-
20
- def delete(key)
21
- raise "Not implemented"
22
- end
23
- end
24
- end
25
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fmrest/token_store/base"
4
-
5
- module FmRest
6
- module TokenStore
7
- class Memory < Base
8
- def initialize(*args)
9
- super
10
- @tokens = {}
11
- end
12
-
13
- def delete(key)
14
- @tokens.delete(key)
15
- end
16
-
17
- def load(key)
18
- @tokens[key]
19
- end
20
-
21
- def store(key, value)
22
- @tokens[key] = value
23
- end
24
- end
25
- end
26
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fmrest/token_store/base"
4
- require "moneta"
5
-
6
- module FmRest
7
- module TokenStore
8
- class Moneta < Base
9
- DEFAULT_ADAPTER = :Memory
10
- DEFAULT_PREFIX = "fmrest-token:".freeze
11
-
12
- attr_reader :moneta
13
-
14
- # @param options [Hash]
15
- # Options to pass to `Moneta.new`
16
- # @option options [Symbol] :adapter (:Memory)
17
- # The Moneta adapter to use
18
- # @option options [String] :prefix (DEFAULT_PREFIX)
19
- # The prefix to use for keys
20
- def initialize(options = {})
21
- options = options.dup
22
- super(options)
23
- adapter = options.delete(:adapter) || DEFAULT_ADAPTER
24
- options[:prefix] ||= DEFAULT_PREFIX
25
- @moneta = ::Moneta.new(adapter, options)
26
- end
27
-
28
- def load(key)
29
- moneta[key]
30
- end
31
-
32
- def delete(key)
33
- moneta.delete(key)
34
- end
35
-
36
- def store(key, value)
37
- moneta[key] = value
38
- end
39
- end
40
- end
41
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "fmrest/token_store/base"
4
- require "redis" unless defined?(MockRedis)
5
-
6
- module FmRest
7
- module TokenStore
8
- class Redis < Base
9
- DEFAULT_PREFIX = "fmrest-token:".freeze
10
-
11
- STORE_OPTIONS = [:redis, :prefix].freeze
12
-
13
- def initialize(options = {})
14
- super
15
- @redis = @options[:redis] || ::Redis.new(options_for_redis)
16
- @prefix = @options[:prefix] || DEFAULT_PREFIX
17
- end
18
-
19
- def load(key)
20
- @redis.get(prefix_key(key))
21
- end
22
-
23
- def store(key, value)
24
- @redis.set(prefix_key(key), value)
25
- value
26
- end
27
-
28
- def delete(key)
29
- @redis.del(prefix_key(key))
30
- end
31
-
32
- private
33
-
34
- def options_for_redis
35
- @options.dup.tap do |options|
36
- STORE_OPTIONS.each { |opt| options.delete(opt) }
37
- end
38
- end
39
-
40
- def prefix_key(key)
41
- "#{@prefix}#{key}"
42
- end
43
- end
44
- end
45
- end