trusty-cms 8.0 → 8.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77d3850c23f30e1a9654c68e84bf5f34c3c7ebd3f0deaf5baadd91a34423eb3f
4
- data.tar.gz: d21af2702b713670e01cd1f33ae95e8d2ea9803e1134921a8d76f90e2d75ec0d
3
+ metadata.gz: a19f132543bcd95bbd5225dc356b1ad17a5e85da6e4778af11151b5474641536
4
+ data.tar.gz: 19bd2adb46698e225aed2c5272238c533a093ccd48e9ae5979665d3f721e9433
5
5
  SHA512:
6
- metadata.gz: 4847f7ef1367b73749feead54eae6d0c7ffa76d953b6ac6dd0c29af23cdfe11b0b4c9a26e8a9018b0d0200ae30818f65cb6aba4be1bc3e41a5e4c4089ac0cd0f
7
- data.tar.gz: bdd09ed13ebc928624962d5d44b0eb82d63694a55a9fbcd5b50584a206ae998c81f5f68353c97738cb0a1e6c84f2fe158cb222bd37f22c3798f932f6346fbc07
6
+ metadata.gz: a03e160394522490d737f7d5d729b4e96d73226a284fdfdc6971d40c10e720ec788b174196509c30e80a43be8d116fd2a49f2321e1bc6eae16564dac97de5be2
7
+ data.tar.gz: a4c06fd38e690bc65e7d83e3e3f964c2919ede43c81a1f56e2d7b5975c1f3e00481452fd0ec53267fb760192ffb3034c16c92fb2347b188042c34d1076acc39c
data/Gemfile CHANGED
@@ -14,16 +14,16 @@ gemspec
14
14
  group :development, :test do
15
15
  gem 'activestorage-validator'
16
16
  gem 'acts_as_list'
17
+ gem 'capybara'
17
18
  gem 'database_cleaner'
18
19
  gem 'devise-two-factor'
19
20
  gem 'factory_bot_rails', '6.5.1'
20
21
  gem 'file_validators'
21
22
  gem 'jsbundling-rails', '~> 1.3'
22
- gem 'launchy', '~> 3.0.1'
23
+ gem 'launchy', '~> 3.1.1'
23
24
  gem 'mysql2'
24
- gem 'paper_trail', '~> 16.0.0'
25
+ gem 'paper_trail', '~> 17.0.0'
25
26
  gem 'paper_trail-association_tracking', '~> 2.3.0'
26
- gem 'poltergeist', '~> 1.18.1'
27
27
  gem 'pry-byebug'
28
28
  gem 'psych', '5.4.0'
29
29
  gem 'rails-observers'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- trusty-cms (8.0)
4
+ trusty-cms (8.2.0)
5
5
  RedCloth (= 4.3.4)
6
6
  activestorage-validator
7
7
  acts_as_list (>= 0.9.5, < 1.3.0)
@@ -15,8 +15,8 @@ PATH
15
15
  diffy
16
16
  drb
17
17
  execjs (~> 2.7)
18
- haml (~> 6.3.0)
19
- haml-rails (~> 2.1)
18
+ haml (>= 6.3, < 7.4)
19
+ haml-rails (>= 2.1, < 4.0)
20
20
  highline (>= 1.7.8, < 3.2.0)
21
21
  image_processing
22
22
  kraken-io
@@ -24,13 +24,14 @@ PATH
24
24
  mini_racer
25
25
  mutex_m
26
26
  mysql2
27
- paper_trail (~> 16.0.0)
27
+ ostruct
28
+ paper_trail (~> 17.0.0)
28
29
  paper_trail-association_tracking (>= 2.2.1, < 2.4.0)
29
30
  psych (= 5.4.0)
30
31
  rack (>= 2.0.1, < 3.2.0)
31
32
  rack-cache (~> 1.7)
32
33
  radius (~> 0.8)
33
- rails (~> 8.0.0)
34
+ rails (~> 8.1.0)
34
35
  rake (< 14.0)
35
36
  ransack (~> 4.2.1)
36
37
  rdoc (>= 5.1, < 9.0)
@@ -47,29 +48,31 @@ GEM
47
48
  remote: https://rubygems.org/
48
49
  specs:
49
50
  RedCloth (4.3.4)
50
- actioncable (8.0.5.1)
51
- actionpack (= 8.0.5.1)
52
- activesupport (= 8.0.5.1)
51
+ action_text-trix (2.1.19)
52
+ railties
53
+ actioncable (8.1.3.1)
54
+ actionpack (= 8.1.3.1)
55
+ activesupport (= 8.1.3.1)
53
56
  nio4r (~> 2.0)
54
57
  websocket-driver (>= 0.6.1)
55
58
  zeitwerk (~> 2.6)
56
- actionmailbox (8.0.5.1)
57
- actionpack (= 8.0.5.1)
58
- activejob (= 8.0.5.1)
59
- activerecord (= 8.0.5.1)
60
- activestorage (= 8.0.5.1)
61
- activesupport (= 8.0.5.1)
59
+ actionmailbox (8.1.3.1)
60
+ actionpack (= 8.1.3.1)
61
+ activejob (= 8.1.3.1)
62
+ activerecord (= 8.1.3.1)
63
+ activestorage (= 8.1.3.1)
64
+ activesupport (= 8.1.3.1)
62
65
  mail (>= 2.8.0)
