forest_liana 8.0.17 → 8.1.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/app/deserializers/forest_liana/resource_deserializer.rb +6 -1
- data/app/helpers/forest_liana/query_helper.rb +22 -5
- data/app/serializers/forest_liana/serializer_factory.rb +17 -1
- data/app/services/forest_liana/apimap_sorter.rb +1 -0
- data/app/services/forest_liana/base_getter.rb +13 -6
- data/app/services/forest_liana/belongs_to_updater.rb +10 -1
- data/app/services/forest_liana/has_many_getter.rb +14 -8
- data/app/services/forest_liana/schema_adapter.rb +37 -1
- data/app/services/forest_liana/schema_utils.rb +26 -3
- data/lib/forest_liana/bootstrapper.rb +6 -1
- data/lib/forest_liana/schema_file_updater.rb +1 -0
- data/lib/forest_liana/version.rb +1 -1
- data/lib/tasks/send_apimap.rake +1 -1
- data/spec/dummy/app/models/address.rb +5 -0
- data/spec/dummy/app/models/user.rb +1 -0
- data/spec/dummy/db/migrate/20231117084236_create_addresses.rb +12 -0
- data/spec/dummy/db/schema.rb +12 -1
- data/spec/helpers/forest_liana/query_helper_spec.rb +25 -1
- data/spec/lib/forest_liana/bootstrapper_spec.rb +1 -0
- data/spec/lib/forest_liana/schema_file_updater_spec.rb +35 -0
- data/spec/requests/resources_spec.rb +84 -0
- data/spec/services/forest_liana/schema_adapter_spec.rb +58 -0
- data/spec/spec_helper.rb +2 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e051d1446dd0f16749a9d078bb0caee6ff1b93c37557b5fdc0571fca710137f8
|
4
|
+
data.tar.gz: 90db1924c8d20ef02b3525eb84bba26ed03025fe042b4c6405d83ebaf3ac2e23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87d40012a5f767ebc6faf75c5cb9826d50afc536837daad7f578f85ecf8b6e4c82f20d2c4eb246a4a3197e7e8d0ef6ad294362dccd5100b1194ce3897fda8044
|
7
|
+
data.tar.gz: 3d24e8527ae65ec0945ebd309a4958257ee4b12792d78f41e72427baea073333f4630756dc48254fef347ad467976a5bddeddf85d823432c94f34a4f8e465eb5
|
@@ -63,7 +63,12 @@ module ForestLiana
|
|
63
63
|
# ActionController::Parameters do not inherit from Hash anymore
|
64
64
|
# since Rails 5.
|
65
65
|
if (data.is_a?(Hash) || data.is_a?(ActionController::Parameters)) && data[:id]
|
66
|
-
|
66
|
+
if (SchemaUtils.polymorphic?(association))
|
67
|
+
@attributes[association.foreign_key] = data[:id]
|
68
|
+
@attributes[association.foreign_type] = data[:type]
|
69
|
+
else
|
70
|
+
@attributes[name] = association.klass.find(data[:id])
|
71
|
+
end
|
67
72
|
elsif data.blank?
|
68
73
|
@attributes[name] = nil
|
69
74
|
end
|
@@ -1,8 +1,16 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
module QueryHelper
|
3
3
|
def self.get_one_associations(resource)
|
4
|
-
SchemaUtils.one_associations(resource)
|
5
|
-
.select
|
4
|
+
associations = SchemaUtils.one_associations(resource)
|
5
|
+
.select do |association|
|
6
|
+
if SchemaUtils.polymorphic?(association)
|
7
|
+
SchemaUtils.polymorphic_models(association).all? { |model| SchemaUtils.model_included?(model) }
|
8
|
+
else
|
9
|
+
SchemaUtils.model_included?(association.klass)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
associations
|
6
14
|
end
|
7
15
|
|
8
16
|
def self.get_one_association_names_symbol(resource)
|
@@ -18,10 +26,19 @@ module ForestLiana
|
|
18
26
|
associations_has_one = self.get_one_associations(resource)
|
19
27
|
|
20
28
|
associations_has_one.each do |association|
|
21
|
-
if
|
22
|
-
|
29
|
+
if SchemaUtils.polymorphic?(association)
|
30
|
+
SchemaUtils.polymorphic_models(association).each do |model|
|
31
|
+
if tables_associated_to_relations_name[model.table_name].nil?
|
32
|
+
tables_associated_to_relations_name[model.table_name] = []
|
33
|
+
end
|
34
|
+
tables_associated_to_relations_name[model.table_name] << association.name
|
35
|
+
end
|
36
|
+
else
|
37
|
+
if tables_associated_to_relations_name[association.try(:table_name)].nil?
|
38
|
+
tables_associated_to_relations_name[association.table_name] = []
|
39
|
+
end
|
40
|
+
tables_associated_to_relations_name[association.table_name] << association.name
|
23
41
|
end
|
24
|
-
tables_associated_to_relations_name[association.table_name] << association.name
|
25
42
|
end
|
26
43
|
|
27
44
|
tables_associated_to_relations_name
|
@@ -265,7 +265,19 @@ module ForestLiana
|
|
265
265
|
|
266
266
|
SchemaUtils.associations(active_record_class).each do |a|
|
267
267
|
begin
|
268
|
-
if SchemaUtils.
|
268
|
+
if SchemaUtils.polymorphic?(a)
|
269
|
+
serializer.send(serializer_association(a), a.name) {
|
270
|
+
if [:has_one, :belongs_to].include?(a.macro)
|
271
|
+
begin
|
272
|
+
object.send(a.name)
|
273
|
+
rescue ActiveRecord::RecordNotFound
|
274
|
+
nil
|
275
|
+
end
|
276
|
+
else
|
277
|
+
[]
|
278
|
+
end
|
279
|
+
}
|
280
|
+
elsif SchemaUtils.model_included?(a.klass)
|
269
281
|
serializer.send(serializer_association(a), a.name) {
|
270
282
|
if [:has_one, :belongs_to].include?(a.macro)
|
271
283
|
begin
|
@@ -369,6 +381,7 @@ module ForestLiana
|
|
369
381
|
|
370
382
|
def attributes(active_record_class)
|
371
383
|
return [] if @is_smart_collection
|
384
|
+
|
372
385
|
active_record_class.column_names.select do |column_name|
|
373
386
|
!association?(active_record_class, column_name)
|
374
387
|
end
|
@@ -410,6 +423,9 @@ module ForestLiana
|
|
410
423
|
def foreign_keys(active_record_class)
|
411
424
|
begin
|
412
425
|
SchemaUtils.belongs_to_associations(active_record_class).map(&:foreign_key)
|
426
|
+
SchemaUtils.belongs_to_associations(active_record_class)
|
427
|
+
.select { |association| !SchemaUtils.polymorphic?(association) }
|
428
|
+
.map(&:foreign_key)
|
413
429
|
rescue => err
|
414
430
|
# Association foreign_key triggers an error. Put the stacktrace and
|
415
431
|
# returns no foreign keys.
|
@@ -33,16 +33,23 @@ module ForestLiana
|
|
33
33
|
def optimize_record_loading(resource, records)
|
34
34
|
instance_dependent_associations = instance_dependent_associations(resource)
|
35
35
|
|
36
|
+
polymorphic = []
|
36
37
|
preload_loads = @includes.select do |name|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
association = resource.reflect_on_association(name)
|
39
|
+
if SchemaUtils.polymorphic?(association)
|
40
|
+
polymorphic << association.name
|
41
|
+
false
|
42
|
+
else
|
43
|
+
targetModelConnection = association.klass.connection
|
44
|
+
targetModelDatabase = targetModelConnection.current_database if targetModelConnection.respond_to? :current_database
|
45
|
+
resourceConnection = resource.connection
|
46
|
+
resourceDatabase = resourceConnection.current_database if resourceConnection.respond_to? :current_database
|
41
47
|
|
42
|
-
|
48
|
+
targetModelDatabase != resourceDatabase
|
49
|
+
end
|
43
50
|
end + instance_dependent_associations
|
44
51
|
|
45
|
-
result = records.eager_load(@includes - preload_loads)
|
52
|
+
result = records.eager_load(@includes - preload_loads - polymorphic)
|
46
53
|
|
47
54
|
# Rails 7 can mix `eager_load` and `preload` in the same scope
|
48
55
|
# Rails 6 cannot mix `eager_load` and `preload` in the same scope
|
@@ -13,7 +13,16 @@ module ForestLiana
|
|
13
13
|
def perform
|
14
14
|
begin
|
15
15
|
@record = @resource.find(@params[:id])
|
16
|
-
|
16
|
+
if (SchemaUtils.polymorphic?(@association))
|
17
|
+
if @data.nil?
|
18
|
+
new_value = nil
|
19
|
+
else
|
20
|
+
association_klass = SchemaUtils.polymorphic_models(@association).select { |a| a.name.downcase == @data[:type] }.first
|
21
|
+
new_value = association_klass.find(@data[:id]) if @data && @data[:id]
|
22
|
+
end
|
23
|
+
else
|
24
|
+
new_value = @association.klass.find(@data[:id]) if @data && @data[:id]
|
25
|
+
end
|
17
26
|
@record.send("#{@association.name}=", new_value)
|
18
27
|
|
19
28
|
@record.save
|
@@ -40,17 +40,23 @@ module ForestLiana
|
|
40
40
|
@includes = @association.klass
|
41
41
|
.reflect_on_all_associations
|
42
42
|
.select do |association|
|
43
|
-
inclusion = !association.options[:polymorphic] &&
|
44
|
-
SchemaUtils.model_included?(association.klass) &&
|
45
|
-
[:belongs_to, :has_and_belongs_to_many].include?(association.macro)
|
46
43
|
|
47
|
-
if
|
48
|
-
inclusion
|
44
|
+
if SchemaUtils.polymorphic?(association)
|
45
|
+
inclusion = SchemaUtils.polymorphic_models(association)
|
46
|
+
.all? { |model| SchemaUtils.model_included?(model) } &&
|
47
|
+
[:belongs_to, :has_and_belongs_to_many].include?(association.macro)
|
49
48
|
else
|
50
|
-
inclusion
|
49
|
+
inclusion = SchemaUtils.model_included?(association.klass) &&
|
50
|
+
[:belongs_to, :has_and_belongs_to_many].include?(association.macro)
|
51
51
|
end
|
52
|
-
|
53
|
-
|
52
|
+
|
53
|
+
if @field_names_requested
|
54
|
+
inclusion && @field_names_requested.include?(association.name)
|
55
|
+
else
|
56
|
+
inclusion
|
57
|
+
end
|
58
|
+
end
|
59
|
+
.map { |association| association.name }
|
54
60
|
end
|
55
61
|
|
56
62
|
def field_names_requested
|
@@ -241,8 +241,33 @@ module ForestLiana
|
|
241
241
|
def add_associations
|
242
242
|
SchemaUtils.associations(@model).each do |association|
|
243
243
|
begin
|
244
|
+
if SchemaUtils.polymorphic?(association) &&
|
245
|
+
(ENV['ENABLE_SUPPORT_POLYMORPHISM'].present? && ENV['ENABLE_SUPPORT_POLYMORPHISM'].downcase == 'true')
|
246
|
+
|
247
|
+
collection.fields << {
|
248
|
+
field: association.name.to_s,
|
249
|
+
type: get_type_for_association(association),
|
250
|
+
relationship: get_relationship_type(association),
|
251
|
+
reference: "#{association.name.to_s}.id",
|
252
|
+
inverse_of: @model.name.demodulize.underscore,
|
253
|
+
is_filterable: false,
|
254
|
+
is_sortable: true,
|
255
|
+
is_read_only: false,
|
256
|
+
is_required: false,
|
257
|
+
is_virtual: false,
|
258
|
+
default_value: nil,
|
259
|
+
integration: nil,
|
260
|
+
relationships: nil,
|
261
|
+
widget: nil,
|
262
|
+
validations: [],
|
263
|
+
polymorphic_referenced_models: get_polymorphic_types(association)
|
264
|
+
}
|
265
|
+
|
266
|
+
collection.fields = collection.fields.reject do |field|
|
267
|
+
field[:field] == association.foreign_key || field[:field] == association.foreign_type
|
268
|
+
end
|
244
269
|
# NOTICE: Delete the association if the targeted model is excluded.
|
245
|
-
|
270
|
+
elsif !SchemaUtils.model_included?(association.klass)
|
246
271
|
field = collection.fields.find do |x|
|
247
272
|
x[:field] == association.foreign_key
|
248
273
|
end
|
@@ -275,6 +300,17 @@ module ForestLiana
|
|
275
300
|
automatic_inverse_of(association)
|
276
301
|
end
|
277
302
|
|
303
|
+
def get_polymorphic_types(relation)
|
304
|
+
types = []
|
305
|
+
ForestLiana.models.each do |model|
|
306
|
+
unless model.reflect_on_all_associations.select { |association| association.options[:as] == relation.name.to_sym }.empty?
|
307
|
+
types << model.name
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
types
|
312
|
+
end
|
313
|
+
|
278
314
|
def automatic_inverse_of(association)
|
279
315
|
name = association.active_record.name.demodulize.underscore
|
280
316
|
|
@@ -4,7 +4,12 @@ module ForestLiana
|
|
4
4
|
def self.associations(active_record_class)
|
5
5
|
active_record_class.reflect_on_all_associations.select do |association|
|
6
6
|
begin
|
7
|
-
|
7
|
+
if (ENV['ENABLE_SUPPORT_POLYMORPHISM'].present? && ENV['ENABLE_SUPPORT_POLYMORPHISM'].downcase == 'true')
|
8
|
+
polymorphic?(association) ? true : !is_active_type?(association.klass)
|
9
|
+
else
|
10
|
+
!polymorphic?(association) && !is_active_type?(association.klass)
|
11
|
+
end
|
12
|
+
|
8
13
|
rescue
|
9
14
|
FOREST_LOGGER.warn "Unknown association #{association.name} on class #{active_record_class.name}"
|
10
15
|
false
|
@@ -53,12 +58,30 @@ module ForestLiana
|
|
53
58
|
ActiveRecord::Base.connection.tables
|
54
59
|
end
|
55
60
|
|
56
|
-
private
|
57
|
-
|
58
61
|
def self.polymorphic?(association)
|
59
62
|
association.options[:polymorphic]
|
60
63
|
end
|
61
64
|
|
65
|
+
def self.klass(association)
|
66
|
+
return association.klass unless polymorphic?(association)
|
67
|
+
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.polymorphic_models(relation)
|
72
|
+
models = []
|
73
|
+
ForestLiana.models.each do |model|
|
74
|
+
unless model.reflect_on_all_associations.select { |association| association.options[:as] == relation.name.to_sym }.empty?
|
75
|
+
models << model
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
models
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
private
|
84
|
+
|
62
85
|
def self.find_model_from_abstract_class(abstract_class, collection_name)
|
63
86
|
abstract_class.subclasses.find do |subclass|
|
64
87
|
if subclass.abstract_class?
|
@@ -5,7 +5,12 @@ module ForestLiana
|
|
5
5
|
class Bootstrapper
|
6
6
|
SCHEMA_FILENAME = File.join(Dir.pwd, '.forestadmin-schema.json')
|
7
7
|
|
8
|
-
def initialize
|
8
|
+
def initialize(reset_api_map = false)
|
9
|
+
if reset_api_map
|
10
|
+
ForestLiana.apimap = []
|
11
|
+
ForestLiana.models = []
|
12
|
+
end
|
13
|
+
|
9
14
|
@integration_stripe_valid = false
|
10
15
|
@integration_intercom_valid = false
|
11
16
|
|
data/lib/forest_liana/version.rb
CHANGED
data/lib/tasks/send_apimap.rake
CHANGED
@@ -3,7 +3,7 @@ namespace :forest do
|
|
3
3
|
task(:send_apimap).clear
|
4
4
|
task send_apimap: :environment do
|
5
5
|
if ForestLiana.env_secret
|
6
|
-
bootstrapper = ForestLiana::Bootstrapper.new
|
6
|
+
bootstrapper = ForestLiana::Bootstrapper.new(true)
|
7
7
|
bootstrapper.synchronize(true)
|
8
8
|
else
|
9
9
|
puts 'Cannot send the Apimap, Forest cannot find your env_secret'
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -10,7 +10,18 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 2023_11_17_084236) do
|
14
|
+
|
15
|
+
create_table "addresses", force: :cascade do |t|
|
16
|
+
t.string "line1"
|
17
|
+
t.string "city"
|
18
|
+
t.string "zipcode"
|
19
|
+
t.string "addressable_type", null: false
|
20
|
+
t.integer "addressable_id", null: false
|
21
|
+
t.datetime "created_at", precision: 6, null: false
|
22
|
+
t.datetime "updated_at", precision: 6, null: false
|
23
|
+
t.index ["addressable_type", "addressable_id"], name: "index_addresses_on_addressable_type_and_addressable_id"
|
24
|
+
end
|
14
25
|
|
15
26
|
create_table "isle", force: :cascade do |t|
|
16
27
|
t.string "name"
|
@@ -3,6 +3,7 @@ module ForestLiana
|
|
3
3
|
before(:all) do
|
4
4
|
Tree.connection
|
5
5
|
User.connection
|
6
|
+
Address.connection
|
6
7
|
Island.connection
|
7
8
|
end
|
8
9
|
|
@@ -14,6 +15,21 @@ module ForestLiana
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
18
|
+
context 'on a model having 1 polymorphic association' do
|
19
|
+
it 'should return the association' do
|
20
|
+
associations = QueryHelper.get_one_associations(Address)
|
21
|
+
expect(associations).to eq(Address.reflect_on_all_associations(:belongs_to))
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should return 0 association when one of referenced model was excluded' do
|
25
|
+
allow(ForestLiana).to receive(:excluded_models).and_return(['User'])
|
26
|
+
associations = QueryHelper.get_one_associations(Address)
|
27
|
+
|
28
|
+
expect(associations.length).to eq(0)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
17
33
|
context 'on a model having some belongsTo associations' do
|
18
34
|
let(:expected_association_attributes) do
|
19
35
|
[
|
@@ -75,7 +91,15 @@ module ForestLiana
|
|
75
91
|
expect(tables_associated_to_relations_name['isle'].second).to eq(:eponymous_island)
|
76
92
|
end
|
77
93
|
end
|
78
|
-
end
|
79
94
|
|
95
|
+
context 'on a model having polymorphic association' do
|
96
|
+
tables_associated_to_relations_name =
|
97
|
+
QueryHelper.get_tables_associated_to_relations_name(Address)
|
98
|
+
|
99
|
+
it 'should return the one-one associations' do
|
100
|
+
expect(tables_associated_to_relations_name.keys.length).to eq(1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
80
104
|
end
|
81
105
|
end
|
@@ -10,6 +10,41 @@ module ForestLiana
|
|
10
10
|
end
|
11
11
|
|
12
12
|
describe "with a given collection" do
|
13
|
+
describe "when the collection has a polymorphic relation" do
|
14
|
+
it "should save the relation" do
|
15
|
+
collections = [
|
16
|
+
{
|
17
|
+
"name" => "Address",
|
18
|
+
"fields" => [
|
19
|
+
{
|
20
|
+
"field" => "addressable",
|
21
|
+
"type" => "Number",
|
22
|
+
"relationship" => "BelongsTo",
|
23
|
+
"reference" => "addressable.id",
|
24
|
+
"inverse_of" => "address",
|
25
|
+
"is_filterable" => false,
|
26
|
+
"is_sortable" => true,
|
27
|
+
"is_read_only" => false,
|
28
|
+
"is_required" => false,
|
29
|
+
"is_virtual" => false,
|
30
|
+
"default_value" => nil,
|
31
|
+
"integration" => nil,
|
32
|
+
"relationships" => nil,
|
33
|
+
"widget" => nil,
|
34
|
+
"validations" => [],
|
35
|
+
"polymorphic_referenced_models" => ["User"]
|
36
|
+
},
|
37
|
+
],
|
38
|
+
"actions" => [],
|
39
|
+
"segments" => []
|
40
|
+
}
|
41
|
+
]
|
42
|
+
schema_file_updater = ForestLiana::SchemaFileUpdater.new("test.txt", collections, {})
|
43
|
+
expect(schema_file_updater.instance_variable_get(:@collections))
|
44
|
+
.to eq(collections)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
13
48
|
describe "when the collection has a smart action action" do
|
14
49
|
it "should save the smart action" do
|
15
50
|
collections = [{
|
@@ -154,3 +154,87 @@ describe 'Requesting Tree resources', :type => :request do
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end
|
157
|
+
|
158
|
+
describe 'Requesting Address resources', :type => :request do
|
159
|
+
|
160
|
+
before do
|
161
|
+
user = User.create(name: 'Michel')
|
162
|
+
address = Address.create(line1: '10 Downing Street', city: 'London', zipcode: '2AB', addressable: user)
|
163
|
+
|
164
|
+
Rails.cache.write('forest.users', {'1' => { 'id' => 1, 'roleId' => 1, 'rendering_id' => '1' }})
|
165
|
+
Rails.cache.write('forest.has_permission', true)
|
166
|
+
Rails.cache.write(
|
167
|
+
'forest.collections',
|
168
|
+
{
|
169
|
+
'Address' => {
|
170
|
+
'browse' => [1],
|
171
|
+
'read' => [1],
|
172
|
+
'edit' => [1],
|
173
|
+
'add' => [1],
|
174
|
+
'delete' => [1],
|
175
|
+
'export' => [1],
|
176
|
+
'actions' => {}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
)
|
180
|
+
|
181
|
+
allow(ForestLiana::IpWhitelist).to receive(:retrieve) { true }
|
182
|
+
allow(ForestLiana::IpWhitelist).to receive(:is_ip_whitelist_retrieved) { true }
|
183
|
+
allow(ForestLiana::IpWhitelist).to receive(:is_ip_valid) { true }
|
184
|
+
allow(ForestLiana::ScopeManager).to receive(:fetch_scopes).and_return({})
|
185
|
+
end
|
186
|
+
|
187
|
+
after do
|
188
|
+
User.destroy_all
|
189
|
+
Address.destroy_all
|
190
|
+
end
|
191
|
+
|
192
|
+
token = JWT.encode({
|
193
|
+
id: 1,
|
194
|
+
email: 'michael.kelso@that70.show',
|
195
|
+
first_name: 'Michael',
|
196
|
+
last_name: 'Kelso',
|
197
|
+
team: 'Operations',
|
198
|
+
rendering_id: 16,
|
199
|
+
exp: Time.now.to_i + 2.weeks.to_i,
|
200
|
+
permission_level: 'admin'
|
201
|
+
}, ForestLiana.auth_secret, 'HS256')
|
202
|
+
|
203
|
+
headers = {
|
204
|
+
'Accept' => 'application/json',
|
205
|
+
'Content-Type' => 'application/json',
|
206
|
+
'Authorization' => "Bearer #{token}"
|
207
|
+
}
|
208
|
+
|
209
|
+
describe 'index' do
|
210
|
+
params = {
|
211
|
+
fields: { 'Address' => 'id,line1,city,zip_code,addressable' },
|
212
|
+
page: { 'number' => '1', 'size' => '10' },
|
213
|
+
searchExtended: '0',
|
214
|
+
sort: '-id',
|
215
|
+
timezone: 'Europe/Paris'
|
216
|
+
}
|
217
|
+
|
218
|
+
it 'should respond the address data' do
|
219
|
+
get '/forest/Address', params: params, headers: headers
|
220
|
+
|
221
|
+
expect(JSON.parse(response.body)).to include(
|
222
|
+
"data" => [
|
223
|
+
{
|
224
|
+
"type" => "Address",
|
225
|
+
"id" => "1",
|
226
|
+
"attributes" => {
|
227
|
+
"id" => 1,
|
228
|
+
"line1" => "10 Downing Street",
|
229
|
+
"city" => "London"
|
230
|
+
},
|
231
|
+
"links" => { "self" => "/forest/address/1" },
|
232
|
+
"relationships" => {
|
233
|
+
"addressable" => { "links" => { "related" => {} }, "data" => { "type" => "User", "id" => "1" } }
|
234
|
+
}
|
235
|
+
}
|
236
|
+
]
|
237
|
+
)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -1,6 +1,64 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
describe SchemaAdapter do
|
3
3
|
describe 'perform' do
|
4
|
+
context 'with polymorphic association' do
|
5
|
+
it 'should define the association with the referenced models' do
|
6
|
+
collection = ForestLiana.apimap.find do |object|
|
7
|
+
object.name.to_s == ForestLiana.name_for(Address)
|
8
|
+
end
|
9
|
+
field = collection.fields.find { |field| field[:field] == 'addressable' }
|
10
|
+
|
11
|
+
expect(field).to eq(
|
12
|
+
{
|
13
|
+
field: "addressable",
|
14
|
+
type: "Number",
|
15
|
+
relationship: "BelongsTo",
|
16
|
+
reference: "addressable.id",
|
17
|
+
inverse_of: "address",
|
18
|
+
is_filterable: false,
|
19
|
+
is_sortable: true,
|
20
|
+
is_read_only: false,
|
21
|
+
is_required: false,
|
22
|
+
is_virtual: false,
|
23
|
+
default_value: nil,
|
24
|
+
integration: nil,
|
25
|
+
relationships: nil,
|
26
|
+
widget: nil,
|
27
|
+
validations: [],
|
28
|
+
polymorphic_referenced_models: ['User']
|
29
|
+
}
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should remove the polymorphic attributes(_id and _type)' do
|
34
|
+
collection = ForestLiana.apimap.find do |object|
|
35
|
+
object.name.to_s == ForestLiana.name_for(Address)
|
36
|
+
end
|
37
|
+
removed_fields = collection.fields.select do
|
38
|
+
|field| field[:field] == 'addressable_id' || field[:field] == 'addressable_type'
|
39
|
+
end
|
40
|
+
|
41
|
+
expect(removed_fields).to be_empty
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when the polymorphic support was disabled' do
|
45
|
+
it 'should not define the association' do
|
46
|
+
ENV['ENABLE_SUPPORT_POLYMORPHISM'] = 'false'
|
47
|
+
Bootstrapper.new(true)
|
48
|
+
collection = ForestLiana.apimap.find do |object|
|
49
|
+
object.name.to_s == ForestLiana.name_for(Address)
|
50
|
+
end
|
51
|
+
association = collection.fields.find { |field| field[:field] == 'addressable' }
|
52
|
+
fields = collection.fields.select do |field|
|
53
|
+
field[:field] == 'addressable_id' || field[:field] == 'addressable_type'
|
54
|
+
end
|
55
|
+
|
56
|
+
expect(association).to be_nil
|
57
|
+
expect(fields.size).to eq(2)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
4
62
|
context 'with an "unhandled" column types (binary, postgis geography, ...)' do
|
5
63
|
it 'should not define theses column in the schema' do
|
6
64
|
collection = ForestLiana.apimap.find do |object|
|
data/spec/spec_helper.rb
CHANGED
@@ -19,6 +19,8 @@ SimpleCov.add_filter ['app/services/forest_liana/ability/fetch.rb', 'lib/forest_
|
|
19
19
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
20
20
|
RSpec.configure do |config|
|
21
21
|
ENV['RAILS_ENV'] = 'test'
|
22
|
+
ENV['ENABLE_SUPPORT_POLYMORPHISM'] = 'true'
|
23
|
+
|
22
24
|
require File.expand_path('../dummy/config/environment', __FILE__)
|
23
25
|
|
24
26
|
# rspec-expectations config goes here. You can use an alternate
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_liana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 8.0
|
4
|
+
version: 8.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sandro Munda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -350,6 +350,7 @@ files:
|
|
350
350
|
- spec/dummy/app/controllers/application_controller.rb
|
351
351
|
- spec/dummy/app/controllers/forest/islands_controller.rb
|
352
352
|
- spec/dummy/app/helpers/application_helper.rb
|
353
|
+
- spec/dummy/app/models/address.rb
|
353
354
|
- spec/dummy/app/models/application_record.rb
|
354
355
|
- spec/dummy/app/models/car.rb
|
355
356
|
- spec/dummy/app/models/driver.rb
|
@@ -403,6 +404,7 @@ files:
|
|
403
404
|
- spec/dummy/db/migrate/20220719094450_create_drivers.rb
|
404
405
|
- spec/dummy/db/migrate/20220727114450_create_manufacturers.rb
|
405
406
|
- spec/dummy/db/migrate/20220727114930_add_columns_to_products.rb
|
407
|
+
- spec/dummy/db/migrate/20231117084236_create_addresses.rb
|
406
408
|
- spec/dummy/db/schema.rb
|
407
409
|
- spec/dummy/lib/forest_liana/collections/island.rb
|
408
410
|
- spec/dummy/lib/forest_liana/collections/location.rb
|
@@ -646,6 +648,7 @@ test_files:
|
|
646
648
|
- spec/dummy/app/controllers/application_controller.rb
|
647
649
|
- spec/dummy/app/controllers/forest/islands_controller.rb
|
648
650
|
- spec/dummy/app/helpers/application_helper.rb
|
651
|
+
- spec/dummy/app/models/address.rb
|
649
652
|
- spec/dummy/app/models/application_record.rb
|
650
653
|
- spec/dummy/app/models/car.rb
|
651
654
|
- spec/dummy/app/models/driver.rb
|
@@ -699,6 +702,7 @@ test_files:
|
|
699
702
|
- spec/dummy/db/migrate/20220719094450_create_drivers.rb
|
700
703
|
- spec/dummy/db/migrate/20220727114450_create_manufacturers.rb
|
701
704
|
- spec/dummy/db/migrate/20220727114930_add_columns_to_products.rb
|
705
|
+
- spec/dummy/db/migrate/20231117084236_create_addresses.rb
|
702
706
|
- spec/dummy/db/schema.rb
|
703
707
|
- spec/dummy/lib/forest_liana/collections/island.rb
|
704
708
|
- spec/dummy/lib/forest_liana/collections/location.rb
|