active_scaffold 4.4.0 → 4.4.1

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: cafbb1cbb0273e33d48ba6efb723a4ac6abd3678c559031bbc10d1b608f61ad5
4
- data.tar.gz: 7e835a08a8b21df39301360a62db0257826b5e1a654c18ef2e8fbc92d4278436
3
+ metadata.gz: 62f92c20382d4b5a33b53bb1525e677d81259a2d89a51996caefcb68ab314ed2
4
+ data.tar.gz: 2b8b5f59b6bdf856af6bdb4cfd5697caca0095960c41278bdb16ea5d51e0d03b
5
5
  SHA512:
6
- metadata.gz: 475d62edc638cfefd7d43bf86a033d842f387968d9e90fc83b61b3da5cfc3f688e3ab8ee200ba7a56f7cebfe9659ad108494618207104ff65b1c9bad67a738c9
7
- data.tar.gz: b4eb39a97611806f10c625111a41aa67061d35093c5caae3f89673516f3785c1692d04a3e87de3f7e8174a0b286818c10a253ec449d10f1ab8aada1ef1547cbd
6
+ metadata.gz: cffce904d4531775442f630fe004153a6ff602fdf7d1d416601712038324d0ad27b75c0e075dca01cefe0cc05d103769de538c2295ae5ab0d670a85944bf59c7
7
+ data.tar.gz: d7b32cbea9ac2da0d506de89ccd6dd5fbfefd7f3565780e4c93d97308bf2e1808d3a4bf396e63d7f7aeaedef7b72efaa2dd03c1d9f63fb7f49390a23382e8bdf
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,10 @@
1
+ = 4.4.1
2
+ - Avoid unnecessary DISTINCT in searches without joins or with only belongs_to joins, fixing PostgreSQL searches on models with json columns
3
+ - Update install generator for the supported rails versions and asset pipelines
4
+ - Fix rendering field descriptions and tabbed forms when custom input helpers return frozen strings
5
+ - Fix inline action links with rails-ujs on Rails 8.1 by inserting the raw HTML response instead of its parsed Document
6
+ - Preserve nested ActiveScaffold session changes with activerecord-session_store 2.3.0
7
+
1
8
  = 4.4.0
2
9
  - Add support for local sorting using JS when the list has no pagination
3
10
  - Add UI rendering customization for CSS framework and theme integration: configure tags and HTML attributes for named elements, use context-aware procs, and override focused helpers when structural markup must change
data/README.md CHANGED
@@ -41,11 +41,9 @@ Add jquery-rails to Gemfile, or handle jquery with other tools like webpack or i
41
41
  gem 'jquery-rails'
42
42
  ```
43
43
 
44
- For rails 7.x, install generator will add `active_scaffold` to `config/importmap.rb`, `app/javascript/application.js`, and `active_scaffold/manifest.js` to `app/assets/config/manifest.js`. It will add `jquery` and `jquery_ujs` to all the 3 files if jquery-rails gem is available.
44
+ On supported Rails versions (7.2 and 8.x), the install generator adds the ActiveScaffold route concerns and the lines required to load its JavaScript and stylesheets for the detected asset pipeline. With import maps, this includes both the pins in `config/importmap.rb` and the imports in `app/javascript/application.js`. With Propshaft, it adds the required helpers to the application layout; with Sprockets, it updates the asset manifests instead.
45
45
 
46
- For rails 6.1, install generator will create `app/assets/javascripts/application.js`, add it, and `active_scaffold/manifest.js`, to `app/assets/config/manifest.js` and add `javascript_include_tag` in the layout, as ActiveScaffold doesn't work with webpack. It will add `jquery` to `app/assets/javascripts/application.js` too if query-rails gem is available, although Jquery may be loaded by packs too and it will work, it won't add `jquery_ujs` or `@rails/ujs` as it's added to `app/javascript/packs/application.js` by default.
47
-
48
- -- TODO: Add notes about dartsass-rails for propshaft or dartsass-sprockets for sprockets.
46
+ For Dart Sass, the generator adds the appropriate `@use` line to `app/assets/stylesheets/application.scss`. It can also update an older `application.css` or `application.css.erb` that contains Sprockets require directives. If `jquery-rails` is installed, the generator adds `jquery` and `jquery_ujs` to the same JavaScript setup. The exact lines for each supported setup are described in [Stylesheet Loading](#stylesheet-loading) and [Javascript Loading](#javascript-loading).
49
47
 
50
48
  Run the following commands
51
49
 
@@ -131,7 +129,7 @@ In the layout, load the importmap modules and call active_scaffold_javascript_ta
131
129
  <%= active_scaffold_javascript_tag %>
132
130
  ```