63
- actionmailer (8.0.5.1)
64
- actionpack (= 8.0.5.1)
65
- actionview (= 8.0.5.1)
66
- activejob (= 8.0.5.1)
67
- activesupport (= 8.0.5.1)
66
+ actionmailer (8.1.3.1)
67
+ actionpack (= 8.1.3.1)
68
+ actionview (= 8.1.3.1)
69
+ activejob (= 8.1.3.1)
70
+ activesupport (= 8.1.3.1)
68
71
  mail (>= 2.8.0)
69
72
  rails-dom-testing (~> 2.2)
70
- actionpack (8.0.5.1)
71
- actionview (= 8.0.5.1)
72
- activesupport (= 8.0.5.1)
73
+ actionpack (8.1.3.1)
74
+ actionview (= 8.1.3.1)
75
+ activesupport (= 8.1.3.1)
73
76
  nokogiri (>= 1.8.5)
74
77
  rack (>= 2.2.4)
75
78
  rack-session (>= 1.0.1)
@@ -77,44 +80,45 @@ GEM
77
80
  rails-dom-testing (~> 2.2)
78
81
  rails-html-sanitizer (~> 1.6)
79
82
  useragent (~> 0.16)
80
- actiontext (8.0.5.1)
81
- actionpack (= 8.0.5.1)
82
- activerecord (= 8.0.5.1)
83
- activestorage (= 8.0.5.1)
84
- activesupport (= 8.0.5.1)
83
+ actiontext (8.1.3.1)
84
+ action_text-trix (~> 2.1.15)
85
+ actionpack (= 8.1.3.1)
86
+ activerecord (= 8.1.3.1)
87
+ activestorage (= 8.1.3.1)
88
+ activesupport (= 8.1.3.1)
85
89
  globalid (>= 0.6.0)
86
90
  nokogiri (>= 1.8.5)
87
- actionview (8.0.5.1)
88
- activesupport (= 8.0.5.1)
91
+ actionview (8.1.3.1)
92
+ activesupport (= 8.1.3.1)
89
93
  builder (~> 3.1)
90
94
  erubi (~> 1.11)
91
95
  rails-dom-testing (~> 2.2)
92
96
  rails-html-sanitizer (~> 1.6)
93
- activejob (8.0.5.1)
94
- activesupport (= 8.0.5.1)
97
+ activejob (8.1.3.1)
98
+ activesupport (= 8.1.3.1)
95
99
  globalid (>= 0.3.6)
96
- activemodel (8.0.5.1)
97
- activesupport (= 8.0.5.1)
98
- activerecord (8.0.5.1)
99
- activemodel (= 8.0.5.1)
100
- activesupport (= 8.0.5.1)
100
+ activemodel (8.1.3.1)
101
+ activesupport (= 8.1.3.1)
102
+ activerecord (8.1.3.1)
103
+ activemodel (= 8.1.3.1)
104
+ activesupport (= 8.1.3.1)
101
105
  timeout (>= 0.4.0)
102
- activestorage (8.0.5.1)
103
- actionpack (= 8.0.5.1)
104
- activejob (= 8.0.5.1)
105
- activerecord (= 8.0.5.1)
106
- activesupport (= 8.0.5.1)
106
+ activestorage (8.1.3.1)
107
+ actionpack (= 8.1.3.1)
108
+ activejob (= 8.1.3.1)
109
+ activerecord (= 8.1.3.1)
110
+ activesupport (= 8.1.3.1)
107
111
  marcel (~> 1.0)
108
112
  activestorage-validator (0.8.0)
109
113
  rails (>= 7.2.0)
110
- activesupport (8.0.5.1)
114
+ activesupport (8.1.3.1)
111
115
  base64
112
- benchmark (>= 0.3)
113
116
  bigdecimal
114
117
  concurrent-ruby (~> 1.0, >= 1.3.1)
115
118
  connection_pool (>= 2.2.5)
116
119
  drb
117
120
  i18n (>= 1.6, < 2)
121
+ json
118
122
  logger (>= 1.4.2)
119
123
  minitest (>= 5.1)
120
124
  securerandom (>= 0.3)
@@ -129,7 +133,6 @@ GEM
129
133
  public_suffix (>= 2.0.2, < 8.0)
130
134
  base64 (0.3.0)
131
135
  bcrypt (3.1.22)
132
- benchmark (0.5.0)
133
136
  bigdecimal (4.1.2)
134
137
  builder (3.3.0)
135
138
  byebug (13.0.0)
@@ -146,7 +149,6 @@ GEM
146
149
  childprocess (5.1.0)
147
150
  logger (~> 1.5)
148
151
  chunky_png (1.4.0)
149
- cliver (0.3.2)
150
152
  coderay (1.1.3)
151
153
  concurrent-ruby (1.3.8)
152
154
  connection_pool (3.0.2)
@@ -180,7 +182,7 @@ GEM
180
182
  diff-lcs (1.6.2)
181
183
  diffy (3.4.4)
182
184
  drb (2.2.3)
183
- erb (6.0.6)
185
+ erb (6.0.7)
184
186
  erubi (1.13.1)
185
187
  execjs (2.10.1)
186
188
  factory_bot (6.6.0)
@@ -203,11 +205,12 @@ GEM
203
205
  mime-types (>= 1.0)
204
206
  globalid (1.4.0)
205
207
  activesupport (>= 6.1)
