active_model_serializers_pg 0.0.6 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d35fba508c14ac3f2dac43976aa98853847901d1854a60cdfc17e9307d7bc054
4
- data.tar.gz: de31287ee80e62dbc4ea06dcef31269d70f1ecdb7611ab6021d56d671057aea7
3
+ metadata.gz: 709fe0bce48637cbd10e3f8a4cc66d9332da0a36ea2158153711c2f49bcdc82f
4
+ data.tar.gz: bbc3e6c16daf9b8c28ce8d105d1dc355c35b1188b935051447c6b5fab96acda0
5
5
  SHA512:
6
- metadata.gz: ef15cf70f75a4d508d963593fc806ab388d9f07b295e5a8a393bdcd2ddb1b95094c47f7229ab4113646454211b1dd4550111dc79902c6baf39ddaaa36a4c16a2
7
- data.tar.gz: 6221b9fa05569ad2fdd6dd874d326363ea698c6a7442a253e25d349adc046814edf1c67ec68a9ddb0f9fe0126052006261eee969093b78462a027bdb4fa94245
6
+ metadata.gz: c323f581ecea8145344d4fe95df91a76d548762de320a43513eb7081842d30b28e81fb33a4adc3cca173964d17ce5ba7c384e27043cf9aca68e0ca161b9b83b9
7
+ data.tar.gz: 076e6dad498e0d0533fe63f4a396099c61557c7b2a05a17ebe910f2caca61b11d4cf005351570e7a4579447e9c427ff7298b759f35a15bfe27749144bee44292
data/README.md CHANGED
@@ -59,8 +59,10 @@ Here are some other details we support:
59
59
  - `belongs_to`, `has_one`, and `has_many` associations.
60
60
  - If you serialize an `enum` you get the string values, not integers.
61
61
  - You can serialize an `alias`'d association.
62
+ - You can serialize an `alias_attribute`'d column.
62
63
  - We preserve SQL ordering from a model's `default_scope`.
63
64
  - We preserve SQL ordering attached to an association.
65
+ - When dasherizing we also dasherize json/jsonb/hstore contents (like standard AMS).
64
66
 
65
67
  ### Methods in Serializers and Models
66
68
 
data/Rakefile CHANGED
@@ -80,6 +80,9 @@ namespace :db do
80
80
  t.json "options"
81
81
  t.jsonb "prefs"
82
82
  t.hstore "settings"
83
+ t.json "selfies", array: true
84
+ t.jsonb "portraits", array: true
85
+ t.hstore "landscapes", array: true
83
86
  t.datetime "created_at"
84
87
  t.datetime "updated_at"
85
88
  end
@@ -77,7 +77,7 @@ module ActiveModelSerializers
77
77
  end
78
78
 
79
79
  def self.warn_about_collection_serializer
80
- msg = "You are using an ordinary AMS CollectionSerializer with the json_api_pg adapter, which probably means Rails is pointlessly loading all your ActiveRecord instances *and* running the build JSON-building query in Postgres."
80
+ msg = "You are using an ordinary AMS CollectionSerializer with the json_api_pg adapter, which probably means Rails is pointlessly loading all your ActiveRecord instances *and* running the JSON-building query in Postgres."
81
81
  if Object.const_defined? 'Rails'
82
82
  Rails.logger.warn msg
83
83
  else
@@ -105,8 +105,8 @@ end
105
105
  # i.e. how you got here, not how you'd leave:
106
106
  # "Reflection" seems to be the internal ActiveRecord lingo
107
107
  # for a belongs_to or has_many relationship.
108
- # (The public documentation calls these "associations",
109
- # I think think older versions of Rails even used that internally,
108
+ # (The public documentation calls these "associations".
109
+ # I think older versions of Rails even used that internally,
110
110
  # but nowadays the method names use "reflection".)
111
111
  class JsonThing
112
112
  attr_reader :ar_class, :full_name, :name, :serializer, :serializer_options, :json_key, :json_type, :reflection, :parent, :cte_name, :jbs_name
@@ -192,7 +192,7 @@ class JsonThing
192
192
  end
193
193
  end
194
194
 
195
- # Each thing has bother a `cte_foo` CTE and a `jbs_foo` CTE.
195
+ # Each thing has both a `cte_foo` CTE and a `jbs_foo` CTE.
196
196
  # (jbs stands for "JSONBs" and is meant to take 3 chars like `cte`.)
197
197
  # The former is just the relevant records,
198
198
  # and the second builds the JSON object for each record.
@@ -447,16 +447,22 @@ class JsonApiPgSql
447
447
  # Standard AMS dasherizes json/jsonb/hstore columns,
448
448
  # so we have to do the same:
449
449
  if ActiveModelSerializers.config.key_transform == :dash
450
- case resource.ar_class.attribute_types[field.to_s]
451
- when ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Hstore
450
+ cl = resource.ar_class.attribute_types[field.to_s]
451
+ if column_is_jsonb? cl
452
+ %Q{jsonb_dasherize("#{resource.table_name}"."#{field}")}
453
+ elsif column_is_jsonb_array? cl
454
+ # TODO: Could be faster:
455
+ # If we made the jsonb_dasherize function smarter so it could handle jsonb[],
456
+ # we wouldn't have to build a json object from the array then cast to jsonb[].
457
+ %Q{jsonb_dasherize(array_to_json("#{resource.table_name}"."#{field}")::jsonb)}
458
+ elsif column_is_castable_to_jsonb? cl
452
459
  # Fortunately we can cast hstore to jsonb,
