active_model_serializers_pg 0.0.6 → 0.0.7

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: 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