206
- haml (6.3.1)
208
+ haml (7.3.0)
209
+ prism (>= 1.1.0)
207
210
  temple (>= 0.8.2)
208
211
  thor
209
212
  tilt
210
- haml-rails (2.1.0)
213
+ haml-rails (3.1.0)
211
214
  actionpack (>= 5.1)
212
215
  activesupport (>= 5.1)
213
216
  haml (>= 4.0.6)
@@ -221,7 +224,7 @@ GEM
221
224
  i18n (1.15.2)
222
225
  concurrent-ruby (~> 1.0)
223
226
  image_processing (2.0.2)
224
- io-console (0.8.2)
227
+ io-console (0.9.2)
225
228
  irb (1.18.0)
226
229
  pp (>= 0.6.0)
227
230
  prism (>= 1.3.0)
@@ -235,9 +238,10 @@ GEM
235
238
  httparty
236
239
  json
237
240
  multipart-post
238
- launchy (3.0.1)
241
+ launchy (3.1.1)
239
242
  addressable (~> 2.8)
240
243
  childprocess (~> 5.0)
244
+ logger (~> 1.6)
241
245
  libv8-node (24.12.0.1)
242
246
  libv8-node (24.12.0.1-aarch64-linux)
243
247
  libv8-node (24.12.0.1-aarch64-linux-musl)
@@ -307,15 +311,12 @@ GEM
307
311
  nokogiri (1.19.4-x86_64-linux-musl)
308
312
  racc (~> 1.4)
309
313
  orm_adapter (0.5.0)
310
- paper_trail (16.0.0)
311
- activerecord (>= 6.1)
314
+ ostruct (0.6.3)
315
+ paper_trail (17.0.0)
316
+ activerecord (>= 7.1)
312
317
  request_store (~> 1.4)
313
318
  paper_trail-association_tracking (2.3.0)
314
319
  paper_trail (>= 12.0)
315
- poltergeist (1.18.1)
316
- capybara (>= 2.1, < 4)
317
- cliver (~> 0.3.1)
318
- websocket-driver (>= 0.2.0)
319
320
  pp (0.6.4)
320
321
  prettyprint
321
322
  prettyprint (0.2.0)
@@ -343,20 +344,20 @@ GEM
343
344
  rackup (2.3.1)
344
345
  rack (>= 3)
345
346
  radius (0.8.0)
346
- rails (8.0.5.1)
347
- actioncable (= 8.0.5.1)
348
- actionmailbox (= 8.0.5.1)
349
- actionmailer (= 8.0.5.1)
350
- actionpack (= 8.0.5.1)
351
- actiontext (= 8.0.5.1)
352
- actionview (= 8.0.5.1)
353
- activejob (= 8.0.5.1)
354
- activemodel (= 8.0.5.1)
355
- activerecord (= 8.0.5.1)
356
- activestorage (= 8.0.5.1)
357
- activesupport (= 8.0.5.1)
347
+ rails (8.1.3.1)
348
+ actioncable (= 8.1.3.1)
349
+ actionmailbox (= 8.1.3.1)
350
+ actionmailer (= 8.1.3.1)
351
+ actionpack (= 8.1.3.1)
352
+ actiontext (= 8.1.3.1)
353
+ actionview (= 8.1.3.1)
354
+ activejob (= 8.1.3.1)
355
+ activemodel (= 8.1.3.1)
356
+ activerecord (= 8.1.3.1)
357
+ activestorage (= 8.1.3.1)
358
+ activesupport (= 8.1.3.1)
358
359
  bundler (>= 1.15.0)
359
- railties (= 8.0.5.1)
360
+ railties (= 8.1.3.1)
360
361
  rails-dom-testing (2.3.0)
361
362
  activesupport (>= 5.0.0)
362
363
  minitest
@@ -366,9 +367,9 @@ GEM
366
367
  nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
367
368
  rails-observers (0.1.5)
368
369
  activemodel (>= 4.0)
369
- railties (8.0.5.1)
370
- actionpack (= 8.0.5.1)
371
- activesupport (= 8.0.5.1)
370
+ railties (8.1.3.1)
371
+ actionpack (= 8.1.3.1)
372
+ activesupport (= 8.1.3.1)
372
373
  irb (~> 1.13)
373
374
  rackup (>= 1.0.0)
374
375
  rake (>= 12.2)
@@ -380,7 +381,7 @@ GEM
380
381
  activerecord (>= 6.1.5)
381
382
  activesupport (>= 6.1.5)
382
383
  i18n
383
- rbs (4.1.2)
384
+ rbs (4.1.3)
384
385
  logger
385
386
  prism (>= 1.6.0)
386
387
  tsort
@@ -389,8 +390,8 @@ GEM
389
390
  prism (>= 1.6.0)
390
391
  rbs (>= 4.0.0)
391
392
  tsort
392
- regexp_parser (2.12.0)
393
- reline (0.6.3)
393
+ regexp_parser (2.13.1)
394
+ reline (0.7.0)
394
395
  io-console (~> 0.5)
395
396
  request_store (1.7.0)
396
397
  rack (>= 1.4)
@@ -451,7 +452,7 @@ GEM
451
452
  ssrf_filter (1.5.0)
452
453
  stringex (2.8.6)
453
454
  stringio (3.2.0)
454
- temple (0.10.4)
455
+ temple (0.10.6)
455
456
  thor (1.5.0)
