forest_admin_datasource_active_record 1.0.0.pre.beta.60 → 1.0.0.pre.beta.62

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: 06eb4e50d70ed020e78c247129d24f1a514efcc8e3150864ac00e2a420d715ed
4
- data.tar.gz: e11b2afab09fbf5ac3e9555a288f70638e2c01e5d2135a983b8601324d701916
3
+ metadata.gz: 768aba915cd8fc48929a8bdc08fdf81dd735aa9b6d8d7f2a7f2ecb4c99c4e854
4
+ data.tar.gz: 32a0e8e3b7468dd6ec2244ea1b59da6383af8f36f48b4c5d7025094550612eca
5
5
  SHA512:
6
- metadata.gz: 895ce913914b2400d39f09b197ef29e25524bcd524e75749a206cb5be6797665f026eac1ab0f99bceff4b11d9546c56edd3e92155c90a68434705faba6b411ec
7
- data.tar.gz: 5afa4e3d45800cce7d9f1a274eba8ccaf78d5c473460e1ccc56dada1064319d7e5d4b1a81b53ccadf293a64f61a1d607021665c6fdee7d95f1f143af4051d29f
6
+ metadata.gz: 7cea2e22bccfce7e48423cce3656b9457cea8882721bb6f39dc6ca44b7edc8fefcb9f0b8bde0226f33fa3ae5dcaae0b5d23113eeb92e6ef9e71793d70c427fb1
7
+ data.tar.gz: 7a015c989b6183d4a97c8d95f1f614b7a6fa58d64e2a498072e246218e6398040e22ec7098bc260ee8cc045119adf8155a64063cad007ad5f0c8ee93869979e6
@@ -6,9 +6,10 @@ module ForestAdminDatasourceActiveRecord
6
6
 
7
7
  attr_reader :model
8
8
 
9
- def initialize(datasource, model)
9
+ def initialize(datasource, model, support_polymorphic_relations: false)
10
10
  @model = model
11
- name = model.name.demodulize.underscore
11
+ @support_polymorphic_relations = support_polymorphic_relations
12
+ name = format_model_name(@model.name)
12
13
  super(datasource, name)
13
14
  fetch_fields
14
15
  fetch_associations
@@ -30,12 +31,12 @@ module ForestAdminDatasourceActiveRecord
30
31
  end
31
32
 
32
33
  def create(_caller, data)
33
- Utils::ActiveRecordSerializer.new(@model.create(data)).to_hash
34
+ Utils::ActiveRecordSerializer.new(@model.create(data)).to_hash(ProjectionFactory.all(self))
34
35
  end
35
36
 
36
37
  def update(_caller, filter, data)
37
38
  entity = Utils::Query.new(self, nil, filter).build.first
38
- entity.update(data)
39
+ entity&.update(data)
39
40
  end
40
41
 
41
42
  def delete(_caller, filter)
@@ -45,6 +46,10 @@ module ForestAdminDatasourceActiveRecord
45
46
 
46
47
  private
47
48
 
49
+ def format_model_name(class_name)
50
+ class_name.gsub('::', '__')
51
+ end
52
+
48
53
  def fetch_fields
49
54
  @model.columns_hash.each do |column_name, column|
50
55
  field = ForestAdminDatasourceToolkit::Schema::ColumnSchema.new(
@@ -63,49 +68,112 @@ module ForestAdminDatasourceActiveRecord
63
68
  end
64
69
  end
65
70
 
71
+ def association_primary_key?(association)
72
+ !association.association_primary_key.empty?
73
+ rescue StandardError
74
+ association.polymorphic?
75
+ end
76
+
66
77
  def fetch_associations
67
- associations(@model).each do |association|
78
+ associations(@model, support_polymorphic_relations: @support_polymorphic_relations).each do |association|
68
79
  case association.macro
69
80
  when :has_one
70
- add_field(
71
- association.name.to_s,
72
- ForestAdminDatasourceToolkit::Schema::Relations::OneToOneSchema.new(
73
- foreign_collection: association.class_name.demodulize.underscore,
74
- origin_key: association.foreign_key,
75
- origin_key_target: association.association_primary_key
76
- )
77
- )
81
+ if association_primary_key?(association)
82
+ if association.through_reflection?
83
+ add_field(
84
+ association.name.to_s,
85
+ ForestAdminDatasourceToolkit::Schema::Relations::ManyToManySchema.new(
86
+ foreign_collection: format_model_name(association.klass.name),
87
+ origin_key: association.through_reflection.foreign_key,
88
+ origin_key_target: association.through_reflection.join_foreign_key,
89
+ foreign_key: association.join_foreign_key,
90
+ foreign_key_target: association.association_primary_key,
91
+ through_collection: format_model_name(association.through_reflection.klass.name)
92
+ )
93
+ )
94
+ elsif association.inverse_of.polymorphic?
95
+ add_field(
96
+ association.name.to_s,
97
+ ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicOneToOneSchema.new(
98
+ foreign_collection: format_model_name(association.klass.name),
99
+ origin_key: association.foreign_key,
100
+ origin_key_target: association.association_primary_key,
101
+ origin_type_field: association.inverse_of.foreign_type,
102
+ origin_type_value: @model.name
103
+ )
104
+ )
105
+ else
106
+ add_field(
107
+ association.name.to_s,
108
+ ForestAdminDatasourceToolkit::Schema::Relations::OneToOneSchema.new(
109
+ foreign_collection: format_model_name(association.klass.name),
110
+ origin_key: association.foreign_key,
111
+ origin_key_target: association.association_primary_key
112
+ )
113
+ )
114
+ end
115
+ end
78
116
  when :belongs_to
79
- add_field(
80
- association.name.to_s,
81
- ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema.new(
82
- foreign_collection: association.class_name.demodulize.underscore,
83
- foreign_key: association.foreign_key,
84
- foreign_key_target: association.association_primary_key
85
- )
86
- )
117
+ if association_primary_key?(association)
118
+ if polymorphic?(association)
119
+ foreign_collections = get_polymorphic_types(association)
120
+ add_field(
121
+ association.name.to_s,
122
+ ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicManyToOneSchema.new(
123
+ foreign_collections: foreign_collections.keys,
124
+ foreign_key: association.foreign_key,
125
+ foreign_key_type_field: association.foreign_type,
126
+ foreign_key_targets: foreign_collections
127
+ )
128
+ )
129
+ schema[:fields][association.foreign_key].is_read_only = true
130
+ schema[:fields][association.foreign_type].is_read_only = true
131
+ else
132
+ add_field(
133
+ association.name.to_s,
134
+ ForestAdminDatasourceToolkit::Schema::Relations::ManyToOneSchema.new(
135
+ foreign_collection: format_model_name(association.klass.name),
136
+ foreign_key: association.foreign_key,
137
+ foreign_key_target: association.association_primary_key
138
+ )
139
+ )
140
+ end
141
+ end
87
142
  when :has_many
88
- if association.through_reflection?
89
- add_field(
90
- association.name.to_s,
91
- ForestAdminDatasourceToolkit::Schema::Relations::ManyToManySchema.new(
92
- foreign_collection: association.class_name.demodulize.underscore,
93
- origin_key: association.through_reflection.foreign_key,
94
- origin_key_target: association.through_reflection.join_foreign_key,
95
- foreign_key: association.join_foreign_key,
96
- foreign_key_target: association.association_primary_key,
97
- through_collection: association.through_reflection.class_name.demodulize.underscore
143
+ if association_primary_key?(association)
144
+ if association.through_reflection?
145
+ add_field(
146
+ association.name.to_s,
147
+ ForestAdminDatasourceToolkit::Schema::Relations::ManyToManySchema.new(
148
+ foreign_collection: format_model_name(association.klass.name),
149
+ origin_key: association.through_reflection.foreign_key,
150
+ origin_key_target: association.through_reflection.join_foreign_key,
151
+ foreign_key: association.join_foreign_key,
152
+ foreign_key_target: association.association_primary_key,
153
+ through_collection: format_model_name(association.through_reflection.klass.name)
154
+ )
155
+ )
156
+ elsif association.inverse_of.polymorphic?
157
+ add_field(
158
+ association.name.to_s,
159
+ ForestAdminDatasourceToolkit::Schema::Relations::PolymorphicOneToManySchema.new(
160
+ foreign_collection: format_model_name(association.klass.name),
161
+ origin_key: association.foreign_key,
162
+ origin_key_target: association.association_primary_key,
163
+ origin_type_field: association.inverse_of.foreign_type,
164
+ origin_type_value: @model.name
165
+ )
98
166
  )
99
- )
100
- else
101
- add_field(
102
- association.name.to_s,
103
- ForestAdminDatasourceToolkit::Schema::Relations::OneToManySchema.new(
104
- foreign_collection: association.class_name.demodulize.underscore,
105
- origin_key: association.foreign_key,
106
- origin_key_target: association.association_primary_key
167
+ else
168
+ add_field(
169
+ association.name.to_s,
170
+ ForestAdminDatasourceToolkit::Schema::Relations::OneToManySchema.new(
171
+ foreign_collection: format_model_name(association.klass.name),
172
+ origin_key: association.foreign_key,
173
+ origin_key_target: association.association_primary_key
174
+ )
107
175
  )
108
- )
176
+ end
109
177
  end
110
178
  end
111
179
  end
@@ -2,9 +2,12 @@ require 'active_record'
2
2
 
3
3
  module ForestAdminDatasourceActiveRecord
4
4
  class Datasource < ForestAdminDatasourceToolkit::Datasource
5
- def initialize(db_config = {})
5
+ attr_reader :models
6
+
7
+ def initialize(db_config = {}, support_polymorphic_relations: false)
6
8
  super()
7
9
  @models = []
10
+ @support_polymorphic_relations = support_polymorphic_relations
8
11
  @habtm_models = {}
9
12
  init_orm(db_config)
10
13
  generate
@@ -15,15 +18,26 @@ module ForestAdminDatasourceActiveRecord
15
18
  def generate
16
19
  ActiveRecord::Base.descendants.each { |model| fetch_model(model) }
17
20
  @models.each do |model|
18
- add_collection(Collection.new(self, model))
21
+ add_collection(
22
+ Collection.new(self, model, support_polymorphic_relations: @support_polymorphic_relations)
23
+ )
19
24
  end
20
25
  end
21
26
 
27
+ def primary_key?(model)
28
+ !model.primary_key.empty?
29
+ rescue StandardError
30
+ false
31
+ end
32
+
22
33
  def fetch_model(model)
23
34
  if model.name.start_with?('HABTM_')
24
35
  build_habtm(model)
25
36
  else
26
- @models << model unless model.abstract_class? || @models.include?(model) || !model.table_exists?
37
+ @models << model unless model.abstract_class? ||
38
+ @models.include?(model) ||
39
+ !model.table_exists? ||
40
+ !primary_key?(model)
27
41
  end
28
42
  end
29
43
 
@@ -1,14 +1,19 @@
1
1
  module ForestAdminDatasourceActiveRecord
2
2
  module Parser
3
3
  module Relation
4
- def associations(model)
4
+ def associations(model, support_polymorphic_relations: false)
5
5
  model.reflect_on_all_associations.select do |association|
6
- !polymorphic?(association) && !active_type?(association.klass)
6
+ if support_polymorphic_relations
7
+ polymorphic?(association) ? true : !active_type?(association.klass)
8
+ else
9
+ !polymorphic?(association) && !active_type?(association.klass)
10
+ end
7
11
  end
8
12
  end
9
13
 
10
14
  def polymorphic?(association)
11
- association.options[:polymorphic]
15
+ (association.options.key?(:polymorphic) && association.options[:polymorphic]) ||
16
+ association.inverse_of&.polymorphic?
12
17
  end
13
18
 
14
19
  # NOTICE: Ignores ActiveType::Object association during introspection and interactions.
@@ -16,6 +21,17 @@ module ForestAdminDatasourceActiveRecord
16
21
  def active_type?(model)
17
22
  Object.const_defined?('ActiveType::Object') && model < ActiveType::Object
18
23
  end
24
+
25
+ def get_polymorphic_types(relation)
26
+ types = {}
27
+ @datasource.models.each do |model|
28
+ unless model.reflect_on_all_associations.none? { |assoc| assoc.options[:as] == relation.name.to_sym }
29
+ types[format_model_name(model.name)] = model.primary_key
30
+ end
31
+ end
32
+
33
+ types
34
+ end
19
35
  end
20
36
  end
21
37
  end
@@ -13,7 +13,7 @@ module ForestAdminDatasourceActiveRecord
13
13
  hash.merge! object.attributes
14
14
 
15
15
  if with_associations
16
- each_association_collection(object) do |association_name, item|
16
+ each_association_collection(object, projection) do |association_name, item|
17
17
  hash[association_name] = hash_object(
18
18
  item,
19
19
  projection.relations[association_name],
@@ -25,9 +25,10 @@ module ForestAdminDatasourceActiveRecord
25
25
  hash
26
26
  end
27
27
 
28
- def each_association_collection(object)
28
+ def each_association_collection(object, projection)
29
29
  one_associations = %i[has_one belongs_to]
30
- object.class.reflect_on_all_associations.filter { |a| one_associations.include?(a.macro) }
30
+ object.class.reflect_on_all_associations
31
+ .filter { |a| one_associations.include?(a.macro) && projection.relations.key?(a.name.to_s) }
31
32
  .each { |association| yield(association.name.to_s, object.send(association.name.to_s)) }
32
33
  end
33
34
  end
@@ -123,14 +123,11 @@ module ForestAdminDatasourceActiveRecord
123
123
  end
124
124
 
125
125
  def format_field(field)
126
- @select << "#{@collection.model.table_name}.#{field}"
127
-
128
126
  if field.include?(':')
129
127
  relation_name, field = field.split(':')
130
128
  relation = @collection.schema[:fields][relation_name]
131
129
  table_name = @collection.datasource.get_collection(relation.foreign_collection).model.table_name
132
130
  add_join_relation(relation_name)
133
- @select << "#{table_name}.#{field}"
134
131
 
135
132
  return "#{table_name}.#{field}"
136
133
  end
@@ -1,3 +1,3 @@
1
1
  module ForestAdminDatasourceActiveRecord
2
- VERSION = "1.0.0-beta.60"
2
+ VERSION = "1.0.0-beta.62"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_admin_datasource_active_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.beta.60
4
+ version: 1.0.0.pre.beta.62
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2024-07-08 00:00:00.000000000 Z
12
+ date: 2024-08-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord