forest_liana 9.20.1 → 9.20.3

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: 7e6590ae4597f44757af9a98c3f4d8ba9e83652eedd857f45aeb1fe365e8a8ae
4
- data.tar.gz: 5aa5f3150171dd65dac411007c311b9cb5409c9eb97d1a415d31e908001b0d34
3
+ metadata.gz: be12c6b12347b9f674f52eb7f52b41294717436fae76926129d02b6194d6a116
4
+ data.tar.gz: 3a2d7c0a34e7cadbfc40d70b4385d23ffe703de619f9c28b49a10af86a23a8f5
5
5
  SHA512:
6
- metadata.gz: 6d848b970f6f68edd2a162f40e546740878c6fc7e2b298a3c494f6641fce908b41e2412a9e3457d13edef7d6433ce9f5704b77604851b2fd7aeca5eb60cfe691
7
- data.tar.gz: 2828ff99f57028970cc2ec4e1662b70203d0d077ca0bbb45350dd4d29d09bffaffd1ef907b923e666cfc28704f97db62358bdf6709cf4b7c16bac822cd1afa15
6
+ metadata.gz: 3c32654d08132350f85a8313b7ef296838782d72e367509c4283990fb7fda261e453629e0b44f268ece649ae2889ec67dea07c31a6b4b3f2f799178367c016d4
7
+ data.tar.gz: 205dad627f2752573f9f8e9c9a17e8e5a1ec3ad2260bad68a041b38d783060ee5f399950928a8b7f6ea8bf3b450d23878ec5fac7247d7c5e067b323348b4acf0
@@ -51,10 +51,8 @@ module ForestLiana
51
51
  def separate_database?(resource, association)
52
52
  return false if SchemaUtils.polymorphic?(association)
53
53
 
54
- target_model_connection = association.klass.connection
55
- target_model_database = target_model_connection.current_database if target_model_connection.respond_to? :current_database
56
- resource_connection = resource.connection
57
- resource_database = resource_connection.current_database if resource_connection.respond_to? :current_database
54
+ target_model_database = association.klass.connection.pool.db_config.database
55
+ resource_database = resource.connection.pool.db_config.database
58
56
 
59
57
  target_model_database != resource_database
60
58
  end
@@ -266,6 +266,9 @@ module ForestLiana
266
266
  }
267
267
 
268
268
  collection.fields = collection.fields.reject do |field|
269
+ # NOTICE: A primary key column must survive; a type column is never one.
270
+ next false if field[:is_primary_key]
271
+
269
272
  field[:field] == association.foreign_key || field[:field] == association.foreign_type
270
273
  end
271
274
  # NOTICE: Delete the association if the targeted model is excluded.
@@ -274,7 +277,8 @@ module ForestLiana
274
277
  x[:field] == association.foreign_key
275
278
  end
276
279
 
277
- collection.fields.delete(field) if field
280
+ # NOTICE: A primary key column must survive, even as an excluded association's FK.
281
+ collection.fields.delete(field) if field && !field[:is_primary_key]
278
282
  # NOTICE: The foreign key exists, so it's a belongsTo relationship.
279
283
  elsif (field = column_association(collection, association)) &&
280
284
  [:has_one, :belongs_to].include?(association.macro)
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "9.20.1"
2
+ VERSION = "9.20.3"
3
3
  end
@@ -83,26 +83,6 @@ module ForestLiana
83
83
  let(:resource) { Product }
84
84
  let(:fields) { { resource.name => 'id,name,manufacturer', 'manufacturer' => 'name' } }
85
85
 
86
- shared_context 'resource current_database' do
87
- before do
88
- connection = resource.connection
89
-
90
- def connection.current_database
91
- 'db/test.sqlite3'
92
- end
93
- end
94
-
95
- after do
96
- resource.connection.singleton_class.remove_method(:current_database)
97
- end
98
- end
99
-
100
- shared_examples 'left outer join' do
101
- it 'should perform a left outer join with the association' do
102
- expect(getter.perform.to_sql).to match(/LEFT OUTER JOIN "manufacturers"/)
103
- end
104
- end
105
-
106
86
  shared_examples 'records' do
107
87
  it 'should get only the expected records' do
108
88
  getter.perform
@@ -117,40 +97,38 @@ module ForestLiana
117
97
  end
118
98
  end
119
99
 
120
- context 'when the connections do not support current_database' do
121
- include_examples 'left outer join'
100
+ context 'when the included association is in the same database' do
101
+ it 'performs a left outer join with the association' do
102
+ expect(getter.perform.to_sql).to match(/LEFT OUTER JOIN "manufacturers"/)
103
+ end
104
+
122
105
  include_examples 'records'
123
106
  end
124
107
 
125
- context 'when the included association uses a different database connection' do
108
+ context 'when the included association is in a different database' do
126
109
  let(:fields) { { resource.name => 'id,name,driver', 'driver' => 'firstname' } }
127
110
 
128
- before do
129
- association_connection = resource.reflect_on_association(:driver).klass.connection
130
-
131
- def association_connection.current_database
132
- 'db/different_test.sqlite3'
133
- end
134
- end
135
-
136
- after do
137
- resource.reflect_on_association(:driver).klass.connection.singleton_class.remove_method(:current_database)
138
- end
139
-
140
- include_context 'resource current_database'
141
-
142
- include_examples 'records'
143
-
144
111
  it 'does not perform a left outer join with the association' do
145
112
  expect(getter.perform.to_sql).not_to match(/LEFT OUTER JOIN "drivers"/)
146
113
  end
114
+
115
+ include_examples 'records'
147
116
  end
148
117
 
149
- context 'when the included association uses the same database connection' do
150
- include_context 'resource current_database'
118
+ it 'resolves the database without issuing a SQL query' do
119
+ getter
151
120
 
152
- include_examples 'left outer join'
153
- include_examples 'records'
121
+ queries = []
122
+ subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |*, payload|
123
+ queries << payload[:sql] unless payload[:name] == 'SCHEMA' || payload[:cached]
124
+ end
125
+ begin
126
+ getter.send(:separate_database?, Product, Product.reflect_on_association(:manufacturer))
127
+ ensure
128
+ ActiveSupport::Notifications.unsubscribe(subscriber)
129
+ end
130
+
131
+ expect(queries).to be_empty
154
132
  end
155
133
  end
156
134
 
@@ -86,6 +86,62 @@ module ForestLiana
86
86
  ForestLiana.apimap << original if original
87
87
  end
88
88
 
89
+ test 'a primary key column that is also the foreign key of an excluded association is kept' do
90
+ excluded_models = ForestLiana.excluded_models
91
+ name = ForestLiana.name_for(BelongsToField)
92
+ original = ForestLiana.apimap.find { |c| c.name.to_s == name }
93
+ ForestLiana.apimap.delete(original) if original
94
+ ForestLiana.excluded_models = [ForestLiana.name_for(HasOneField)]
95
+ BelongsToField.define_singleton_method(:primary_key) { 'has_one_field_id' }
96
+
97
+ schema = SchemaAdapter.new(BelongsToField).perform
98
+ field = schema.fields.find { |f| f[:field] == 'has_one_field_id' }
99
+
100
+ refute_nil field, 'the primary key column must not be deleted'
101
+ assert_equal true, field[:is_primary_key]
102
+ ensure
103
+ BelongsToField.singleton_class.send(:remove_method, :primary_key)
104
+ ForestLiana.excluded_models = excluded_models
105
+ rebuilt = ForestLiana.apimap.find { |c| c.name.to_s == name }
106
+ ForestLiana.apimap.delete(rebuilt) if rebuilt
107
+ ForestLiana.apimap << original if original
108
+ end
109
+
110
+ test 'an ordinary foreign key of an excluded association is still deleted' do
111
+ excluded_models = ForestLiana.excluded_models
112
+ name = ForestLiana.name_for(BelongsToField)
113
+ original = ForestLiana.apimap.find { |c| c.name.to_s == name }
114
+ ForestLiana.apimap.delete(original) if original
115
+ ForestLiana.excluded_models = [ForestLiana.name_for(HasOneField)]
116
+
117
+ schema = SchemaAdapter.new(BelongsToField).perform
118
+
119
+ assert_nil schema.fields.find { |f| f[:field] == 'has_one_field_id' }
120
+ ensure
121
+ ForestLiana.excluded_models = excluded_models
122
+ rebuilt = ForestLiana.apimap.find { |c| c.name.to_s == name }
123
+ ForestLiana.apimap.delete(rebuilt) if rebuilt
124
+ ForestLiana.apimap << original if original
125
+ end
126
+
127
+ test 'a primary key column that is also a polymorphic foreign key is kept' do
128
+ name = ForestLiana.name_for(PolymorphicField)
129
+ original = ForestLiana.apimap.find { |c| c.name.to_s == name }
130
+ ForestLiana.apimap.delete(original) if original
131
+ PolymorphicField.define_singleton_method(:primary_key) { 'has_one_field_id' }
132
+
133
+ schema = SchemaAdapter.new(PolymorphicField).perform
134
+ field = schema.fields.find { |f| f[:field] == 'has_one_field_id' }
135
+
136
+ refute_nil field, 'the primary key column must not be rejected'
137
+ assert_equal true, field[:is_primary_key]
138
+ ensure
139
+ PolymorphicField.singleton_class.send(:remove_method, :primary_key)
140
+ rebuilt = ForestLiana.apimap.find { |c| c.name.to_s == name }
141
+ ForestLiana.apimap.delete(rebuilt) if rebuilt
142
+ ForestLiana.apimap << original if original
143
+ end
144
+
89
145
  test 'belongsTo relationship' do
90
146
  schema = SchemaAdapter.new(BelongsToField).perform
91
147
  fields = schema.fields.select do |field|
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: 9.20.1
4
+ version: 9.20.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-23 00:00:00.000000000 Z
11
+ date: 2026-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails