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.
- checksums.yaml +4 -4
- data/.yardopts +2 -0
- data/CHANGELOG.md +38 -0
- data/README.md +194 -763
- metadata +70 -97
- data/.gitignore +0 -26
- data/.rspec +0 -3
- data/.travis.yml +0 -5
- data/Gemfile +0 -3
- data/Rakefile +0 -6
- data/fmrest.gemspec +0 -38
- data/lib/fmrest.rb +0 -29
- data/lib/fmrest/errors.rb +0 -28
- data/lib/fmrest/spyke.rb +0 -21
- data/lib/fmrest/spyke/base.rb +0 -23
- data/lib/fmrest/spyke/container_field.rb +0 -59
- data/lib/fmrest/spyke/model.rb +0 -36
- data/lib/fmrest/spyke/model/associations.rb +0 -82
- data/lib/fmrest/spyke/model/attributes.rb +0 -171
- data/lib/fmrest/spyke/model/auth.rb +0 -35
- data/lib/fmrest/spyke/model/connection.rb +0 -74
- data/lib/fmrest/spyke/model/container_fields.rb +0 -25
- data/lib/fmrest/spyke/model/global_fields.rb +0 -40
- data/lib/fmrest/spyke/model/http.rb +0 -37
- data/lib/fmrest/spyke/model/orm.rb +0 -212
- data/lib/fmrest/spyke/model/serialization.rb +0 -91
- data/lib/fmrest/spyke/model/uri.rb +0 -30
- data/lib/fmrest/spyke/portal.rb +0 -55
- data/lib/fmrest/spyke/relation.rb +0 -359
- data/lib/fmrest/spyke/spyke_formatter.rb +0 -273
- data/lib/fmrest/spyke/validation_error.rb +0 -25
- data/lib/fmrest/string_date.rb +0 -220
- data/lib/fmrest/token_store.rb +0 -6
- data/lib/fmrest/token_store/active_record.rb +0 -74
- data/lib/fmrest/token_store/base.rb +0 -25
- data/lib/fmrest/token_store/memory.rb +0 -26
- data/lib/fmrest/token_store/moneta.rb +0 -41
- data/lib/fmrest/token_store/redis.rb +0 -45
- data/lib/fmrest/v1.rb +0 -21
- data/lib/fmrest/v1/connection.rb +0 -89
- data/lib/fmrest/v1/container_fields.rb +0 -114
- data/lib/fmrest/v1/dates.rb +0 -81
- data/lib/fmrest/v1/paths.rb +0 -47
- data/lib/fmrest/v1/raise_errors.rb +0 -57
- data/lib/fmrest/v1/token_session.rb +0 -142
- data/lib/fmrest/v1/token_store/active_record.rb +0 -13
- data/lib/fmrest/v1/token_store/memory.rb +0 -13
- data/lib/fmrest/v1/type_coercer.rb +0 -192
- data/lib/fmrest/v1/utils.rb +0 -95
- data/lib/fmrest/version.rb +0 -5
data/lib/fmrest/spyke.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
begin
|
4
|
-
require "spyke"
|
5
|
-
rescue LoadError => e
|
6
|
-
e.message << " (Did you include Spyke in your Gemfile?)" unless e.message.frozen?
|
7
|
-
raise e
|
8
|
-
end
|
9
|
-
|
10
|
-
require "fmrest"
|
11
|
-
require "fmrest/spyke/spyke_formatter"
|
12
|
-
require "fmrest/spyke/model"
|
13
|
-
require "fmrest/spyke/base"
|
14
|
-
|
15
|
-
module FmRest
|
16
|
-
module Spyke
|
17
|
-
def self.included(base)
|
18
|
-
base.include Model
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
data/lib/fmrest/spyke/base.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module FmRest
|
4
|
-
module Spyke
|
5
|
-
class Base < ::Spyke::Base
|
6
|
-
include FmRest::Spyke::Model
|
7
|
-
end
|
8
|
-
|
9
|
-
class << self
|
10
|
-
def Base(config = nil)
|
11
|
-
warn "[DEPRECATION] Inheriting from `FmRest::Spyke::Base(config)` is deprecated and will be removed, inherit from `FmRest::Spyke::Base` (without arguments) and use `fmrest_config=` instead"
|
12
|
-
|
13
|
-
if config
|
14
|
-
return Class.new(::FmRest::Spyke::Base) do
|
15
|
-
self.fmrest_config = config
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
::FmRest::Spyke::Base
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module FmRest
|
4
|
-
module Spyke
|
5
|
-
class ContainerField
|
6
|
-
|
7
|
-
# @return [String] the name of the container field
|
8
|
-
attr_reader :name
|
9
|
-
|
10
|
-
# @param base [FmRest::Spyke::Base] the record this container belongs to
|
11
|
-
# @param name [Symbol] the name of the container field
|
12
|
-
def initialize(base, name)
|
13
|
-
@base = base
|
14
|
-
@name = name
|
15
|
-
end
|
16
|
-
|
17
|
-
# @return [String] the URL for the container
|
18
|
-
def url
|
19
|
-
@base.attributes[name]
|
20
|
-
end
|
21
|
-
|
22
|
-
# @return (see FmRest::V1::ContainerFields#fetch_container_data)
|
23
|
-
def download
|
24
|
-
FmRest::V1.fetch_container_data(url, @base.class.connection)
|
25
|
-
end
|
26
|
-
|
27
|
-
# @param filename_or_io [String, IO] a path to the file to upload or an
|
28
|
-
# IO object
|
29
|
-
# @param options [Hash]
|
30
|
-
# @option options [Integer] :repetition (1) The repetition to pass to the
|
31
|
-
# upload URL
|
32
|
-
# @option (see FmRest::V1::ContainerFields#upload_container_data)
|
33
|
-
def upload(filename_or_io, options = {})
|
34
|
-
raise ArgumentError, "Record needs to be saved before uploading to a container field" unless @base.persisted?
|
35
|
-
|
36
|
-
response =
|
37
|
-
FmRest::V1.upload_container_data(
|
38
|
-
@base.class.connection,
|
39
|
-
upload_path(options[:repetition] || 1),
|
40
|
-
filename_or_io,
|
41
|
-
options
|
42
|
-
)
|
43
|
-
|
44
|
-
# Update mod id on record
|
45
|
-
@base.mod_id = response.body[:data][:mod_id]
|
46
|
-
|
47
|
-
true
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
# @param repetition [Integer]
|
53
|
-
# @return [String] the path for uploading a file to the container
|
54
|
-
def upload_path(repetition)
|
55
|
-
FmRest::V1.container_field_path(@base.class.layout, @base.id, name, repetition)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/lib/fmrest/spyke/model.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "fmrest/spyke/model/connection"
|
4
|
-
require "fmrest/spyke/model/uri"
|
5
|
-
require "fmrest/spyke/model/attributes"
|
6
|
-
require "fmrest/spyke/model/serialization"
|
7
|
-
require "fmrest/spyke/model/associations"
|
8
|
-
require "fmrest/spyke/model/orm"
|
9
|
-
require "fmrest/spyke/model/container_fields"
|
10
|
-
require "fmrest/spyke/model/global_fields"
|
11
|
-
require "fmrest/spyke/model/http"
|
12
|
-
require "fmrest/spyke/model/auth"
|
13
|
-
|
14
|
-
module FmRest
|
15
|
-
module Spyke
|
16
|
-
module Model
|
17
|
-
extend ::ActiveSupport::Concern
|
18
|
-
|
19
|
-
include Connection
|
20
|
-
include Uri
|
21
|
-
include Attributes
|
22
|
-
include Serialization
|
23
|
-
include Associations
|
24
|
-
include Orm
|
25
|
-
include ContainerFields
|
26
|
-
include GlobalFields
|
27
|
-
include Http
|
28
|
-
include Auth
|
29
|
-
|
30
|
-
included do
|
31
|
-
# @return [Integer] the record's modId
|
32
|
-
attr_accessor :mod_id
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "fmrest/spyke/portal"
|
4
|
-
|
5
|
-
module FmRest
|
6
|
-
module Spyke
|
7
|
-
module Model
|
8
|
-
module Associations
|
9
|
-
extend ::ActiveSupport::Concern
|
10
|
-
|
11
|
-
included do
|
12
|
-
# Keep track of portal options by their FM keys as we could need it
|
13
|
-
# to parse the portalData JSON in SpykeFormatter
|
14
|
-
class_attribute :portal_options, instance_accessor: false, instance_predicate: false
|
15
|
-
|
16
|
-
# class_attribute supports a :default option since ActiveSupport 5.2,
|
17
|
-
# but we want to support previous versions too so we set the default
|
18
|
-
# manually instead
|
19
|
-
self.portal_options = {}.freeze
|
20
|
-
|
21
|
-
class << self; private :portal_options=; end
|
22
|
-
end
|
23
|
-
|
24
|
-
class_methods do
|
25
|
-
# Based on +has_many+, but creates a special Portal association
|
26
|
-
# instead.
|
27
|
-
#
|
28
|
-
# Custom options:
|
29
|
-
#
|
30
|
-
# * <tt>:portal_key</tt> - The key used for the portal in the FM Data JSON portalData.
|
31
|
-
# * <tt>:attribute_prefix</tt> - The prefix used for portal attributes in the FM Data JSON.
|
32
|
-
#
|
33
|
-
# Example:
|
34
|
-
#
|
35
|
-
# has_portal :jobs, portal_key: "JobsTable", attribute_prefix: "Job"
|
36
|
-
#
|
37
|
-
def has_portal(name, options = {})
|
38
|
-
create_association(name, Portal, options)
|
39
|
-
|
40
|
-
# Store options for SpykeFormatter to use if needed
|
41
|
-
portal_key = options[:portal_key] || name
|
42
|
-
self.portal_options = portal_options.merge(portal_key.to_s => options.dup.merge(name: name.to_s)).freeze
|
43
|
-
|
44
|
-
define_method "#{name.to_s.singularize}_ids" do
|
45
|
-
association(name).map(&:id)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Override Spyke's association reader to keep a cache of loaded
|
51
|
-
# portals. Spyke's default behavior is to reload the association
|
52
|
-
# each time.
|
53
|
-
#
|
54
|
-
def association(name)
|
55
|
-
@loaded_portals ||= {}
|
56
|
-
|
57
|
-
if @loaded_portals.has_key?(name.to_sym)
|
58
|
-
return @loaded_portals[name.to_sym]
|
59
|
-
end
|
60
|
-
|
61
|
-
super.tap do |assoc|
|
62
|
-
next unless assoc.kind_of?(FmRest::Spyke::Portal)
|
63
|
-
@loaded_portals[name.to_sym] = assoc
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def reload(*_)
|
68
|
-
super.tap { @loaded_portals = nil }
|
69
|
-
end
|
70
|
-
|
71
|
-
def portals
|
72
|
-
self.class.associations.each_with_object([]) do |(key, _), portals|
|
73
|
-
candidate = association(key)
|
74
|
-
next unless candidate.kind_of?(FmRest::Spyke::Portal)
|
75
|
-
portals << candidate
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
@@ -1,171 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "fmrest/spyke/model/orm"
|
4
|
-
|
5
|
-
module FmRest
|
6
|
-
module Spyke
|
7
|
-
module Model
|
8
|
-
module Attributes
|
9
|
-
extend ::ActiveSupport::Concern
|
10
|
-
|
11
|
-
include Orm # Needed to extend custom save and reload
|
12
|
-
|
13
|
-
include ::ActiveModel::Dirty
|
14
|
-
include ::ActiveModel::ForbiddenAttributesProtection
|
15
|
-
|
16
|
-
included do
|
17
|
-
# Prevent the creation of plain (no prefix/suffix) attribute methods
|
18
|
-
# when calling ActiveModels' define_attribute_method, otherwise it
|
19
|
-
# will define an `attribute` method which overrides the one provided
|
20
|
-
# by Spyke
|
21
|
-
self.attribute_method_matchers.shift
|
22
|
-
|
23
|
-
# ActiveModel::Dirty methods for id
|
24
|
-
define_attribute_method(:id)
|
25
|
-
|
26
|
-
# Keep track of attribute mappings so we can get the FM field names
|
27
|
-
# for changed attributes
|
28
|
-
class_attribute :mapped_attributes, instance_writer: false, instance_predicate: false
|
29
|
-
|
30
|
-
# class_attribute supports a :default option since ActiveSupport 5.2,
|
31
|
-
# but we want to support previous versions too so we set the default
|
32
|
-
# manually instead
|
33
|
-
self.mapped_attributes = ::ActiveSupport::HashWithIndifferentAccess.new.freeze
|
34
|
-
|
35
|
-
class << self; private :mapped_attributes=; end
|
36
|
-
end
|
37
|
-
|
38
|
-
class_methods do
|
39
|
-
# Similar to Spyke::Base.attributes, but allows defining attribute
|
40
|
-
# methods that map to FM attributes with different names.
|
41
|
-
#
|
42
|
-
# Example:
|
43
|
-
#
|
44
|
-
# class Person < Spyke::Base
|
45
|
-
# include FmRest::Spyke::Model
|
46
|
-
#
|
47
|
-
# attributes first_name: "FstName", last_name: "LstName"
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# p = Person.new
|
51
|
-
# p.first_name = "Jojo"
|
52
|
-
# p.attributes # => { "FstName" => "Jojo" }
|
53
|
-
#
|
54
|
-
def attributes(*attrs)
|
55
|
-
if attrs.length == 1 && attrs.first.kind_of?(Hash)
|
56
|
-
attrs.first.each { |from, to| _fmrest_define_attribute(from, to) }
|
57
|
-
else
|
58
|
-
attrs.each { |attr| _fmrest_define_attribute(attr, attr) }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
# Override Spyke::Base.new_or_return (private), called whenever
|
65
|
-
# loading records from the HTTP API, so we can reset dirty info on
|
66
|
-
# freshly loaded records
|
67
|
-
#
|
68
|
-
# See: https://github.com/balvig/spyke/blob/master/lib/spyke/http.rb
|
69
|
-
#
|
70
|
-
def new_or_return(attributes_or_object, *_)
|
71
|
-
# In case of an existing Spyke object return it as is so that we
|
72
|
-
# don't accidentally remove dirty data from associations
|
73
|
-
return super if attributes_or_object.is_a?(::Spyke::Base)
|
74
|
-
super.tap do |record|
|
75
|
-
# In ActiveModel 4.x #clear_changes_information is a private
|
76
|
-
# method, so we need to call it with send() in that case, but
|
77
|
-
# keep calling it normally for AM5+
|
78
|
-
if record.respond_to?(:clear_changes_information)
|
79
|
-
record.clear_changes_information
|
80
|
-
else
|
81
|
-
record.send(:clear_changes_information)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def _fmrest_attribute_methods_container
|
87
|
-
@fmrest_attribute_methods_container ||= Module.new.tap { |mod| include mod }
|
88
|
-
end
|
89
|
-
|
90
|
-
def _fmrest_define_attribute(from, to)
|
91
|
-
raise ArgumentError, "attribute name `id' is reserved for the recordId" if from.to_s == "id"
|
92
|
-
|
93
|
-
# We use a setter here instead of injecting the hash key/value pair
|
94
|
-
# directly with #[]= so that we don't change the mapped_attributes
|
95
|
-
# hash on the parent class. The resulting hash is frozen for the
|
96
|
-
# same reason.
|
97
|
-
self.mapped_attributes = mapped_attributes.merge(from => to).freeze
|
98
|
-
|
99
|
-
_fmrest_attribute_methods_container.module_eval do
|
100
|
-
define_method(from) do
|
101
|
-
attribute(to)
|
102
|
-
end
|
103
|
-
|
104
|
-
define_method(:"#{from}=") do |value|
|
105
|
-
send("#{from}_will_change!") unless value == send(from)
|
106
|
-
set_attribute(to, value)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Define ActiveModel::Dirty's methods
|
111
|
-
define_attribute_method(from)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def id=(value)
|
116
|
-
id_will_change! unless value == id
|
117
|
-
super
|
118
|
-
end
|
119
|
-
|
120
|
-
def reload(*args)
|
121
|
-
super.tap { |r| clear_changes_information }
|
122
|
-
end
|
123
|
-
|
124
|
-
def save(*args)
|
125
|
-
super.tap { |r| changes_applied_after_save if r }
|
126
|
-
end
|
127
|
-
|
128
|
-
# ActiveModel::Dirty since version 5.2 assumes that if there's an
|
129
|
-
# @attributes instance variable set we must be using ActiveRecord, so
|
130
|
-
# we override the instance variable name used by Spyke to avoid issues.
|
131
|
-
#
|
132
|
-
# TODO: Submit a pull request to Spyke so this isn't needed
|
133
|
-
#
|
134
|
-
def attributes
|
135
|
-
@_spyke_attributes
|
136
|
-
end
|
137
|
-
|
138
|
-
# In addition to the comments above on `attributes`, this also adds
|
139
|
-
# support for forbidden attributes
|
140
|
-
#
|
141
|
-
def attributes=(new_attributes)
|
142
|
-
@_spyke_attributes ||= ::Spyke::Attributes.new(scope.params)
|
143
|
-
use_setters(sanitize_for_mass_assignment(new_attributes)) if new_attributes && !new_attributes.empty?
|
144
|
-
end
|
145
|
-
|
146
|
-
private
|
147
|
-
|
148
|
-
def changed_params
|
149
|
-
attributes.to_params.slice(*mapped_changed)
|
150
|
-
end
|
151
|
-
|
152
|
-
def mapped_changed
|
153
|
-
mapped_attributes.values_at(*changed)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Use known mapped_attributes for inspect
|
157
|
-
#
|
158
|
-
def inspect_attributes
|
159
|
-
mapped_attributes.except(primary_key).map do |k, v|
|
160
|
-
"#{k}: #{attribute(v).inspect}"
|
161
|
-
end.join(', ')
|
162
|
-
end
|
163
|
-
|
164
|
-
def changes_applied_after_save
|
165
|
-
changes_applied
|
166
|
-
portals.each(&:parent_changes_applied)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module FmRest
|
4
|
-
module Spyke
|
5
|
-
module Model
|
6
|
-
module Auth
|
7
|
-
extend ::ActiveSupport::Concern
|
8
|
-
|
9
|
-
class_methods do
|
10
|
-
# Logs out the database session for this model (and other models
|
11
|
-
# using the same credentials).
|
12
|
-
#
|
13
|
-
# @raise [FmRest::V1::TokenSession::NoSessionTokenSet] if no session
|
14
|
-
# token was set (and no request is sent).
|
15
|
-
def logout!
|
16
|
-
connection.delete(FmRest::V1.session_path("dummy-token"))
|
17
|
-
end
|
18
|
-
|
19
|
-
# Logs out the database session for this model (and other models
|
20
|
-
# using the same credentials). Unlike `logout!`, no exception is
|
21
|
-
# raised in case of missing session token.
|
22
|
-
#
|
23
|
-
# @return [Boolean] Whether the logout request was sent (it's only
|
24
|
-
# sent if a session token was previously set)
|
25
|
-
def logout
|
26
|
-
logout!
|
27
|
-
true
|
28
|
-
rescue FmRest::V1::TokenSession::NoSessionTokenSet
|
29
|
-
false
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module FmRest
|
4
|
-
module Spyke
|
5
|
-
module Model
|
6
|
-
module Connection
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
included do
|
10
|
-
class_attribute :fmrest_config, instance_writer: false, instance_predicate: false
|
11
|
-
|
12
|
-
# Overrides the fmrest_config reader created by class_attribute so we
|
13
|
-
# can default set the default at call time.
|
14
|
-
#
|
15
|
-
# This method gets overwriten in subclasses if self.fmrest_config= is
|
16
|
-
# called.
|
17
|
-
define_singleton_method(:fmrest_config) do
|
18
|
-
FmRest.default_connection_settings
|
19
|
-
end
|
20
|
-
|
21
|
-
class_attribute :faraday_block, instance_accessor: false, instance_predicate: false
|
22
|
-
class << self; private :faraday_block, :faraday_block=; end
|
23
|
-
|
24
|
-
# FM Data API expects PATCH for updates (Spyke's default was PUT)
|
25
|
-
self.callback_methods = { create: :post, update: :patch }.freeze
|
26
|
-
end
|
27
|
-
|
28
|
-
class_methods do
|
29
|
-
def connection
|
30
|
-
super || fmrest_connection
|
31
|
-
end
|
32
|
-
|
33
|
-
# Sets a block for injecting custom middleware into the Faraday
|
34
|
-
# connection. Example usage:
|
35
|
-
#
|
36
|
-
# class MyModel < FmRest::Spyke::Base
|
37
|
-
# faraday do |conn|
|
38
|
-
# # Set up a custom logger for the model
|
39
|
-
# conn.response :logger, MyApp.logger, bodies: true
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
def faraday(&block)
|
44
|
-
self.faraday_block = block
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def fmrest_connection
|
50
|
-
@fmrest_connection ||=
|
51
|
-
begin
|
52
|
-
config = fmrest_config
|
53
|
-
|
54
|
-
FmRest::V1.build_connection(config) do |conn|
|
55
|
-
faraday_block.call(conn) if faraday_block
|
56
|
-
|
57
|
-
# Pass the class to SpykeFormatter's initializer so it can have
|
58
|
-
# access to extra context defined in the model, e.g. a portal
|
59
|
-
# where name of the portal and the attributes prefix don't match
|
60
|
-
# and need to be specified as options to `portal`
|
61
|
-
conn.use FmRest::Spyke::SpykeFormatter, self
|
62
|
-
|
63
|
-
conn.use FmRest::V1::TypeCoercer, config
|
64
|
-
|
65
|
-
# FmRest::Spyke::JsonParse expects symbol keys
|
66
|
-
conn.response :json, parser_options: { symbolize_names: true }
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|