Skip to content

Commit 1b07d5b

Browse files
authored
use new with_advisory_lock (#450)
1 parent 673c149 commit 1b07d5b

12 files changed

+51
-28
lines changed

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
source 'https://rubygems.org'
44

55
gemspec
6+
7+
gem 'with_advisory_lock', github: 'closuretree/with_advisory_lock'

closure_tree.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Gem::Specification.new do |gem|
2828
gem.required_ruby_version = '>= 3.3.0'
2929

3030
gem.add_runtime_dependency 'activerecord', '>= 7.1.0'
31-
gem.add_runtime_dependency 'with_advisory_lock', '>= 5.0.0', '< 6.0.0'
31+
gem.add_runtime_dependency 'with_advisory_lock', '>= 6.0.0'
3232

3333
gem.add_development_dependency 'appraisal'
3434
gem.add_development_dependency 'database_cleaner'

gemfiles/activerecord_7.1.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
source "https://rubygems.org"
44

5+
gem "with_advisory_lock", github: "closuretree/with_advisory_lock"
56
gem "activerecord", "~> 7.1.0"
67
gem "railties"
78

gemfiles/activerecord_7.2.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
source "https://rubygems.org"
44

5+
gem "with_advisory_lock", github: "closuretree/with_advisory_lock"
56
gem "activerecord", "~> 7.2.0"
67
gem "railties"
78

gemfiles/activerecord_8.0.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
source "https://rubygems.org"
44

5+
gem "with_advisory_lock", github: "closuretree/with_advisory_lock"
56
gem "activerecord", "~> 8.0.0"
67
gem "railties"
78

gemfiles/activerecord_edge.gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
source "https://rubygems.org"
44

5+
gem "with_advisory_lock", github: "closuretree/with_advisory_lock"
56
gem "activerecord", github: "rails/rails"
67
gem "railties", github: "rails/rails"
78

lib/closure_tree/numeric_order_support.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ module ClosureTree
22
module NumericOrderSupport
33

44
def self.adapter_for_connection(connection)
5-
das = WithAdvisoryLock::DatabaseAdapterSupport.new(connection)
6-
if das.postgresql?
5+
adapter_name = connection.adapter_name.downcase
6+
if adapter_name.include?('postgresql') || adapter_name.include?('postgis')
77
::ClosureTree::NumericOrderSupport::PostgreSQLAdapter
8-
elsif das.mysql?
8+
elsif adapter_name.include?('mysql') || adapter_name.include?('trilogy')
99
::ClosureTree::NumericOrderSupport::MysqlAdapter
1010
else
1111
::ClosureTree::NumericOrderSupport::GenericAdapter

lib/closure_tree/support.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ class Support
1818

1919
def initialize(model_class, options)
2020
@model_class = model_class
21+
22+
# Detect if we're using SQLite and disable advisory locks
23+
default_with_advisory_lock = !connection.adapter_name.downcase.include?('sqlite')
24+
2125
@options = {
2226
:parent_column_name => 'parent_id',
2327
:dependent => :nullify, # or :destroy or :delete_all -- see the README
2428
:name_column => 'name',
25-
:with_advisory_lock => true,
29+
:with_advisory_lock => default_with_advisory_lock,
2630
:numeric_order => false
2731
}.merge(options)
2832
raise ArgumentError, "name_column can't be 'path'" if options[:name_column] == 'path'
@@ -34,14 +38,10 @@ def initialize(model_class, options)
3438
def hierarchy_class_for_model
3539
parent_class = model_class.module_parent
3640
hierarchy_class = parent_class.const_set(short_hierarchy_class_name, Class.new(model_class.superclass))
37-
use_attr_accessible = use_attr_accessible?
38-
include_forbidden_attributes_protection = include_forbidden_attributes_protection?
3941
model_class_name = model_class.to_s
4042
hierarchy_class.class_eval do
41-
include ActiveModel::ForbiddenAttributesProtection if include_forbidden_attributes_protection
4243
belongs_to :ancestor, class_name: model_class_name
4344
belongs_to :descendant, class_name: model_class_name
44-
attr_accessible :ancestor, :descendant, :generations if use_attr_accessible
4545
def ==(other)
4646
self.class == other.class && ancestor_id == other.ancestor_id && descendant_id == other.descendant_id
4747
end

lib/closure_tree/support_flags.rb

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
module ClosureTree
22
module SupportFlags
33

4-
def use_attr_accessible?
5-
defined?(ActiveModel::MassAssignmentSecurity) &&
6-
model_class.respond_to?(:accessible_attributes) &&
7-
! model_class.accessible_attributes.empty?
8-
end
9-
10-
def include_forbidden_attributes_protection?
11-
defined?(ActiveModel::ForbiddenAttributesProtection) &&
12-
model_class.ancestors.include?(ActiveModel::ForbiddenAttributesProtection)
13-
end
144

155
def order_option?
166
order_by.present?

test/closure_tree/matcher_test.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,14 @@ class MatcherTest < ActiveSupport::TestCase
2828
end
2929

3030
test "advisory_lock option" do
31-
assert_closure_tree User, with_advisory_lock: true
32-
assert_closure_tree Label, ordered: true, with_advisory_lock: true
33-
assert_closure_tree Metal, ordered: :sort_order, with_advisory_lock: true
31+
# SQLite doesn't support advisory locks, so skip these tests when using SQLite
32+
if ActiveRecord::Base.connection.adapter_name.downcase.include?('sqlite')
33+
skip "SQLite doesn't support advisory locks"
34+
else
35+
assert_closure_tree User, with_advisory_lock: true
36+
assert_closure_tree Label, ordered: true, with_advisory_lock: true
37+
assert_closure_tree Metal, ordered: :sort_order, with_advisory_lock: true
38+
end
3439
end
3540

3641
test "without_advisory_lock option" do

test/support/tag_examples.rb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ def self.included(mod)
1212
end
1313

1414
describe 'class setup' do
15-
it 'has correct accessible_attributes' do
16-
if @tag_class._ct.use_attr_accessible?
17-
assert_equal(%w[parent name title].sort, @tag_class.accessible_attributes.to_a.sort)
18-
end
19-
end
2015

2116
it 'should build hierarchy classname correctly' do
2217
assert_equal @tag_hierarchy_class, @tag_class.hierarchy_class

test/test_helper.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,37 @@ def sqlite?
7878
env_db == :sqlite3
7979
end
8080

81-
ActiveRecord::Base.connection.recreate_database('closure_tree_test') unless sqlite?
81+
# For PostgreSQL and MySQL, we need to create/reset the database structure
82+
unless sqlite?
83+
begin
84+
if ActiveRecord::Base.connection.adapter_name.downcase.include?('postgresql')
85+
# PostgreSQL requires disconnecting before dropping the database
86+
ActiveRecord::Base.connection.disconnect!
87+
# Connect to postgres database to drop/create closure_tree_test
88+
if connection_config.is_a?(String)
89+
# Parse the DATABASE_URL and change database to postgres
90+
postgres_url = connection_config.gsub(/\/closure_tree_test/, '/postgres')
91+
ActiveRecord::Base.establish_connection(postgres_url)
92+
else
93+
ActiveRecord::Base.establish_connection(connection_config.merge(database: 'postgres'))
94+
end
95+
ActiveRecord::Base.connection.drop_database('closure_tree_test') rescue nil
96+
ActiveRecord::Base.connection.create_database('closure_tree_test')
97+
ActiveRecord::Base.connection.disconnect!
98+
ActiveRecord::Base.establish_connection(connection_config)
99+
else
100+
# MySQL can recreate directly
101+
ActiveRecord::Base.connection.recreate_database('closure_tree_test')
102+
end
103+
rescue => e
104+
puts "Warning: Could not recreate database: #{e.message}"
105+
end
106+
end
82107
puts "Testing with #{env_db} database, ActiveRecord #{ActiveRecord.gem_version} and #{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} as #{RUBY_VERSION}"
83108

84109
DatabaseCleaner.strategy = :truncation
110+
# Allow DatabaseCleaner to work with our test database
111+
DatabaseCleaner.allow_remote_database_url = true
85112

86113
module Minitest
87114
class Spec

0 commit comments

Comments
 (0)