fmrest-spyke 0.17.1 → 0.18.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19e4983cff9d5959b2e9263687daaf18d779fcf6d284cbb6ec8844c1623beabf
4
- data.tar.gz: 0e558a94cf0b26f5ffe1258f33385f0e016a73ae55aa200ea6768160c746ebd1
3
+ metadata.gz: 38cc05be48b9ba5737e7a2c1d89504bab617a2f1d6d7261fde1b5a919aa793e7
4
+ data.tar.gz: 0b1780c8ce2f7d8d8f4c300909b2bafb7f41e18e2ce648f929be9e2d3569ddbe
5
5
  SHA512:
6
- metadata.gz: 1af0c0918fe48374fd2dbe5f20bbeb8f0f7e9f73537233f9b530ea53ec37c3ceffba5612c244ce0c9553c66a2090dcd1d8330581940f6713660cbc6b1a362dd0
7
- data.tar.gz: 75abe05bdbfec9e21d0bc3e6dcc5c10d3bbdb66213382c494e3b7511f4c00c628b5ad054ca81e486c4c614a3c9832f60787000a5d990399488ce7027c59a45e1
6
+ metadata.gz: 123d5611c9c862605c30643b8034665c67c24fc283d21311f6124baff2271c459bcae0d4834f2480f4aa2e521105a6df58ecb011f46fc4f50a656df4a91108f5
7
+ data.tar.gz: 91a6d0bdf49792a76b0bf817543a89e7b92bcf0c55eaa128d9bee3219f250e47a14bd064f862383f11f66dac70f1830cc6f1017b56d912f4d8be344e7ac86bed
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## Changelog
2
2
 
3
+ ### 0.18.0
4
+
5
+ * Better support for portals with mismatching field qualifiers
6
+ * Defining an attribute on a model that would collide with an existing method
7
+ now raises an error
8
+
3
9
  ### 0.17.1
4
10
 
5
11
  * Fixed crash when `fmid_token` is set but `username` isn't
data/README.md CHANGED
@@ -543,6 +543,10 @@ class LoggyBee < FmRest::Layout
543
543
  end
544
544
  ```
545
545
 
546
+ ## Gotchas
547
+
548
+ Read about unexpected scenarios in the [gotchas doc](docs/Gotchas.md).
549
+
546
550
  ## API implementation completeness table
547
551
 
548
552
  FM Data API reference: https://fmhelp.filemaker.com/docs/18/en/dataapi/
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fmrest/spyke/portal_builder"
3
4
  require "fmrest/spyke/portal"
4
5
 
5
6
  module FmRest
@@ -13,6 +14,8 @@ module FmRest
13
14
  included do
14
15
  # Keep track of portal options by their FM keys as we could need it
15
16
  # to parse the portalData JSON in SpykeFormatter
17
+ #
18
+ # TODO: Replace this with options in PortalBuilder
16
19
  class_attribute :portal_options, instance_accessor: false, instance_predicate: false
17
20
 
18
21
  # class_attribute supports a :default option since ActiveSupport 5.2,
@@ -40,11 +43,13 @@ module FmRest
40
43
  # end
41
44
  #
42
45
  def has_portal(name, options = {})
43
- create_association(name, Portal, options)
46
+ # This is analogous to Spyke's create_association method, but using
47
+ # our custom builder instead
48
+ self.associations = associations.merge(name => PortalBuilder.new(self, name, Portal, options))
44
49
 
45
50
  # Store options for SpykeFormatter to use if needed
46
51
  portal_key = options[:portal_key] || name
47
- self.portal_options = portal_options.merge(portal_key.to_s => options.dup.merge(name: name.to_s)).freeze
52
+ self.portal_options = portal_options.merge(portal_key.to_s => options.dup.merge(name: name.to_s).freeze).freeze
48
53
 
49
54
  define_method "#{name.to_s.singularize}_ids" do
50
55
  association(name).map(&:id)
@@ -94,11 +94,17 @@ module FmRest
94
94
  end
95
95
 
96
96
  def _fmrest_define_attribute(from, to)
97
+ if existing_method = ((method_defined?(from) || private_method_defined?(from)) && from) ||
98
+ ((method_defined?("#{from}=") || private_method_defined?("#{from}=")) && "#{from}=")
99
+
100
+ raise ArgumentError, "You tried to define an attribute named `#{from}' on `#{name}', but this will generate a instance method `#{existing_method}', which is already defined by FmRest::Layout."
101
+ end
102
+
97
103
  # We use a setter here instead of injecting the hash key/value pair
98
104
  # directly with #[]= so that we don't change the mapped_attributes
99
105
  # hash on the parent class. The resulting hash is frozen for the
100
106
  # same reason.
101
- self.mapped_attributes = mapped_attributes.merge(from => to).freeze
107
+ self.mapped_attributes = mapped_attributes.merge(from => to.to_s).freeze
102
108
 
103
109
  _fmrest_attribute_methods_container.module_eval do
104
110
  define_method(from) do
@@ -6,8 +6,6 @@ module FmRest
6
6
  module GlobalFields
7
7
  extend ::ActiveSupport::Concern
8
8
 
9
- FULLY_QUALIFIED_FIELD_NAME_MATCHER = /\A[^:]+::[^:]+\Z/.freeze
10
-
11
9
  class_methods do
12
10
  def set_globals(values_hash)
13
11
  connection.patch(FmRest::V1.globals_path, {
@@ -26,7 +24,7 @@ module FmRest
26
24
  next
27
25
  end
28
26
 
29
- unless FULLY_QUALIFIED_FIELD_NAME_MATCHER === k.to_s
27
+ unless V1.is_fully_qualified?(k.to_s)
30
28
  raise ArgumentError, "global fields must be given in fully qualified format (table name::field name)"
31
29
  end
32
30
 
@@ -26,7 +26,7 @@ module FmRest
26
26
  def serialize_for_portal(portal)
27
27
  params =
28
28
  changed_params.except(:__record_id).transform_keys do |key|
29
- "#{portal.attribute_prefix}::#{key}"
29
+ V1.is_fully_qualified?(key) ? key : "#{portal.attribute_prefix}::#{key}"
30
30
  end
31
31
 
32
32
  params[:recordId] = __record_id.to_s if __record_id
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FmRest
4
+ module Spyke
5
+ class PortalBuilder < ::Spyke::Associations::Builder
6
+ attr_reader :options
7
+
8
+ def klass
9
+ begin
10
+ super
11
+ rescue NameError => e
12
+ ::FmRest::Layout
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -195,8 +195,8 @@ module FmRest
195
195
  out
196
196
  end
197
197
 
198
- # Extracts `recordId` and strips the `"PortalName::"` field prefix for each
199
- # portal
198
+ # Extracts `recordId` and strips the `"tableName::"` field qualifier for
199
+ # each portal
200
200
  #
201
201
  # Sample `json_portal_data`:
202
202
  #
@@ -210,19 +210,33 @@ module FmRest
210
210
  # @return [Hash] the portal data in Spyke format
211
211
  def prepare_portal_data(json_portal_data)
212
212
  json_portal_data.each_with_object({}) do |(portal_name, portal_records), out|
213
+
213
214
  portal_options = @model.portal_options[portal_name.to_s] || {}
215
+ portal_builder = @model.associations[portal_options[:name].to_sym]
216
+ portal_class = portal_builder && portal_builder.klass
217
+ portal_attributes = (portal_class && portal_class.mapped_attributes.values) || []
214
218
 
215
219
  out[portal_name] =
216
220
  portal_records.map do |portal_fields|
217
221
  attributes = { __record_id: portal_fields[:recordId] }
218
222
  attributes[:__mod_id] = portal_fields[:modId] if portal_fields[:modId]
219
223
 
220
- prefix = portal_options[:attribute_prefix] || portal_name
221
- prefix_matcher = /\A#{prefix}::/
224
+ qualifier = portal_options[:attribute_prefix] || portal_name
225
+ qualifier_matcher = /\A#{qualifier}::/
222
226
 
223
227
  portal_fields.each do |k, v|
224
228
  next if :recordId == k || :modId == k
225
- attributes[k.to_s.gsub(prefix_matcher, "").to_sym] = v
229
+
230
+ stripped_field_name = k.to_s.gsub(qualifier_matcher, "")
231
+
232
+ # Only use the non-qualified attribute name if it was defined
233
+ # that way on the portal model, otherwise default to the fully
234
+ # qualified name
235
+ if portal_attributes.include?(stripped_field_name)
236
+ attributes[stripped_field_name.to_sym] = v
237
+ else
238
+ attributes[k.to_sym] = v
239
+ end
226
240
  end
227
241
 
228
242
  attributes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fmrest-spyke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.1
4
+ version: 0.18.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pedro Carbajal
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-29 00:00:00.000000000 Z
11
+ date: 2021-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fmrest-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.17.1
19
+ version: 0.18.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.17.1
26
+ version: 0.18.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: spyke
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -68,6 +68,7 @@ files:
68
68
  - lib/fmrest/spyke/model/serialization.rb
69
69
  - lib/fmrest/spyke/model/uri.rb
70
70
  - lib/fmrest/spyke/portal.rb
71
+ - lib/fmrest/spyke/portal_builder.rb
71
72
  - lib/fmrest/spyke/relation.rb
72
73
  - lib/fmrest/spyke/spyke_formatter.rb
73
74
  - lib/fmrest/spyke/validation_error.rb
@@ -86,9 +87,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
87
  version: '0'
87
88
  required_rubygems_version: !ruby/object:Gem::Requirement
88
89
  requirements:
89
- - - ">="
90
+ - - ">"
90
91
  - !ruby/object:Gem::Version
91
- version: '0'
92
+ version: 1.3.1
92
93
  requirements: []
93
94
  rubygems_version: 3.2.3
94
95
  signing_key: