caruby-core 2.1.1 → 2.1.2
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.
- data/Gemfile +1 -0
- data/History.md +5 -1
- data/lib/caruby/database/cache.rb +20 -9
- data/lib/caruby/database/lazy_loader.rb +1 -1
- data/lib/caruby/database/operation.rb +2 -0
- data/lib/caruby/database/persistable.rb +19 -13
- data/lib/caruby/database/persistence_service.rb +14 -38
- data/lib/caruby/database/persistifier.rb +86 -37
- data/lib/caruby/database/reader.rb +87 -87
- data/lib/caruby/database/reader_template_builder.rb +7 -4
- data/lib/caruby/database/sql_executor.rb +32 -15
- data/lib/caruby/database/writer.rb +20 -12
- data/lib/caruby/database/writer_template_builder.rb +10 -6
- data/lib/caruby/database.rb +97 -55
- data/lib/caruby/helpers/coordinate.rb +4 -4
- data/lib/caruby/helpers/person.rb +2 -2
- data/lib/caruby/helpers/properties.rb +4 -4
- data/lib/caruby/helpers/roman.rb +2 -2
- data/lib/caruby/helpers/version.rb +1 -1
- data/lib/caruby/json/serializable.rb +17 -0
- data/lib/caruby/metadata/propertied.rb +8 -1
- data/lib/caruby/metadata/property_characteristics.rb +41 -46
- data/lib/caruby/metadata.rb +1 -2
- data/lib/caruby/migration/migrator.rb +108 -0
- data/lib/caruby/resource.rb +2 -2
- data/lib/caruby/version.rb +1 -1
- data/lib/caruby.rb +0 -2
- data/test/lib/caruby/database/cache_test.rb +1 -3
- metadata +6 -8
- data/lib/caruby/caruby-src.tar.gz +0 -0
- data/lib/caruby/json/deserializer.rb +0 -15
- data/lib/caruby/json/serializer.rb +0 -69
@@ -9,37 +9,38 @@ module CaRuby
|
|
9
9
|
# +:autogenerated+ flag.
|
10
10
|
SUPPORTED_FLAGS = [
|
11
11
|
:autogenerated, :logical, :cascaded, :no_cascade_update_to_create, :saved, :unsaved, :fetched,
|
12
|
-
:unfetched, :include_in_save_template, :fetch_saved, :create_only, :update_only,
|
13
|
-
:volatile].to_set
|
12
|
+
:unfetched, :transient, :include_in_save_template, :fetch_saved, :create_only, :update_only,
|
13
|
+
:nosync, :volatile].to_set
|
14
14
|
|
15
|
-
# Returns whether
|
16
|
-
# *
|
17
|
-
# *
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
15
|
+
# Returns whether this property is fetched, determined as follows:
|
16
|
+
# * this property is marked with the +:fetched+ flag
|
17
|
+
# * this property is not marked with the +:transient+ or +:unfetched+ flag
|
18
|
+
# * otherwise, this is a non-domain property
|
19
|
+
# * otherwise, this is a domain property and one of the following conditions hold:
|
20
|
+
# * this is a non-logical dependent domain property
|
21
|
+
# * this is an owner property
|
22
|
+
# * this is an abstract, non-derived independent property
|
23
23
|
#
|
24
|
-
# @return [Boolean] whether
|
24
|
+
# @return [Boolean] whether this property is fetched
|
25
25
|
def fetched?
|
26
26
|
return true if @flags.include?(:fetched)
|
27
|
-
return false if @flags.include?(:unfetched)
|
27
|
+
return false if @flags.include?(:transient) or @flags.include?(:unfetched)
|
28
28
|
nondomain? or dependent? ? fetched_dependent? : fetched_independent?
|
29
29
|
end
|
30
|
-
|
31
|
-
# Returns whether
|
30
|
+
|
31
|
+
# Returns whether this property is unfetched, unsaved and should not be
|
32
|
+
# lazy-loaded, determined by whether it is marked with the +:transient+ flag.
|
32
33
|
#
|
33
|
-
# @return [Boolean] whether
|
34
|
-
def
|
35
|
-
@flags.include?(:
|
34
|
+
# @return [Boolean] whether this property is transient
|
35
|
+
def transient?
|
36
|
+
@flags.include?(:transient)
|
36
37
|
end
|
37
|
-
|
38
|
-
# Returns whether
|
38
|
+
|
39
|
+
# Returns whether this property is a dependent whose value is automatically generated
|
39
40
|
# with place-holder domain objects when the parent is created. An attribute is auto-generated
|
40
41
|
# if the +:autogenerated+ flag is set.
|
41
42
|
#
|
42
|
-
# @return [Boolean] whether
|
43
|
+
# @return [Boolean] whether this property is auto-generated
|
43
44
|
def autogenerated?
|
44
45
|
@flags.include?(:autogenerated)
|
45
46
|
end
|
@@ -50,34 +51,34 @@ module CaRuby
|
|
50
51
|
# * it is {#cascaded?} and marked with the +:unfetched+ flag
|
51
52
|
# * it is marked with the +:fetch_saved+ flag
|
52
53
|
#
|
53
|
-
# @return [Boolean] whether
|
54
|
+
# @return [Boolean] whether this property must be refetched in order to reflect
|
54
55
|
# the database content
|
55
56
|
def fetch_saved?
|
56
57
|
@flags.include?(:fetch_saved) or autogenerated? or (cascaded? and @flags.include?(:unfetched))
|
57
58
|
end
|
58
59
|
|
59
|
-
# Returns whether
|
60
|
+
# Returns whether this property is either:
|
60
61
|
# 1. an owner attribute which does not automatically cascade application service creation
|
61
62
|
# or update to the referenced dependent, or
|
62
63
|
# 2. the dependent attribute whose inverse is a logical owner attribute
|
63
64
|
#
|
64
|
-
# @return [Boolean] whether
|
65
|
+
# @return [Boolean] whether this property is an uncascaded dependent
|
65
66
|
def logical?
|
66
67
|
@flags.include?(:logical) or (owner? and inverse_property and inverse_property.logical?)
|
67
68
|
end
|
68
69
|
|
69
|
-
#
|
70
|
-
# *
|
71
|
-
# * the
|
70
|
+
# This property is creatable if all of the following conditions hold:
|
71
|
+
# * it is {#saved?}
|
72
|
+
# * the +:update_only+ flag is not set
|
72
73
|
#
|
73
74
|
# @return [Boolean] whether this attribute is saved in a create operation
|
74
75
|
def creatable?
|
75
76
|
saved? and not @flags.include?(:update_only)
|
76
77
|
end
|
77
78
|
|
78
|
-
#
|
79
|
-
# *
|
80
|
-
# * the
|
79
|
+
# This property is updatable if all of the following conditions hold:
|
80
|
+
# * it is {#saved?}
|
81
|
+
# * the +:create_only+ flag is not set
|
81
82
|
#
|
82
83
|
# @return [Boolean] whether this attribute is saved in a update operation
|
83
84
|
def updatable?
|
@@ -86,7 +87,7 @@ module CaRuby
|
|
86
87
|
|
87
88
|
# Indicates whether this reference propery is saved when its owner is saved.
|
88
89
|
#
|
89
|
-
# @return [Boolean] whether
|
90
|
+
# @return [Boolean] whether this property is a physical dependent or the +:cascaded+ flag is set
|
90
91
|
def cascaded?
|
91
92
|
(dependent? and not logical?) or @flags.include?(:cascaded)
|
92
93
|
end
|
@@ -110,25 +111,23 @@ module CaRuby
|
|
110
111
|
# The given object has a null identifier:
|
111
112
|
# followed by the attribute type name.
|
112
113
|
#
|
113
|
-
# @return [Boolean] whether
|
114
|
+
# @return [Boolean] whether this property cascades to crate when the owner is updated
|
114
115
|
def cascade_update_to_create?
|
115
116
|
cascaded? and not @flags.include?(:no_cascade_update_to_create)
|
116
117
|
end
|
117
118
|
|
118
|
-
#
|
119
|
-
# * the attribute :unsaved flag is set
|
120
|
-
# * the attribute is {#proxied_save?}
|
119
|
+
# This property is saved if it is a Java property that is not {#unsaved} or {#proxied_save?}
|
121
120
|
# and any of the following conditions hold:
|
122
|
-
# *
|
123
|
-
# *
|
124
|
-
# *
|
125
|
-
# *
|
126
|
-
# *
|
121
|
+
# * it is {#nondomain?}
|
122
|
+
# * it is {#cascaded?}
|
123
|
+
# * it is not a {#collection?}
|
124
|
+
# * it does not have an inverse
|
125
|
+
# * it is a {#unidirectional_java_dependent?}
|
127
126
|
#
|
128
127
|
# @return [Boolean] whether this attribute is saved in a create or update operation
|
129
128
|
def saved?
|
130
129
|
@flags.include?(:saved) or
|
131
|
-
(java_property? and not @flags.include?(:unsaved)
|
130
|
+
(java_property? and not (@flags.include?(:unsaved) or transient? or proxied_save?) and
|
132
131
|
(nondomain? or cascaded? or not collection? or inverse.nil? or unidirectional_java_dependent?))
|
133
132
|
end
|
134
133
|
|
@@ -143,7 +142,7 @@ module CaRuby
|
|
143
142
|
not saved?
|
144
143
|
end
|
145
144
|
|
146
|
-
# @return [Boolean] whether
|
145
|
+
# @return [Boolean] whether this property return {#type} is a Resource class which
|
147
146
|
# implements the saver_proxy method
|
148
147
|
def proxied_save?
|
149
148
|
domain? and type.method_defined?(:saver_proxy)
|
@@ -163,11 +162,6 @@ module CaRuby
|
|
163
162
|
inv_prop = inverse_property
|
164
163
|
inv_prop.nil? or inv_prop.collection?
|
165
164
|
end
|
166
|
-
|
167
|
-
# @return [Boolean] whether the subject attribute is not saved
|
168
|
-
def transient?
|
169
|
-
not saved?
|
170
|
-
end
|
171
165
|
|
172
166
|
# @return [Boolean] whether this is a non-collection Java attribute
|
173
167
|
def searchable?
|
@@ -176,6 +170,7 @@ module CaRuby
|
|
176
170
|
|
177
171
|
# @return [Boolean] whether this attribute is set by the server
|
178
172
|
def volatile?
|
173
|
+
# TODO - subsume by autogenerated?
|
179
174
|
to_sym == :identifier or @flags.include?(:volatile)
|
180
175
|
end
|
181
176
|
|
data/lib/caruby/metadata.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require 'jinx/json/deserializer'
|
2
1
|
require 'caruby/metadata/propertied'
|
3
2
|
|
4
3
|
module CaRuby
|
5
4
|
# The metadata persistence mix-in.
|
6
5
|
module Metadata
|
7
|
-
include Propertied, Jinx::
|
6
|
+
include Propertied, Jinx::Metadata
|
8
7
|
|
9
8
|
private
|
10
9
|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'jinx/helpers/stopwatch'
|
2
|
+
require 'jinx/migration/migrator'
|
3
|
+
|
4
|
+
module CaRuby
|
5
|
+
class Migrator < Jinx::Migrator
|
6
|
+
# Creates a new Migrator with the given options.
|
7
|
+
#
|
8
|
+
# The migration configuration must provide sufficient information to build a well-formed migration
|
9
|
+
# target object. For example, if the target object is a new +CaTissue::SpecimenCollectionGroup+,
|
10
|
+
# then the migrator must build that SCG's required +CollectionProtocolRegistration+. The CPR in
|
11
|
+
# turn must either exist in the database or the migrator must build the required CPR
|
12
|
+
# +participant+ and +collection_protocol+.
|
13
|
+
#
|
14
|
+
# @option (see Jinx::Migrator#initialize)
|
15
|
+
# @option opts [Database] :database the target application database
|
16
|
+
# @see #migrate_to_database
|
17
|
+
def initialize(opts={})
|
18
|
+
super
|
19
|
+
@database = opts[:database]
|
20
|
+
end
|
21
|
+
|
22
|
+
# Imports this migrator's file into the database with the given connect options.
|
23
|
+
# This method creates or updates the domain objects mapped from the migration source.
|
24
|
+
# If a block is given to this method, then the block is called on each migrated
|
25
|
+
# target object.
|
26
|
+
#
|
27
|
+
# The target object is saved in the database. Every referenced migrated object is created,
|
28
|
+
# if necessary. Finally, a migration target owner object is created, if necessary.
|
29
|
+
#
|
30
|
+
# For example, suppose a migration configuration specifies the following:
|
31
|
+
# * the target is a +CaTissue::SpecimenCollectionGroup+
|
32
|
+
# * the field mapping specifies a +Participant+ MRN,
|
33
|
+
# * the defaults specify a +CollectionProtocol+ title and a +Site+ name
|
34
|
+
#
|
35
|
+
# The migrator attempts to fetch the protocol and site from the database. If they do not
|
36
|
+
# exist, then they are created. In order to create the protocol and site, the migration
|
37
|
+
# configuration must specify sufficient information to validate the objects before creation,
|
38
|
+
# as described in {#initialize}. Finally, the SCG +CollectionProtocolRegistration+ owner
|
39
|
+
# is created. This CPR references the migration protocol and site.
|
40
|
+
#
|
41
|
+
# If the +:create+ option is set, then an input record for a target object which already
|
42
|
+
# exists in the database is noted in a debug log message and ignored rather than updated.
|
43
|
+
#
|
44
|
+
# @yield [target, row] operates on the migration target
|
45
|
+
# @yieldparam [Resource] target the migrated target domain object
|
46
|
+
# @yieldparam [{Symbol => Object}] row the migration source record
|
47
|
+
def migrate_to_database(&block)
|
48
|
+
# migrate with save
|
49
|
+
tm = Jinx::Stopwatch.measure { execute_save(&block) }.elapsed
|
50
|
+
logger.debug { format_migration_time_log_message(tm) }
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# {#migrate} with a {#save} block on the migration target. Each migrated object
|
56
|
+
# is created, if necessary, after the target save.
|
57
|
+
def execute_save
|
58
|
+
if @database.nil? then
|
59
|
+
raise MigrationError.new("Migrator cannot save records since the database option was not specified.")
|
60
|
+
end
|
61
|
+
@database.open do |db|
|
62
|
+
migrate do |tgt, rec|
|
63
|
+
# Save the target object.
|
64
|
+
save(tgt, db)
|
65
|
+
# Ensure that each migrated object is created if necessary.
|
66
|
+
@migrated.each { |obj| create(obj, db) unless db.exists?(obj) }
|
67
|
+
yield(tgt, rec) if block_given?
|
68
|
+
db.clear
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# @param [Resource] obj the domain object to save in the database
|
74
|
+
# @return [Resource, nil] obj if the save is successful, nil otherwise
|
75
|
+
def save(obj, database)
|
76
|
+
if @create then
|
77
|
+
create(obj, database)
|
78
|
+
else
|
79
|
+
logger.debug { "Migrator saving #{obj}..." }
|
80
|
+
database.save(obj)
|
81
|
+
logger.debug { "Migrator saved #{obj}." }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param [Resource] obj the domain object to create in the database
|
86
|
+
# @return [Resource, nil] obj if the create is successful, nil otherwise
|
87
|
+
def create(obj, database)
|
88
|
+
logger.debug { "Migrator creating #{obj}..." }
|
89
|
+
database.create(obj)
|
90
|
+
logger.debug { "Migrator created #{obj}." }
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [String] a log message for the given migration time in seconds
|
94
|
+
def format_migration_time_log_message(time)
|
95
|
+
# the database execution time
|
96
|
+
dt = @database.execution_time
|
97
|
+
if time > 120 then
|
98
|
+
time /= 60
|
99
|
+
dt /= 60
|
100
|
+
unit = "minutes"
|
101
|
+
else
|
102
|
+
unit = "seconds"
|
103
|
+
end
|
104
|
+
"Migration took #{'%.2f' % time} #{unit}, of which #{'%.2f' % dt} were database operations."
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
data/lib/caruby/resource.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'jinx/resource'
|
2
|
-
require '
|
2
|
+
require 'caruby/json/serializable'
|
3
3
|
require 'caruby/migration/migratable'
|
4
4
|
require 'caruby/database/persistable'
|
5
5
|
|
@@ -18,7 +18,7 @@ module CaRuby
|
|
18
18
|
# @metadata_module = CaRuby::Metadata
|
19
19
|
# end
|
20
20
|
module Resource
|
21
|
-
include CaRuby::Migratable, CaRuby::Persistable,
|
21
|
+
include CaRuby::Migratable, CaRuby::Persistable, CaRuby::JSON::Serializable, Jinx::Resource
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
data/lib/caruby/version.rb
CHANGED
data/lib/caruby.rb
CHANGED
@@ -12,8 +12,6 @@ class CacheTest < Test::Unit::TestCase
|
|
12
12
|
b = Item.new(:a)
|
13
13
|
assert_equal(a, cache[b], "Cached equivalent not found")
|
14
14
|
assert_equal(a, cache.add(b), "Cached add replaced existing entry")
|
15
|
-
cache.add!(b)
|
16
|
-
assert_equal(b, cache.add(b), "Cached add! did not replace existing entry")
|
17
15
|
end
|
18
16
|
|
19
17
|
def test_add!
|
@@ -22,7 +20,7 @@ class CacheTest < Test::Unit::TestCase
|
|
22
20
|
cache.add(a)
|
23
21
|
b = Item.new(:a)
|
24
22
|
cache.add!(b)
|
25
|
-
assert_equal(b, cache
|
23
|
+
assert_equal(b, cache[a], "Cached add! did not replace existing entry")
|
26
24
|
end
|
27
25
|
|
28
26
|
def test_clear
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: caruby-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 2.1.
|
5
|
+
version: 2.1.2
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- OHSU
|
@@ -10,8 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-
|
14
|
-
default_executable:
|
13
|
+
date: 2012-06-12 00:00:00 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: bundler
|
@@ -111,7 +110,6 @@ extra_rdoc_files: []
|
|
111
110
|
|
112
111
|
files:
|
113
112
|
- lib/caruby.rb
|
114
|
-
- lib/caruby/caruby-src.tar.gz
|
115
113
|
- lib/caruby/database.rb
|
116
114
|
- lib/caruby/metadata.rb
|
117
115
|
- lib/caruby/resource.rb
|
@@ -141,13 +139,13 @@ files:
|
|
141
139
|
- lib/caruby/helpers/properties.rb
|
142
140
|
- lib/caruby/helpers/roman.rb
|
143
141
|
- lib/caruby/helpers/version.rb
|
144
|
-
- lib/caruby/json/
|
145
|
-
- lib/caruby/json/serializer.rb
|
142
|
+
- lib/caruby/json/serializable.rb
|
146
143
|
- lib/caruby/metadata/java_property.rb
|
147
144
|
- lib/caruby/metadata/propertied.rb
|
148
145
|
- lib/caruby/metadata/property.rb
|
149
146
|
- lib/caruby/metadata/property_characteristics.rb
|
150
147
|
- lib/caruby/migration/migratable.rb
|
148
|
+
- lib/caruby/migration/migrator.rb
|
151
149
|
- lib/caruby/rdbi/driver/jdbc.rb
|
152
150
|
- History.md
|
153
151
|
- LEGAL
|
@@ -161,7 +159,6 @@ files:
|
|
161
159
|
- test/lib/caruby/helpers/properties_test.rb
|
162
160
|
- test/lib/caruby/helpers/roman_test.rb
|
163
161
|
- test/lib/caruby/helpers/version_test.rb
|
164
|
-
has_rdoc: yard
|
165
162
|
homepage: http://caruby.rubyforge.org
|
166
163
|
licenses:
|
167
164
|
- MIT
|
@@ -185,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
182
|
requirements: []
|
186
183
|
|
187
184
|
rubyforge_project: caruby
|
188
|
-
rubygems_version: 1.
|
185
|
+
rubygems_version: 1.8.15
|
189
186
|
signing_key:
|
190
187
|
specification_version: 3
|
191
188
|
summary: Ruby facade for caBIG applications.
|
@@ -197,3 +194,4 @@ test_files:
|
|
197
194
|
- test/lib/caruby/helpers/properties_test.rb
|
198
195
|
- test/lib/caruby/helpers/roman_test.rb
|
199
196
|
- test/lib/caruby/helpers/version_test.rb
|
197
|
+
has_rdoc: yard
|
Binary file
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module CaRuby
|
4
|
-
module JSON
|
5
|
-
# JSON => {Jinx::Resource} deserializer.
|
6
|
-
module Deserializer
|
7
|
-
# @param [String] json the JSON to deserialize
|
8
|
-
# @return [Jinx::Resource] the deserialized object
|
9
|
-
def json_create(json)
|
10
|
-
# Make the new object from the json data attribute => value hash.
|
11
|
-
new(json['data'])
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module CaRuby
|
2
|
-
module JSON
|
3
|
-
# {Jinx::Resource} => JSON serializer.
|
4
|
-
module Serializer
|
5
|
-
# @param args the JSON serialization options
|
6
|
-
# @return [String] the JSON representation of this {Jinx::Resource}
|
7
|
-
def to_json(*args)
|
8
|
-
database.lazy_loader.disable do
|
9
|
-
{
|
10
|
-
'json_class' => json_class_name,
|
11
|
-
'data' => json_value_hash
|
12
|
-
}.to_json(*args)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
# The JSON class name must be scoped by the Resource package module, not the
|
19
|
-
# Java package, in order to recognize the Jinx::Resource JSON hooks.
|
20
|
-
#
|
21
|
-
# @return [String] the class name qualified by the Resource package module name context
|
22
|
-
def json_class_name
|
23
|
-
[self.class.domain_module, self.class.name.demodulize].join('::')
|
24
|
-
end
|
25
|
-
|
26
|
-
# Builds a serializable attribute => value hash. An independent or owner attribute
|
27
|
-
# value is a copy of the referenced domain object consisting of only the key attributes.
|
28
|
-
#
|
29
|
-
# @return [{Symbol => Object}] the serializable value hash
|
30
|
-
def json_value_hash
|
31
|
-
vh = value_hash(self.class.nondomain_attributes)
|
32
|
-
vh.merge!(value_hash(self.class.dependent_attributes))
|
33
|
-
self.class.independent_attributes.each do |oa|
|
34
|
-
value = send(oa) || next
|
35
|
-
vh[oa] = owner.copy(owner.class.all_key_attributes)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def json_independent_reference(ref)
|
40
|
-
return ref.map { |item| json_independent_reference(item) } if ref.collection?
|
41
|
-
ref.copy(json_foreign_key_value_hash(ref))
|
42
|
-
end
|
43
|
-
|
44
|
-
def json_foreign_key_value_hash(ref)
|
45
|
-
json_key_value_hash(ref, ref.class.primary_key_attributes) or
|
46
|
-
json_key_value_hash(ref, ref.class.secondary_key_attributes) or
|
47
|
-
json_key_value_hash(ref, ref.class.alternate_key_attributes)
|
48
|
-
Hash::EMPTY_HASH
|
49
|
-
end
|
50
|
-
|
51
|
-
def json_key_value_hash(ref, attributes)
|
52
|
-
attributes.to_compact_hash { |ka| json_foreign_key_value(ref, ka) || return }
|
53
|
-
end
|
54
|
-
|
55
|
-
def json_foreign_key_value(ref, attribute)
|
56
|
-
value = ref.send(attribute) || return
|
57
|
-
Jinx::Resource === value ? json_foreign_key_value_hash(value) : value
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
module Enumerable
|
64
|
-
# @param args the JSON serialization options
|
65
|
-
# @return [String] the JSON representation of this Enumerable as an array
|
66
|
-
def to_json(*args)
|
67
|
-
to_a.to_json(*args)
|
68
|
-
end
|
69
|
-
end
|