456
457
  tilt (2.8.0)
457
458
  timeout (0.6.1)
@@ -490,16 +491,16 @@ PLATFORMS
490
491
  DEPENDENCIES
491
492
  activestorage-validator
492
493
  acts_as_list
494
+ capybara
493
495
  database_cleaner
494
496
  devise-two-factor
495
497
  factory_bot_rails (= 6.5.1)
496
498
  file_validators
497
499
  jsbundling-rails (~> 1.3)
498
- launchy (~> 3.0.1)
500
+ launchy (~> 3.1.1)
499
501
  mysql2
500
- paper_trail (~> 16.0.0)
502
+ paper_trail (~> 17.0.0)
501
503
  paper_trail-association_tracking (~> 2.3.0)
502
- poltergeist (~> 1.18.1)
503
504
  pry-byebug
504
505
  psych (= 5.4.0)
505
506
  rails-observers
@@ -512,4 +513,4 @@ DEPENDENCIES
512
513
  trustygems (~> 0.2.0)
513
514
 
514
515
  BUNDLED WITH
515
- 2.5.21
516
+ 4.0.22
data/INSTALL.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  From within the directory containing your TrustyCMS instance:
4
4
 
5
- 1. Create a new Rails 7.0+ application (i.e. `rails new [project_name]`)
5
+ 1. Create a new Rails 8.0+ application (i.e. `rails new [project_name]`)
6
6
 
7
7
  2. Add the following gems to your Gemfile:
8
8
 
data/README.md CHANGED
@@ -53,11 +53,10 @@ See the INSTALL.md file for more instructions.
53
53
  Prerequisites:
54
54
 