453
460
  # which gives us a solution that works whether or not the hstore extension is installed.
454
461
  # Defining an hstore_dasherize function would work only if the extension were present.
455
462
  %Q{jsonb_dasherize("#{resource.table_name}"."#{field}"::jsonb)}
456
- when ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb
457
- %Q{jsonb_dasherize("#{resource.table_name}"."#{field}")}
458
- when self.class.json_column_type
459
- %Q{jsonb_dasherize("#{resource.table_name}"."#{field}"::jsonb)}
463
+ elsif column_is_castable_to_jsonb_array? cl
464
+ # TODO: Could be faster (see above):
465
+ %Q{jsonb_dasherize(array_to_json("#{resource.table_name}"."#{field}"::jsonb[])::jsonb)}
460
466
  else
461
467
  %Q{"#{resource.table_name}"."#{field}"}
462
468
  end
@@ -466,6 +472,25 @@ class JsonApiPgSql
466
472
  end
467
473
  end
468
474
 
475
+ def column_is_jsonb?(column_class)
476
+ column_class.is_a? ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb
477
+ end
478
+
479
+ def column_is_jsonb_array?(column_class)
480
+ column_class.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array) and
481
+ column_class.subtype.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb)
482
+ end
483
+
484
+ def column_is_castable_to_jsonb?(column_class)
485
+ column_class.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Hstore) or
486
+ column_class.is_a?(self.class.json_column_type)
487
+ end
488
+
489
+ def column_is_castable_to_jsonb_array?(column_class)
490
+ column_class.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array) and
491
+ column_is_castable_to_jsonb?(column_class.subtype)
492
+ end
493
+
469
494
  def select_resource_relationship_links(resource, reflection)
470
495
  reflection.links.map {|link_name, link_parts|
471
496
  <<~EOQ
@@ -603,8 +628,6 @@ class JsonApiPgSql
603
628
 
604
629
  # See note in _jbs_name method for why we split each thing into two CTEs.
605
630
  def include_cte(resource)
606
- # Sometimes options[:fields] has plural keys and sometimes singular,
607
- # so try both:
608
631
  parent = resource.parent
609
632
  <<~EOQ
610
633
  SELECT DISTINCT ON ("#{resource.table_name}"."#{resource.primary_key}")
@@ -1,3 +1,3 @@
1
1
  module ActiveModelSerializersPg
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
@@ -215,9 +215,12 @@ describe 'ArraySerializer' do
215
215
  let(:person) {
216
216
  Person.create first_name: 'Test',
217
217
  last_name: 'User',
218
- options: { 'foo_foo': 'baz', bar: [{ 'jar_jar': 'binks' }] },
219
- prefs: { 'foo_foo': 'baz', bar: [{ 'jar_jar': 'binks' }] },
220
- settings: { 'foo_foo': 'bar' }
218
+ options: { 'foo_foo': 'baz', bar: [{ 'jar_jar': 'binks' }] },
219
+ prefs: { 'foo_foo': 'baz', bar: [{ 'jar_jar': 'binks' }] },
220
+ settings: { 'foo_foo': 'bar' },
221
+ selfies: [ { 'photo_resolution': '200x200' } ],
222
+ portraits: [ { 'photo_resolution': '150x200' } ],
223
+ landscapes: [ { 'photo_resolution': '200x150' } ]
221
224
  }
222
225
  let(:options) { { each_serializer: PersonWithJsonSerializer } }
223
226
 
@@ -245,9 +248,18 @@ describe 'ArraySerializer' do
245
248
  bar: [{ 'jar-jar' => 'binks'}],
246
249
  'foo-foo' => 'baz',
247
250
  },
251
+ selfies: [
252
+ { 'photo-resolution' => '200x200' },
253
+ ],
248
254
  settings: {
249
255
  'foo-foo' => 'bar'
250
256
  },
257
+ portraits: [
258
+ { 'photo-resolution' => '150x200' },
259
+ ],
260
+ landscapes: [
261
+ { 'photo-resolution' => '200x150' },
262
+ ],
251
263
  },
252
264
  }
253
265
  ]
@@ -69,7 +69,13 @@ class PersonSerializer < ActiveModel::Serializer
69
69
  end
70
70
 
71
71
  class PersonWithJsonSerializer < ActiveModel::Serializer
72
- attributes :id, :options, :prefs, :settings
72
+ attributes :id,
73
+ :options, # json
74
+ :prefs, # jsonb
75
+ :settings, # hstore
76
+ :selfies, # json[]
77
+ :portraits, # jsonb[]
78
+ :landscapes # hstore[]
73
79
  end
74
80
 
75
81
  class Note < ActiveRecord::Base
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_model_serializers_pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul A. Jungwirth
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-25 00:00:00.000000000 Z
11
+ date: 2020-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -226,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
226
  - !ruby/object:Gem::Version
227
227
  version: '0'
228
228
  requirements: []
229
- rubygems_version: 3.0.1
229
+ rubygems_version: 3.0.8
230
230
  signing_key:
231
231
  specification_version: 4
232
232
  summary: Harness the power of PostgreSQL when crafting JSON reponses