133
131
 
134
- ### Propshaft
132
+ ### Propshaft without import maps
135
133
 
136
134
  If you're not using importmaps, then you can load the JS files individually, but you only need to load jquery and jquery_ujs or rails_ujs, and then call active_scaffold_javascript_tag:
137
135
 
@@ -1339,7 +1339,12 @@
1339
1339
  return true;
1340
1340
  });
1341
1341
  jQuery(document).on('ajax:success', 'a.as_action', function(event, response) {
1342
- if (event.detail && !response) response = event.detail[0];
1342
+ if (event.detail && !response) {
1343
+ response = event.detail[0];
1344
+ // rails-ujs parses text/html responses into a Document, which cannot be inserted and
1345
+ // loses table rows parsed outside a table, so use the raw response from the XHR.
1346
+ if (response instanceof Document && event.detail[2]) response = event.detail[2].responseText;
1347
+ }
1343
1348
  var action_link = ActiveScaffold.ActionLink.get(jQuery(this));
1344
1349
  if (action_link) {
1345
1350
  if (action_link.position) {
@@ -35,7 +35,7 @@ module ActiveScaffold::Actions
35
35
  end
36
36
 
37
37
  def set_outer_joins_for_search(columns) # rubocop:disable Naming/AccessorMethodName
38
- active_scaffold_outer_joins.concat columns.flat_map(&:search_joins).uniq
38
+ active_scaffold_outer_joins.concat columns.flat_map(&:search_joins).compact.uniq
39
39
  end
40
40
 
41
41
  def store_search_params_into_session
@@ -57,6 +57,12 @@ module ActiveScaffold
57
57
  require 'active_scaffold/extensions/paginator_extensions'
58
58
  end
59
59
 
60
+ initializer 'active_scaffold.active_record_session_store', after: :load_config_initializers do |app|
61
+ require 'active_scaffold/extensions/active_record_session_store'
62
+ extension = ActiveScaffold::Extensions::ActiveRecordSessionStore
63
+ ActiveScaffold::Core.prepend(extension::Core) if extension.affected?(app)
64
+ end
65
+
60
66
  initializer 'active_scaffold.assets' do |app|
61
67
  if defined?(::Sprockets)
62
68
  # Tell sprockets where your assets are located
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveScaffold
4
+ module Extensions
5
+ module ActiveRecordSessionStore
6
+ AFFECTED_VERSION = Gem::Version.new('2.3.0')
7
+
8
+ # activerecord-session_store 2.3.0 keeps references to nested values in
9
+ # the request session, so in-place changes can also alter the value used
10
+ # for dirty comparison. Keep ActiveScaffold's request storage detached.
11
+ module Core
12
+ def active_scaffold_session_storage(id = nil)
13
+ session_index = active_scaffold_session_storage_key(id)
14
+ @active_scaffold_session_storage ||= {}
15
+
16
+ storage = @active_scaffold_session_storage[session_index]
17
+ return storage if storage && session[session_index].equal?(storage)
18
+
19
+ storage = session[session_index]&.deep_dup || {}
20
+ session[session_index] = storage
21
+ @active_scaffold_session_storage[session_index] = storage
22
+ end
23
+ end
24
+
25
+ def self.affected?(application = Rails.application)
26
+ store_class = active_record_store
27
+ version = session_store_version
28
+ return false unless store_class && version
29
+
30
+ configured_store = application.config.session_store
31
+ uses_active_record_store =
32
+ configured_store == store_class ||
33
+ (configured_store.is_a?(Class) && configured_store < store_class)
34
+
35
+ uses_active_record_store && Gem::Version.new(version) == AFFECTED_VERSION
36
+ end
37
+
38
+ def self.active_record_store
39
+ ::ActionDispatch::Session::ActiveRecordStore if defined?(::ActionDispatch::Session::ActiveRecordStore)
40
+ end
41
+ private_class_method :active_record_store
42
+
43
+ def self.session_store_version
44
+ ::ActiveRecord::SessionStore::VERSION if defined?(::ActiveRecord::SessionStore::VERSION)
45
+ end
46
+ private_class_method :session_store_version
47
+ end
48
+ end
49
+ end
@@ -776,7 +776,14 @@ module ActiveScaffold
776
776
  end
777
777
 
778
778
  def distinct_query?(options)
779
- options[:left_outer_joins].present? || options[:left_joins].present?
779
+ joins = [options[:left_outer_joins], options[:left_joins]].flatten.compact
780
+ model = active_scaffold_config.model
781
+
782
+ joins.any? do |join|
783
+ next true unless join.is_a?(Symbol)
784
+
785
+ model.reflect_on_association(join)&.macro != :belongs_to
786
+ end
780
787
  end
781
788
 
782
789
  def joins_for_finder
@@ -259,12 +259,12 @@ module ActiveScaffold
259
259
  if column.association.nil? || column.association.belongs_to?
260
260
  # hidden field probably not needed, but leaving it just in case
261
261
  # but it isn't working for assocations which are not belongs_to
262
- field << hidden_field(:record, column.association&.foreign_key || column.name, column_options)
262
+ field = safe_join([field, hidden_field(:record, column.association&.foreign_key || column.name, column_options)])
263
263
  end
264
264
  else
265
265
  field ||= active_scaffold_input_for column, scope, column_options, form_columns: form_columns
266
266
  end
267
- field << loading_indicator_tag(action: :render_field, id: params[:id]) if field && column.update_columns
267
+ field = safe_join([field, loading_indicator_tag(action: :render_field, id: params[:id])]) if field && column.update_columns
268
268
  description = column_description(column, record, scope)
269
269
 
270
270
  label = label_tag(label_for(column, column_options), form_column_label(column, record, scope))
@@ -273,7 +273,7 @@ module ActiveScaffold
273
273
  end
274
274
 
275
275
  def form_attribute_html(column, label, field, description, attributes, collapsible_id: nil)
276
- (field ||= h('')) << description if description.present?
276
+ field = safe_join([field, description].compact) if description.present?
277
277
  context = {column: column}
278
278
  as_element :form_attribute, proc_options: context, **attributes do
279
279
  as_element(:form_attribute_label, label, proc_options: context) <<
@@ -10,9 +10,11 @@ module ActiveScaffold
10
10
  tab_options = send(override_helper_per_model(:active_scaffold_tab_options, record.class), column, record)
11
11
  used_tabs = send(override_helper_per_model(:active_scaffold_current_tabs, record.class), column, record, tab_options)
12
12
  input_helper = override_helper_per_model(:active_scaffold_input_for_tabbed, record.class)
13
- send(input_helper, column, record, subsection_id, tab_options, used_tabs.map { |v, _| v }) <<
14
- active_scaffold_refresh_link(nil, {'data-update_url' => url_for(add_tab_url)}, record, refresh_opts) <<
15
- active_scaffold_tabs_for(column, record, subsection_id, tab_options, used_tabs, &)
13
+ safe_join([
14
+ send(input_helper, column, record, subsection_id, tab_options, used_tabs.map { |v, _| v }),
15
+ active_scaffold_refresh_link(nil, {'data-update_url' => url_for(add_tab_url)}, record, refresh_opts),
16
+ active_scaffold_tabs_for(column, record, subsection_id, tab_options, used_tabs, &)
17
+ ])
16
18
  end
17
19
 
18
20
  def active_scaffold_input_for_tabbed(column, record, subsection_id, tab_options, used_tabs)
@@ -4,7 +4,7 @@ module ActiveScaffold
4
4
  module Version
5
5
  MAJOR = 4
6
6
  MINOR = 4
7
- PATCH = 0
7
+ PATCH = 1
8
8
  FIX = nil
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, FIX].compact.join('.')
@@ -1,11 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rails/generators/base'
4
- # require 'generators/active_scaffold_controller/active_scaffold_controller_generator'
5
4
 
6
5
  module ActiveScaffold
7
6
  module Generators
8
7
  class InstallGenerator < Rails::Generators::Base
8
+ IMPORTMAP = 'config/importmap.rb'
9
+ JS_ASSET = 'app/assets/javascripts/application.js'
10
+ JS_APP = 'app/javascript/application.js'
11
+ LAYOUT = 'app/views/layouts/application.html.erb'
12
+ MANIFEST = 'app/assets/config/manifest.js'
13
+ SCSS_ASSET = 'app/assets/stylesheets/application.scss'
14
+ CSS_ASSETS = %w[app/assets/stylesheets/application.css app/assets/stylesheets/application.css.erb].freeze
15
+
9
16
  def self.base_root
10
17
  File.expand_path '../..', __dir__
11
18
  end
@@ -15,151 +22,249 @@ module ActiveScaffold
15
22
  route 'concern :active_scaffold_association, ActiveScaffold::Routing::Association.new'
16
23
  end
17
24
 
18
- IMPORTMAP = 'config/importmap.rb'
19
- JS_ASSET = 'app/assets/javascripts/application.js'
20
- JS_APP = 'app/javascript/application.js'
21
- MANIFEST = 'app/assets/config/manifest.js'
22
-
23
25
  def add_javascript
24
26
  if File.exist?(IMPORTMAP)
25
- add_to_importmap
26
- add_to_js_app
27
- elsif File.exist?(JS_ASSET) # rails 6.1
28
- original_js = File.binread(JS_ASSET)
29
- if original_js.include?('require active_scaffold')
30
- say_status('skipped', "insert into #{JS_ASSET}", :yellow)
31
- else
32
- insert_into_file JS_ASSET, after: %r{//= require +.*ujs['"]?\n} do
33
- "//= require active_scaffold\n"
34
- end
35
- add_to_manifest 'active_scaffold/manifest.js'
36
- end
37
- setup_jquery JS_ASSET, original_js
27
+ add_importmap_javascript
28
+ elsif use_sprockets_javascript?
29
+ add_sprockets_javascript
30
+ elsif propshaft? || File.exist?(JS_APP)
31
+ add_propshaft_javascript_tags
38
32
  else
39
- create_javascript_manifest JS_ASSET
33
+ raise Thor::Error, 'Unable to configure ActiveScaffold JavaScript: no import map, Propshaft setup, ' \
34
+ "#{JS_APP}, or #{JS_ASSET} was found"
40
35
  end
41
36
  end
42
37
 
43
- def add_to_stylesheet_manifest
44
- file = 'app/assets/stylesheets/application.css'
45
- return unless File.exist?(file)
46
-
47
- original_css = File.binread(file)
48
- if original_css.match?(/require active_scaffold$/)
49
- say_status('skipped', 'insert into app/assets/stylesheets/application.css', :yellow)
38
+ def add_stylesheet
39
+ if File.exist?(SCSS_ASSET)
40
+ add_to_scss_asset
50
41
  else
51
- insert_into_file 'app/assets/stylesheets/application.css', before: %r{ *\*/} do
52
- " *= require active_scaffold\n"
53
- end
42
+ add_to_css_asset
54
43
  end
55
44
  end
56
45
 
57
46
  protected
58
47
 
48
+ def add_importmap_javascript
49
+ unless File.exist?(JS_APP)
50
+ raise Thor::Error, "Unable to configure import maps: #{JS_APP} does not exist"
51
+ end
52
+
53
+ add_to_importmap
54
+ add_to_js_app
55
+ add_importmap_layout_tags if propshaft?
56
+ end
57
+
59
58
  def add_to_importmap
60
59
  original_js = File.binread(IMPORTMAP)
61
- if original_js.match?(/^pin +['"]active_scaffold['"](?=,|$)/)
60
+ pin = propshaft? ? "pin 'active_scaffold', to: 'active_scaffold/load.js'" : "pin 'active_scaffold'"
61
+ current_pin = original_js[/^pin +['"]active_scaffold['"].*$/, 0]
62
+ if current_pin == pin
62
63
  say_status('skipped', "append active_scaffold to #{IMPORTMAP}", :yellow)
64
+ elsif current_pin && generated_active_scaffold_pin?(current_pin)
65
+ gsub_file IMPORTMAP, current_pin, pin
63
66
  else
64
- append_to_file IMPORTMAP do
65
- "pin 'active_scaffold'\n"
66
- end
67
+ append_to_file IMPORTMAP, "#{pin}\n"
67
68
  end
68
- if Object.const_defined?(:Jquery)
69
- if original_js.match?(/^pin +['"]jquery['"](?=,|$)/)
70
- say_status('skipped', "append jquery to #{IMPORTMAP}", :yellow)
71
- else
72
- append_to_file IMPORTMAP do
73
- "pin 'jquery'\n"
74
- end
75
- end
76
- if original_js.match?(%r{^pin +['"](jquery_ujs|@rails/ujs)['"](?=,|$)})
77
- say_status('skipped', "append jquery_ujs to #{IMPORTMAP}", :yellow)
78
- else
79
- append_to_file IMPORTMAP do
80
- "pin 'jquery_ujs'\n"
81
- end
82
- end
69
+
70
+ if jquery?
71
+ add_importmap_pin original_js, 'jquery'
72
+ add_importmap_pin original_js, 'jquery_ujs', alternatives: ['@rails/ujs']
83
73
  else
84
- say_status('missing', 'no jquery-rails gem, load jquery, and jquery_ujs or @rails/ujs, in your layout, or add jquery-rails ' \
85
- "to Gemfile and add pin \"jquery\" and pin \"jquery_ujs\" or pin \"@rails/ujs\", to #{IMPORTMAP}", :red)
74
+ say_status('missing', 'no jquery-rails gem; load jquery and jquery_ujs or @rails/ujs manually', :red)
86
75
  end
87
76
  end
88
77
 
89
- def add_to_js_app
90
- original_js = File.binread(JS_APP)
91
- if original_js.match?(/^import +['"]active_scaffold['"]/)
92
- say_status('skipped', "append active_scaffold to #{JS_APP}", :yellow)
78
+ def add_importmap_pin(original_js, name, alternatives: [])
79
+ names = [name, *alternatives].map { |item| Regexp.escape(item) }.join('|')
80
+ if original_js.match?(/^pin +['"](?:#{names})['"](?=,|$)/)
81
+ say_status('skipped', "append #{name} to #{IMPORTMAP}", :yellow)
93
82
  else
94
- append_to_file JS_APP do
95
- "import 'active_scaffold'\n"
96
- end
83
+ append_to_file IMPORTMAP, "pin '#{name}'\n"
97
84
  end
98
- manifest = ['active_scaffold/manifest.js']
99
- if Object.const_defined?(:Jquery)
100
- if original_js.match?(/^import +['"]jquery['"]/)
101
- say_status('skipped', "append jquery to #{JS_APP}", :yellow)
102
- else
103
- manifest << 'jquery.js'
104
- insert_into_file JS_APP, before: /import +['"]active_scaffold['"]\n/ do
105
- "import 'jquery'\n"
106
- end
85
+ end
86
+
87
+ def generated_active_scaffold_pin?(pin)
88
+ pin.match?(%r{\Apin +['"]active_scaffold['"](?:, *to: *['"]active_scaffold/load\.js['"])?\z})
89
+ end
90
+
91
+ def add_to_js_app
92
+ original_js = File.binread(JS_APP)
93
+ add_js_import original_js, 'active_scaffold'
94
+ manifest_files = ['active_scaffold/manifest.js']
95
+
96
+ if jquery?
97
+ unless js_import?(original_js, 'jquery')
98
+ add_js_import original_js, 'jquery', before: 'active_scaffold'
99
+ manifest_files << 'jquery.js'
107
100
  end
108
- if original_js.match?(%r{^import +(['"]jquery_ujs['"]|Rails from ['"]@rails/ujs['"])})
109
- say_status('skipped', "append jquery_ujs to #{JS_APP}", :yellow)
110
- else
111
- manifest << 'jquery_ujs.js'
112
- insert_into_file JS_APP, before: /import +['"]active_scaffold['"]\n/ do
113
- "import 'jquery_ujs'\n"
114
- end
101
+ unless original_js.match?(%r{^import +(['"]jquery_ujs['"]|Rails from ['"]@rails/ujs['"])})
102
+ add_js_import original_js, 'jquery_ujs', before: 'active_scaffold'
103
+ manifest_files << 'jquery_ujs.js'
115
104
  end
116
105
  end
117
- add_to_manifest(*manifest)
118
- end
119
-
120
- def create_javascript_manifest(file)
121
- FileUtils.mkdir_p File.dirname(file)
122
- js_content = "// This is a manifest file that'll be compiled into application.js, which will include all the files
123
- // listed below.
124
- //
125
- // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
126
- // vendor/assets/javascripts directory can be referenced here using a relative path.
127
- //
128
- // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
129
- // compiled file. JavaScript code in this file should be added after the last require_* statement.
130
- //
131
- // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
132
- // about supported directives.
133
- //
134
- //= require active_scaffold
135
- "
136
- File.open(file, 'w') { |f| f << js_content } unless options[:pretend]
137
- say_status('create', file)
138
- insert_into_file 'app/views/layouts/application.html.erb', after: /javascript_pack_tag 'application'.*\n/ do
139
- " <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', 'data-turbo-track': 'reload' %>\n"
140
- end
141
- add_to_manifest 'application.js', 'active_scaffold/manifest.js'
142
- setup_jquery file, js_content, where: 'active_scaffold'
106
+
107
+ add_to_manifest(*manifest_files) if sprockets?
108
+ end
109
+
110
+ def add_js_import(original_js, name, before: nil)
111
+ if js_import?(original_js, name)
112
+ say_status('skipped', "add #{name} to #{JS_APP}", :yellow)
113
+ elsif before
114
+ insert_into_file JS_APP, "import '#{name}'\n", before: /^import +['"]#{Regexp.escape(before)}['"]\n/
115
+ else
116
+ append_to_file JS_APP, "import '#{name}'\n"
117
+ end
118
+ end
119
+
120
+ def js_import?(content, name)
121
+ content.match?(/^import +['"]#{Regexp.escape(name)}['"]/)
122
+ end
123
+
124
+ def add_importmap_layout_tags
125
+ tags = []
126
+ content = layout_content
127
+ tags << '<%= javascript_importmap_tags %>' unless content.include?('javascript_importmap_tags')
128
+ tags << '<%= active_scaffold_javascript_tag %>' unless content.include?('active_scaffold_javascript_tag')
129
+ add_layout_tags tags
130
+ end
131
+
132
+ def add_propshaft_javascript_tags
133
+ tags = []
134
+ content = layout_content
135
+ if jquery? && !content.match?(/javascript_include_tag .*jquery/)
136
+ tags << "<%= javascript_include_tag 'jquery', 'jquery_ujs' %>"
137
+ elsif !jquery?
138
+ say_status('missing', 'no jquery-rails gem; load jquery and jquery_ujs or @rails/ujs in the layout', :red)
139
+ end
140
+ tags << '<%= active_scaffold_javascript_tag %>' unless content.include?('active_scaffold_javascript_tag')
141
+ add_layout_tags tags
142
+ end
143
+
144
+ def layout_content
145
+ unless File.exist?(LAYOUT)
146
+ raise Thor::Error, "Unable to configure ActiveScaffold JavaScript: #{LAYOUT} does not exist"
147
+ end
148
+
149
+ File.binread(LAYOUT)
150
+ end
151
+
152
+ def add_layout_tags(tags)
153
+ return if tags.empty?
154
+
155
+ content = File.binread(LAYOUT)
156
+ unless content.include?('</head>')
157
+ raise Thor::Error, "Unable to configure ActiveScaffold JavaScript: no </head> tag found in #{LAYOUT}"
158
+ end
159
+
160
+ insert_into_file LAYOUT, tags.map { |tag| " #{tag}\n" }.join, before: %r{^[ \t]*</head>}
161
+ end
162
+
163
+ def add_sprockets_javascript
164
+ original_js = File.binread(JS_ASSET)
165
+ unless original_js.match?(%r{//= require +active_scaffold(?:\s|$)})
166
+ append_to_file JS_ASSET, "\n//= require active_scaffold\n"
167
+ end
168
+ setup_sprockets_jquery original_js
169
+ add_to_manifest 'active_scaffold/manifest.js'
170
+ end
171
+
172
+ def use_sprockets_javascript?
173
+ File.exist?(JS_ASSET) && (sprockets? || (!propshaft? && !File.exist?(JS_APP)))
174
+ end
175
+
176
+ def setup_sprockets_jquery(original_js)
177
+ if jquery?
178
+ return if original_js.match?(%r{//= require +jquery(?:\s|$)})
179
+
180
+ insert_into_file JS_ASSET, "//= require jquery\n", before: %r{//= require +active_scaffold(?:\s|$)}
181
+ else
182
+ say_status('missing', 'no jquery-rails gem; load jquery manually before ActiveScaffold', :red)
183
+ end
143
184
  end
144
185
 
145
186
  def add_to_manifest(*files)
146
- append_to_file MANIFEST do
147
- files.map { |file| "//= link #{file}\n" }.join
187
+ original_manifest = File.exist?(MANIFEST) ? File.binread(MANIFEST) : ''
188
+ files.each do |file|
189
+ next if original_manifest.match?(%r{^//= link #{Regexp.escape(file)}$})
190
+
191
+ append_to_file MANIFEST, "//= link #{file}\n"
148
192
  end
149
193
  end
150
194
 
151
- def setup_jquery(file, original_js = nil, where: 'ujs')
152
- original_js ||= File.binread(file)
153
- if Object.const_defined?(:Jquery)
154
- unless original_js.include?('require jquery')
155
- insert_into_file file, before: %r{//= require +.*#{where}['"]?\n} do
156
- "//= require jquery\n"
157
- end
158
- end
195
+ def add_to_scss_asset
196
+ dependency = scss_dependency
197
+ unless dependency
198
+ say_status('missing', "could not detect dartsass-rails or dartsass-sprockets; update #{SCSS_ASSET} manually", :red)
199
+ return
200
+ end
201
+
202
+ original_scss = File.binread(SCSS_ASSET)
203
+ if original_scss.match?(%r{^@use +['"]active_scaffold(?:/core)?['"]})
204
+ say_status('skipped', "add ActiveScaffold to #{SCSS_ASSET}", :yellow)
205
+ else
206
+ prepend_to_file SCSS_ASSET, "@use '#{dependency}';\n"
207
+ end
208
+ end
209
+
210
+ def scss_dependency
211
+ if gem_loaded?('dartsass-sprockets')
212
+ 'active_scaffold'
213
+ elsif gem_loaded?('dartsass-rails')
214
+ 'active_scaffold/core'
215
+ end
216
+ end
217
+
218
+ def add_to_css_asset
219
+ file = CSS_ASSETS.find do |path|
220
+ File.exist?(path) && File.binread(path).match?(/\*= require(?:_tree)?\b/)
221
+ end
222
+ unless file
223
+ say_status('missing', 'no Dart Sass entrypoint or Sprockets stylesheet manifest found', :red)
224
+ return
225
+ end
226
+
227
+ original_css = File.binread(file)
228
+ if original_css.match?(/\*= require +active_scaffold(?:\s|$)/)
229
+ say_status('skipped', "add ActiveScaffold to #{file}", :yellow)
159
230
  else
160
- say_status('missing', 'no jquery-rails gem, load jquery in your layout, or add jquery-rails to Gemfile and add //= require jquery to application.js', :red)
231
+ insert_into_file file, " *= require active_scaffold\n", after: /^[ \t]*\*= require(?:_tree)?\b.*\n/
161
232
  end
162
233
  end
234
+
235
+ def propshaft?
236
+ asset_pipeline == :propshaft
237
+ end
238
+
239
+ def sprockets?
240
+ asset_pipeline == :sprockets
241
+ end
242
+
243
+ def asset_pipeline
244
+ return :propshaft if propshaft_active?
245
+ return :sprockets if sprockets_active?
246
+ return :propshaft if gem_loaded?('propshaft')
247
+
248
+ :sprockets if gem_loaded?('sprockets-rails')
249
+ end
250
+
251
+ def propshaft_active?
252
+ defined?(Propshaft::Assembly) && Rails.application.respond_to?(:assets) &&
253
+ Rails.application.assets.is_a?(Propshaft::Assembly)
254
+ end
255
+
256
+ def sprockets_active?
257
+ defined?(Sprockets::Environment) && Rails.application.respond_to?(:assets) &&
258
+ Rails.application.assets.is_a?(Sprockets::Environment)
259
+ end
260
+
261
+ def jquery?
262
+ Object.const_defined?(:Jquery)
263
+ end
264
+
265
+ def gem_loaded?(name)
266
+ Gem.loaded_specs.key?(name)
267
+ end
163
268
  end
164
269
  end
165
270
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_scaffold
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
4
+ version: 4.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Many, see README
@@ -325,6 +325,7 @@ files:
325
325
  - lib/active_scaffold/extensions/action_controller_rendering.rb
326
326
  - lib/active_scaffold/extensions/action_controller_rescueing.rb
327
327
  - lib/active_scaffold/extensions/action_view_rendering.rb
328
+ - lib/active_scaffold/extensions/active_record_session_store.rb
328
329
  - lib/active_scaffold/extensions/connection_adapter.rb
329
330
  - lib/active_scaffold/extensions/ice_nine.rb
330
331
  - lib/active_scaffold/extensions/localize.rb