55
55
  * A Github account and Git ([Github has some really good instructions](https://help.github.com/articles/set-up-git))
56
- * Ruby 3.1 or higher
57
- * A Rails application (currently supports version 7.0)
56
+ * Ruby 3.3 or higher
57
+ * A Rails application (currently supports version 8.1)
58
58
  * Bundler
59
59
  * MySQL
60
- * [PhantomJS >= 1.8.1](https://github.com/teampoltergeist/poltergeist/tree/v1.5.0#installing-phantomjs)
61
60
 
62
61
  Steps:
63
62
 
@@ -19,11 +19,22 @@ module Admin::PagesHelper
19
19
  end
20
20
 
21
21
  def parent_page_options(current_site, page)
22
- parent_pages = []
23
- parent_pages.concat(Page.parent_pages(current_site.homepage_id))
24
- parent_pages << page.parent if page.parent
25
- selected_page_id = page.parent_id
26
- options_for_select(parent_pages.map { |p| [p.title, p.id] }, selected_page_id)
22
+ parent_pages = Page.parent_pages(current_site.homepage_id).to_a
23
+ parent_pages << page.parent if page.parent && parent_pages.exclude?(page.parent)
24
+ # A page can never be its own parent. For a site's root page this would
25
+ # otherwise set parent_id to itself and create an infinite loop in the tree.
26
+ parent_pages.reject! { |p| p.id == page.id }
27
+ # The root (top) page of a site must have no parent, so give it a blank
28
+ # option. Without one the browser submits the first option on save, which
29
+ # gives the root page a parent and breaks the whole site.
30
+ return options_for_select([[t('select.none'), '']], '') if root_page?(current_site, page)
31
+
32
+ options = parent_pages.map { |p| [p.title, p.id] }
33
+ options_for_select(options, page.parent.id)
34
+ end
35
+
36
+ def root_page?(current_site, page)
37
+ page.id.present? && page.id == current_site.homepage_id
27
38
  end
28
39
 
29
40
  def revert_confirmation_message(version)
@@ -19,10 +19,6 @@ module TrustyCms
19
19
  include TrustyCms::Initializer
20
20
  config.load_defaults 8.0
21
21
 
22
- # Rails 8.1 will make `to_time` always preserve the receiver's timezone.
23
- # Opt in now to silence the deprecation and get the new behavior.
24
- config.active_support.to_time_preserves_timezone = :zone
25
-
26
22
  Rails.autoloaders.log!
27
23
  # Enable the asset pipeline
28
24
  config.assets.enabled = true
@@ -2,7 +2,6 @@ Rails.autoloaders.each do |autoloader|
2
2
  autoloader.inflector.inflect(
3
3
  'clipped_admin_ui' => 'ClippedAdminUI',
4
4
  'admin_ui' => 'AdminUI',
5
- 'ostruct' => 'OpenStruct',
6
5
  # Add more inflections as needed
7
6
  )
8
7
  end
@@ -5,7 +5,7 @@ module TrustyCms::AvailableLocales
5
5
  available_locales = {}
6
6
  TrustyCms.configuration.i18n.load_path.each do |path|
7
7
  if File.exist?(path) && path !~ /_available_tags/
8
- locale_yaml = YAML.load_file(path)
8
+ locale_yaml = YAML.load_file(path, aliases: true)
9
9
  stem = File.basename(path, '.yml')
10
10
  if locale_yaml[stem] && lang = locale_yaml[stem]['this_file_language']
11
11
  available_locales[lang] = stem
@@ -53,13 +53,6 @@ module TrustyCms
53
53
  super
54
54
  @table = Hash.new { |h, k| h[k] = Response.new }
55
55
  end
56
-
57
- def initialize_copy(orig)
58
- super
59
- @table.keys.each do |key|
60
- @table[key] = orig.send(key).dup
61
- end
62
- end
63
56
  end
64
57
 
65
58
  class Response
@@ -145,7 +145,7 @@ module TrustyCms
145
145
  end
146
146
 
147
147
  def load_template_file(filename)
148
- YAML.load_file(filename)
148
+ YAML.load_file(filename, aliases: true)
149
149
  end
150
150
 
151
151
  def create_records(template)
@@ -3,7 +3,7 @@ module TrustyCms
3
3
  class << self
4
4
  def establish_connection
5
5
  unless ActiveRecord::Base.connected?
6
- connection_hash = YAML.load_file("#{Rails.root}/config/database.yml").to_hash
6
+ connection_hash = YAML.load_file("#{Rails.root}/config/database.yml", aliases: true).to_hash
7
7
  env_connection = connection_hash[Rails.env]
8
8
  ActiveRecord::Base.establish_connection(env_connection)
9
9
  end
@@ -23,7 +23,7 @@ module TrustyCms
23
23
  begin
24
24
  TrustyCms::Config.transaction do
25
25
  TrustyCms::Config.delete_all if clear
26
- configs = YAML.load(YAML.load_file(path))
26
+ configs = YAML.load(YAML.load_file(path), aliases: true)
27
27
  configs.each do |key, value|
28
28
  c = TrustyCms::Config.find_or_initialize_by_key(key)
29
29
  c.value = value
@@ -1,3 +1,3 @@
1
1
  module TrustyCms
2
- VERSION = '8.0'.freeze
2
+ VERSION = '8.2.0'.freeze
3
3
  end
@@ -116,18 +116,27 @@ RSpec.describe Admin::PagesController, type: :controller do
116
116
  end
117
117
 
118
118
  describe 'GET #search' do
119
- it 'returns matching pages when a query is present' do
120
- create(:page, title: 'Findable', slug: 'findable', parent: home)
119
+ # The suite-wide stub returns nil, which the real Page.current_site can't do:
120
+ # the multi-site extension defines it as `@current_site ||= Site.default`, and
121
+ # Site.default ends in a catchall it creates. #search is the one action that
122
+ # reads it, so stub it faithfully here and let the fallback actually run.
123
+ let(:site) { create(:site) }
121
124
 
122
- get :search, params: { site_id: nil, search: { query: 'Findable' } }
125
+ before { allow(Page).to receive(:current_site).and_return(site) }
126
+
127
+ it 'falls back to the current site when no site_id is given' do
128
+ create(:page, title: 'Findable', slug: 'findable', parent: home, site_id: site.id)
129
+
130
+ get :search, params: { search: { query: 'Findable' } }
123
131
 
124
132
  expect(response).to have_http_status(:ok)
133
+ expect(controller.instance_variable_get(:@site_id)).to eq(site.id)
125
134
  titles = controller.instance_variable_get(:@pages).map(&:title)
126
135
  expect(titles).to include('Findable')
127
136
  end
128
137
 
129
138
  it 'does not run a query when none is given' do
130
- get :search, params: { site_id: '' }
139
+ get :search
131
140
  expect(controller.instance_variable_get(:@pages)).to be_nil
132
141
  end
133
142
  end
@@ -142,21 +151,17 @@ RSpec.describe Admin::PagesController, type: :controller do
142
151
  end
143
152
 
144
153
  describe 'PUT #restore' do
145
- # NOTE: latent bug / Rails 8 upgrade blocker — restore_page_version calls
146
- # PaperTrail's `reify`, which YAML-loads the stored version. Under Psych 4+
147
- # (psych 5.4 is pinned) safe-loading rejects ActiveSupport::TimeWithZone
148
- # because no permitted classes are configured, so restoring any page that has
149
- # a timestamp in its versioned state raises Psych::DisallowedClass. Page
150
- # restore is effectively broken until paper_trail's serializer is configured
151
- # with permitted classes (e.g. via ActiveRecord::Base.yaml_column_permitted_classes
152
- # or a custom serializer). Characterizing current behavior.
153
- it 'currently fails to reify a versioned page (Psych safe-load blocker)' do
154
+ # reify YAML-loads the stored version under Psych 4+ safe-load, which needs
155
+ # ActiveSupport::TimeWithZone (and friends) in
156
+ # ActiveRecord.yaml_column_permitted_classes — configured in the dummy app.
157
+ it 'reifies the prior version and redirects to edit' do
154
158
  page = create(:page, title: 'V1', parent: home)
155
159
  PaperTrail.request(whodunnit: admin.id.to_s) { page.update!(title: 'V2') }
156
160
 
157
- expect {
158
- put :restore, params: { id: page.id, version_index: 1 }
159
- }.to raise_error(Psych::DisallowedClass, /TimeWithZone/)
161
+ put :restore, params: { id: page.id, version_index: 1 }
162
+
163
+ expect(response).to redirect_to(edit_admin_page_path(page))
164
+ expect(page.reload.title).to eq('V1')
160
165
  end
161
166
  end
162
167
  end
@@ -41,8 +41,7 @@ module TrustyCms
41
41
 
42
42
  config.encoding = 'utf-8'
43
43
  config.time_zone = 'UTC'
44
- # Rails 8.1 will make `to_time` always preserve the receiver's timezone.
45
- config.active_support.to_time_preserves_timezone = :zone
44
+
46
45
  # Skip frameworks you're not going to use (only works if using vendor/rails).
47
46
  # To use Rails without a database, you must remove the Active Record framework
48
47
  # config.frameworks -= [ :action_mailer ]
@@ -121,6 +120,11 @@ module TrustyCms
121
120
  end
122
121
  end
123
122
 
123
+ config.active_record.yaml_column_permitted_classes = [
124
+ Symbol, Date, Time, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone,
125
+ ActiveSupport::HashWithIndifferentAccess, BigDecimal
126
+ ]
127
+
124
128
  config.to_prepare do
125
129
  extension_loader.deactivate_extensions
126
130
  extension_loader.load_extensions
@@ -2,7 +2,6 @@ Rails.autoloaders.each do |autoloader|
2
2
  autoloader.inflector.inflect(
3
3
  'clipped_admin_ui' => 'ClippedAdminUI',
4
4
  'admin_ui' => 'AdminUI',
5
- 'ostruct' => 'OpenStruct',
6
5
  # Add more inflections as needed
7
6
  )
8
7
  end
@@ -72,6 +72,36 @@ describe Admin::PagesHelper, type: :helper do
72
72
  expect(html).to include('Home')
73
73
  expect(html).to include("value=\"#{home.id}\"")
74
74
  end
75
+
76
+ it 'offers a blank parent option for the site root page' do
77
+ home = FactoryBot.create(:home, title: 'Home')
78
+ current_site = double('Site', homepage_id: home.id)
79
+ allow(Page).to receive(:parent_pages).with(home.id).and_return([home])
80
+
81
+ html = helper.parent_page_options(current_site, home)
82
+ expect(html).to include('<option selected="selected" value="">&lt;none&gt;</option>')
83
+ end
84
+
85
+ it 'never lists the root page as a candidate for its own parent' do
86
+ home = FactoryBot.create(:home, title: 'Home')
87
+ current_site = double('Site', homepage_id: home.id)
88
+ allow(Page).to receive(:parent_pages).with(home.id).and_return([home])
89
+
90
+ html = helper.parent_page_options(current_site, home)
91
+
92
+ expect(html).not_to include("value=\"#{home.id}\"")
93
+ end
94
+
95
+ it 'does not offer a blank parent option for non-root pages' do
96
+ home = FactoryBot.create(:home, title: 'Home')
97
+ child = FactoryBot.create(:page, title: 'Child', slug: 'child', parent: home)
98
+ current_site = double('Site', homepage_id: home.id)
99
+ allow(Page).to receive(:parent_pages).with(home.id).and_return([home])
100
+
101
+ html = helper.parent_page_options(current_site, child)
102
+
103
+ expect(html).not_to include('<option value="">')
104
+ end
75
105
  end
76
106
 
77
107
  describe '#revert_confirmation_message' do
@@ -1,14 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'ostruct'
3
3
 
4
- # lib/ostruct.rb reopens OpenStruct (originally patched for a Ruby upgrade) and
5
- # shadows the stdlib version via the load path. This is exactly the kind of
6
- # patch a Ruby/Rails upgrade can break, so pin the behaviour we rely on.
7
- describe 'OpenStruct patch' do
8
- it 'is the project patch, not the stdlib implementation' do
9
- expect(OpenStruct.instance_method(:initialize).source_location.first)
10
- .to eq(File.expand_path('../../lib/ostruct.rb', __dir__))
11
- end
4
+ describe 'OpenStruct' do
12
5
 
13
6
  it 'builds accessors from a hash, symbolizing string keys' do
14
7
  os = OpenStruct.new('a' => 1, :b => 2)
data/spec/spec_helper.rb CHANGED
@@ -13,9 +13,9 @@ SimpleCov::Formatter::LcovFormatter.config do |config|
13
13
  end
14
14
 
15
15
  SimpleCov.configure do
16
- add_filter %r{^/lib/generators/}
17
- add_filter 'lib/trusty_cms/setup.rb'
18
- add_filter %r{/templates/} # generated-app boilerplate
16
+ skip %r{^/lib/generators/}
17
+ skip 'lib/trusty_cms/setup.rb'
18
+ skip %r{/templates/} # generated-app boilerplate
19
19
  end
20
20
 
21
21
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
data/trusty_cms.gemspec CHANGED
@@ -21,7 +21,6 @@ a general purpose content management system--not merely a blogging engine.'
21
21
  s.rdoc_options = ['--title', 'TrustyCms -- Content Management You Can Trust', '--line-numbers', '--main', 'README', '--exclude', 'app', '--exclude', 'bin', '--exclude',
22
22
  'config', '--exclude', 'db', '--exclude', 'features', '--exclude', 'lib', '--exclude', 'log', '--exclude', 'pkg', '--exclude', 'public', '--exclude', 'script', '--exclude', 'spec', '--exclude', 'test', '--exclude', 'tmp', '--exclude', 'vendor']
23
23
  s.require_paths = ['lib']
24
- s.rubygems_version = '1.3.7'
25
24
  s.summary = 'A no-fluff content management system designed for small teams.'
26
25
  s.license = 'MIT'
27
26
  s.test_files = Dir['spec/**/*']
@@ -37,8 +36,8 @@ a general purpose content management system--not merely a blogging engine.'
37
36
  s.add_dependency 'diffy'
38
37
  s.add_dependency 'drb'
39
38
  s.add_dependency 'execjs', '~> 2.7'
40
- s.add_dependency 'haml', '~> 6.3.0'
41
- s.add_dependency 'haml-rails', '~> 2.1'
39
+ s.add_dependency 'haml', '>= 6.3', '< 7.4'
40
+ s.add_dependency 'haml-rails', '>= 2.1', '< 4.0'
42
41
  s.add_dependency 'highline', '>= 1.7.8', '< 3.2.0'
43
42
  s.add_dependency 'image_processing'
44
43
  s.add_dependency 'kraken-io'
@@ -46,13 +45,14 @@ a general purpose content management system--not merely a blogging engine.'
46
45
  s.add_dependency 'mini_racer'
47
46
  s.add_dependency 'mutex_m'
48
47
  s.add_dependency 'mysql2'
49
- s.add_dependency 'paper_trail', '~> 16.0.0'
48
+ s.add_dependency 'ostruct'
49
+ s.add_dependency 'paper_trail', '~> 17.0.0'
50
50
  s.add_dependency 'paper_trail-association_tracking', '>= 2.2.1', '< 2.4.0'
51
51
  s.add_dependency 'psych', '5.4.0'
52
52
  s.add_dependency 'rack', '>= 2.0.1', '< 3.2.0'
53
53
  s.add_dependency 'rack-cache', '~> 1.7'
54
54
  s.add_dependency 'radius', '~> 0.8'
55
- s.add_dependency 'rails', '~> 8.0.0'
55
+ s.add_dependency 'rails', '~> 8.1.0'
56
56
  s.add_dependency 'rake', '< 14.0'
57
57
  s.add_dependency 'ransack', '~> 4.2.1'
58
58
  s.add_dependency 'rdoc', '>= 5.1', '< 9.0'
data/yarn.lock CHANGED
@@ -1671,9 +1671,9 @@ fast-glob@^3.2.5, fast-glob@^3.2.9:
1671
1671
  micromatch "^4.0.8"
1672
1672
 
1673
1673
  fast-uri@^3.0.1:
1674
- version "3.1.4"
1675
- resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.4.tgz#3b3daf9ce68f41f956df0b505132c0cfce9ec7af"
1676
- integrity sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==
1674
+ version "3.1.5"
1675
+ resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.5.tgz#610f37419a030270430cecd68d74e3d4d96725d0"
1676
+ integrity sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==
1677
1677
 
1678
1678
  fastest-levenshtein@^1.0.12:
1679
1679
  version "1.0.16"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trusty-cms
3
3
  version: !ruby/object:Gem::Version
4
- version: '8.0'
4
+ version: 8.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - TrustyCms CMS dev team
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-08-07 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activestorage-validator
@@ -194,30 +193,42 @@ dependencies:
194
193
  name: haml
195
194
  requirement: !ruby/object:Gem::Requirement
196
195
  requirements:
197
- - - "~>"
196
+ - - ">="
198
197
  - !ruby/object:Gem::Version
199
- version: 6.3.0
198
+ version: '6.3'
199
+ - - "<"
200
+ - !ruby/object:Gem::Version
201
+ version: '7.4'
200
202
  type: :runtime
201
203
  prerelease: false
202
204
  version_requirements: !ruby/object:Gem::Requirement
203
205
  requirements:
204
- - - "~>"
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '6.3'
209
+ - - "<"
205
210
  - !ruby/object:Gem::Version
206
- version: 6.3.0
211
+ version: '7.4'
207
212
  - !ruby/object:Gem::Dependency
208
213
  name: haml-rails
209
214
  requirement: !ruby/object:Gem::Requirement
210
215
  requirements:
211
- - - "~>"
216
+ - - ">="
212
217
  - !ruby/object:Gem::Version
213
218
  version: '2.1'
219
+ - - "<"
220
+ - !ruby/object:Gem::Version
221
+ version: '4.0'
214
222
  type: :runtime
215
223
  prerelease: false
216
224
  version_requirements: !ruby/object:Gem::Requirement
217
225
  requirements:
218
- - - "~>"
226
+ - - ">="
219
227
  - !ruby/object:Gem::Version
220
228
  version: '2.1'
229
+ - - "<"
230
+ - !ruby/object:Gem::Version
231
+ version: '4.0'
221
232
  - !ruby/object:Gem::Dependency
222
233
  name: highline
223
234
  requirement: !ruby/object:Gem::Requirement
@@ -322,20 +333,34 @@ dependencies:
322
333
  - - ">="
323
334
  - !ruby/object:Gem::Version
324
335
  version: '0'
336
+ - !ruby/object:Gem::Dependency
337
+ name: ostruct
338
+ requirement: !ruby/object:Gem::Requirement
339
+ requirements:
340
+ - - ">="
341
+ - !ruby/object:Gem::Version
342
+ version: '0'
343
+ type: :runtime
344
+ prerelease: false
345
+ version_requirements: !ruby/object:Gem::Requirement
346
+ requirements:
347
+ - - ">="
348
+ - !ruby/object:Gem::Version
349
+ version: '0'
325
350
  - !ruby/object:Gem::Dependency
326
351
  name: paper_trail
327
352
  requirement: !ruby/object:Gem::Requirement
328
353
  requirements:
329
354
  - - "~>"
330
355
  - !ruby/object:Gem::Version
331
- version: 16.0.0
356
+ version: 17.0.0
332
357
  type: :runtime
333
358
  prerelease: false
334
359
  version_requirements: !ruby/object:Gem::Requirement
335
360
  requirements:
336
361
  - - "~>"
337
362
  - !ruby/object:Gem::Version
338
- version: 16.0.0
363
+ version: 17.0.0
339
364
  - !ruby/object:Gem::Dependency
340
365
  name: paper_trail-association_tracking
341
366
  requirement: !ruby/object:Gem::Requirement
@@ -424,14 +449,14 @@ dependencies:
424
449
  requirements:
425
450
  - - "~>"
426
451
  - !ruby/object:Gem::Version
427
- version: 8.0.0
452
+ version: 8.1.0
428
453
  type: :runtime
429
454
  prerelease: false
430
455
  version_requirements: !ruby/object:Gem::Requirement
431
456
  requirements:
432
457
  - - "~>"
433
458
  - !ruby/object:Gem::Version
434
- version: 8.0.0
459
+ version: 8.1.0
435
460
  - !ruby/object:Gem::Dependency
436
461
  name: rake
437
462
  requirement: !ruby/object:Gem::Requirement
@@ -639,9 +664,9 @@ executables:
639
664
  - trusty_cms
640
665
  extensions: []
641
666
  extra_rdoc_files:
642
- - README.md
643
667
  - INSTALL.md
644
668
  - LICENSE.md
669
+ - README.md
645
670
  files:
646
671
  - ".gitignore"
647
672
  - CODE_OF_CONDUCT.md
@@ -1137,7 +1162,6 @@ files:
1137
1162
  - lib/inheritable_class_attributes.rb
1138
1163
  - lib/login_system.rb
1139
1164
  - lib/method_observer.rb
1140
- - lib/ostruct.rb
1141
1165
  - lib/simpleton.rb
1142
1166
  - lib/string_extensions/string_extensions.rb
1143
1167
  - lib/symbol_extensions/symbol_extensions.rb
@@ -1351,7 +1375,6 @@ homepage: https://github.com/pgharts/trusty-cms
1351
1375
  licenses:
1352
1376
  - MIT
1353
1377
  metadata: {}
1354
- post_install_message:
1355
1378
  rdoc_options:
1356
1379
  - "--title"
1357
1380
  - TrustyCms -- Content Management You Can Trust
@@ -1399,8 +1422,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1399
1422
  - !ruby/object:Gem::Version
1400
1423
  version: 1.3.1
1401
1424
  requirements: []
1402
- rubygems_version: 3.5.11
1403
- signing_key:
1425
+ rubygems_version: 4.0.16
1404
1426
  specification_version: 4
1405
1427
  summary: A no-fluff content management system designed for small teams.
1406
1428
  test_files:
@@ -1427,6 +1449,7 @@ test_files:
1427
1449
  - spec/dummy/bin/rails
1428
1450
  - spec/dummy/bin/rake
1429
1451
  - spec/dummy/bin/setup
1452
+ - spec/dummy/config.ru
1430
1453
  - spec/dummy/config/application.rb
1431
1454
  - spec/dummy/config/boot.rb
1432
1455
  - spec/dummy/config/cable.yml
@@ -1453,7 +1476,6 @@ test_files:
1453
1476
  - spec/dummy/config/routes.rb
1454
1477
  - spec/dummy/config/secrets.yml
1455
1478
  - spec/dummy/config/storage.yml
1456
- - spec/dummy/config.ru
1457
1479
  - spec/dummy/db/migrate/20260729201444_add_service_name_to_active_storage_blobs.active_storage.rb
1458
1480
  - spec/dummy/db/migrate/20260729201445_create_active_storage_variant_records.active_storage.rb
1459
1481
  - spec/dummy/db/migrate/20260729201446_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb
data/lib/ostruct.rb DELETED
@@ -1,51 +0,0 @@
1
- # patching OpenStruct due to Ruby 2.3.1 upgrade
2
- # See more here: http://stackoverflow.com/questions/39278864/openstruct-issue-with-ruby-2-3-1/39280374#39280374
3
-
4
- class OpenStruct
5
- def initialize(hash = nil)
6
- @table = {}
7
- hash&.each_pair do |k, v|
8
- k = k.to_sym
9
- @table[k] = v
10
- new_ostruct_member(k)
11
- end
12
- end
13
-
14
- def modifiable
15
- begin
16
- @modifiable = true
17
- rescue StandardError
18
- raise RuntimeError, "can't modify frozen #{self.class}", caller(3)
19
- end
20
- @table
21
- end
22
- protected :modifiable
23
-
24
- def new_ostruct_member(name)
25
- name = name.to_sym
26
- unless respond_to?(name)
27
- define_singleton_method(name) { @table[name] }
28
- define_singleton_method("#{name}=") { |x| modifiable[name] = x }
29
- end
30
- name
31
- end
32
- protected :new_ostruct_member
33
-
34
- def method_missing(mid, *args) # :nodoc:
35
- mname = mid.id2name
36
- len = args.length
37
- if mname.chomp!('=')
38
- if len != 1
39
- raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
40
- end
41
-
42
- modifiable[new_ostruct_member(mname)] = args[0]
43
- elsif len == 0
44
- @table[mid]
45
- else
46
- err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args
47
- err.set_backtrace caller(1)
48
- raise err
49
- end
50
- end
51
- end