active_scaffold 4.2.2 → 4.2.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 +4 -4
- data/CHANGELOG.rdoc +7 -0
- data/app/assets/stylesheets/active_scaffold_layout.scss +7 -1
- data/lib/active_scaffold/bridges/logical_query_parser/keyword_query_parser.rb +23 -0
- data/lib/active_scaffold/bridges/logical_query_parser.rb +3 -2
- data/lib/active_scaffold/constraints.rb +37 -32
- data/lib/active_scaffold/data_structures/column.rb +1 -1
- data/lib/active_scaffold/finder.rb +9 -6
- data/lib/active_scaffold/helpers/search_column_helpers.rb +2 -2
- data/lib/active_scaffold/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d279597d030fea168fba4fbcc8cd44c99d02f44b4596c774ec4476db04d53cd1
|
|
4
|
+
data.tar.gz: 48fd530b7990ec28454a1b3adebd5da80ca1d833727b22563a85cef1e140747f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1317103cf2e2344d0340f76f020a7df076f7aedff8f07b1c0a19499338d2d7941e762c51b33757cbcf3cd039d0d9f8bc8b57653282098f23fadfc069fd631bf0
|
|
7
|
+
data.tar.gz: 1300926c2397ea724f788a2b9899397e6c1e0ec6ca5a55a77677edf93dc98e5ed70e1b742c9a6ee8618067e4c378e58899d18e0fba9514e41cbde943c5589c01
|
data/CHANGELOG.rdoc
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
= 4.2.3
|
|
2
|
+
- Make simplified searches on LogicalQueryParser bridge working with upstream gem, no need for my fork
|
|
3
|
+
- Styles for radio form_ui
|
|
4
|
+
- Fix style for checkbox list in subform
|
|
5
|
+
- Fix constraints (broken on 4.2.2 on some cases)
|
|
6
|
+
|
|
7
|
+
= 4.2.2
|
|
1
8
|
- Support setting form_ui_options with nil, for subforms
|
|
2
9
|
- Support saving when embedded on through singular association, as it's supported for nested too
|
|
3
10
|
|
|
@@ -750,6 +750,12 @@ float: left;
|
|
|
750
750
|
.active-scaffold li.form-element dd input[type="checkbox"] {
|
|
751
751
|
margin-top: 6px;
|
|
752
752
|
}
|
|
753
|
+
.active-scaffold form input[type=radio] {
|
|
754
|
+
margin-right: 5px;
|
|
755
|
+
}
|
|
756
|
+
.active-scaffold form label:has(input[type=radio]) {
|
|
757
|
+
margin-right: 10px;
|
|
758
|
+
}
|
|
753
759
|
|
|
754
760
|
.active-scaffold li.form-element dd .select-field:not(.draggable-lists-container) {
|
|
755
761
|
display: inline-block;
|
|
@@ -1039,7 +1045,7 @@ padding: 0 2px 2px 2px;
|
|
|
1039
1045
|
border: solid 1px;
|
|
1040
1046
|
}
|
|
1041
1047
|
|
|
1042
|
-
.active-scaffold .sub-form .checkbox-list
|
|
1048
|
+
.active-scaffold .sub-form .checkbox-list li {
|
|
1043
1049
|
display: block;
|
|
1044
1050
|
}
|
|
1045
1051
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'method_source'
|
|
4
|
+
|
|
5
|
+
class ActiveScaffold::Bridges::LogicalQueryParser
|
|
6
|
+
class KeywordQueryParser
|
|
7
|
+
LogicalQueryParser.singleton_methods.each do |method_name|
|
|
8
|
+
method = LogicalQueryParser.method(method_name)
|
|
9
|
+
define_method(method_name, &method)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Copy search method from LogicalQueryParser
|
|
13
|
+
class_eval(LogicalQueryParser.method(:search).source, __FILE__, __LINE__)
|
|
14
|
+
|
|
15
|
+
def initialize(operator)
|
|
16
|
+
@operator = operator
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def new
|
|
20
|
+
ActiveScaffold::Bridges::LogicalQueryParser::TokensGrammar::Parser.new(@operator)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class ActiveScaffold::Bridges::LogicalQueryParser < ActiveScaffold::DataStructures::Bridge
|
|
4
|
+
autoload :TokensGrammar, 'active_scaffold/bridges/logical_query_parser/tokens_grammar'
|
|
5
|
+
autoload :KeywordQueryParser, 'active_scaffold/bridges/logical_query_parser/keyword_query_parser'
|
|
6
|
+
|
|
4
7
|
def self.install
|
|
5
|
-
require File.join(File.dirname(__FILE__), 'logical_query_parser/tokens_grammar')
|
|
6
|
-
ActiveScaffold::Finder.send(:remove_const, :LOGICAL_COMPARATORS)
|
|
7
8
|
ActiveScaffold::Finder.const_set :LOGICAL_COMPARATORS, %w[all_tokens any_token logical].freeze
|
|
8
9
|
end
|
|
9
10
|
end
|
|
@@ -155,6 +155,41 @@ module ActiveScaffold
|
|
|
155
155
|
"Malformed constraint `#{klass}##{column_name}'. If it's a legitimate column, and you are using a nested scaffold, please specify or double-check the reverse association name."
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
+
def apply_constraint_on_association(record, association, value, allow_autosave: false)
|
|
159
|
+
if association.through_singular? && association.source_reflection.reverse
|
|
160
|
+
create_on_through_singular(record, association, association.klass.find(value))
|
|
161
|
+
elsif association.collection?
|
|
162
|
+
record.send(k.to_s).send(:<<, association.klass.find(value)) unless association.nested?
|
|
163
|
+
elsif association.polymorphic?
|
|
164
|
+
apply_constraint_on_polymorphic_association(record, association, value)
|
|
165
|
+
elsif !association.source_reflection&.through? && # regular singular association, or one-level through association
|
|
166
|
+
!value.is_a?(Array)
|
|
167
|
+
record.send(:"#{association.name}=", association.klass.find(value))
|
|
168
|
+
|
|
169
|
+
# setting the belongs_to side of a has_one isn't safe. if the has_one was already
|
|
170
|
+
# specified, rails won't automatically clear out the previous associated record.
|
|
171
|
+
#
|
|
172
|
+
# note that we can't take the extra step to correct this unless we're permitted to
|
|
173
|
+
# run operations where activerecord auto-saves the object.
|
|
174
|
+
reverse = association.reverse_association
|
|
175
|
+
if reverse&.singular? && !reverse.belongs_to? && allow_autosave
|
|
176
|
+
record.send(association.name).send(:"#{reverse.name}=", record)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def apply_constraint_on_polymorphic_association(record, association, value)
|
|
182
|
+
unless value.is_a?(Array) && value.size >= 2
|
|
183
|
+
raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(association), caller
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
if value.size == 2
|
|
187
|
+
record.send(:"#{association.name}=", value[0].constantize.find(value[1]))
|
|
188
|
+
else
|
|
189
|
+
record.send(:"#{association.foreign_type}=", value[0])
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
158
193
|
# Applies constraints to the given record.
|
|
159
194
|
#
|
|
160
195
|
# Searches through the known columns for association columns. If the given constraint is an association,
|
|
@@ -163,42 +198,12 @@ module ActiveScaffold
|
|
|
163
198
|
#
|
|
164
199
|
# For some operations ActiveRecord will automatically update the database. That's not always ok.
|
|
165
200
|
# If it *is* ok (e.g. you're in a transaction), then set :allow_autosave to true.
|
|
166
|
-
def apply_constraints_to_record(record,
|
|
167
|
-
options[:allow_autosave] = false if options[:allow_autosave].nil?
|
|
168
|
-
constraints = options[:constraints] || active_scaffold_constraints
|
|
169
|
-
|
|
201
|
+
def apply_constraints_to_record(record, allow_autosave: false, constraints: active_scaffold_constraints)
|
|
170
202
|
config = record.is_a?(active_scaffold_config.model) ? active_scaffold_config : active_scaffold_config_for(record.class)
|
|
171
203
|
constraints.each do |k, v|
|
|
172
204
|
column = config.columns[k]
|
|
173
205
|
if column&.association
|
|
174
|
-
|
|
175
|
-
create_on_through_singular(record, column.association, column.association.klass.find(v))
|
|
176
|
-
elsif column.association.collection?
|
|
177
|
-
record.send(k.to_s).send(:<<, column.association.klass.find(v)) unless column.association.nested?
|
|
178
|
-
elsif column.association.polymorphic?
|
|
179
|
-
unless v.is_a?(Array) && v.size >= 2
|
|
180
|
-
raise ActiveScaffold::MalformedConstraint, polymorphic_constraint_error(column.association), caller
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
if v.size == 2
|
|
184
|
-
record.send(:"#{k}=", v[0].constantize.find(v[1]))
|
|
185
|
-
else
|
|
186
|
-
record.send(:"#{column.association.foreign_type}=", v[0])
|
|
187
|
-
end
|
|
188
|
-
elsif !column.association.source_reflection&.through? && # regular singular association, or one-level through association
|
|
189
|
-
!v.is_a?(Array)
|
|
190
|
-
record.send(:"#{k}=", column.association.klass.find(v))
|
|
191
|
-
|
|
192
|
-
# setting the belongs_to side of a has_one isn't safe. if the has_one was already
|
|
193
|
-
# specified, rails won't automatically clear out the previous associated record.
|
|
194
|
-
#
|
|
195
|
-
# note that we can't take the extra step to correct this unless we're permitted to
|
|
196
|
-
# run operations where activerecord auto-saves the object.
|
|
197
|
-
reverse = column.association.reverse_association
|
|
198
|
-
if reverse&.singular? && !reverse.belongs_to? && options[:allow_autosave]
|
|
199
|
-
record.send(k).send(:"#{reverse.name}=", record)
|
|
200
|
-
end
|
|
201
|
-
end
|
|
206
|
+
apply_constraint_on_association(record, column.association, v, allow_autosave: allow_autosave)
|
|
202
207
|
else
|
|
203
208
|
record.send(:"#{k}=", v)
|
|
204
209
|
end
|
|
@@ -346,7 +346,7 @@ module ActiveScaffold::DataStructures
|
|
|
346
346
|
end
|
|
347
347
|
|
|
348
348
|
def searchable?
|
|
349
|
-
search_sql.present? || (logical_search.present? && ActiveScaffold::Finder
|
|
349
|
+
search_sql.present? || (logical_search.present? && ActiveScaffold::Finder.logical_comparators.present?)
|
|
350
350
|
end
|
|
351
351
|
|
|
352
352
|
def link
|
|
@@ -6,6 +6,10 @@ module ActiveScaffold
|
|
|
6
6
|
@@like_operator ||= ::ActiveRecord::Base.connection.adapter_name.in?(%w[PostgreSQL PostGIS]) ? 'ILIKE' : 'LIKE'
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
def self.logical_comparators
|
|
10
|
+
ActiveScaffold::Finder::LOGICAL_COMPARATORS if ActiveScaffold::Finder.const_defined? :LOGICAL_COMPARATORS
|
|
11
|
+
end
|
|
12
|
+
|
|
9
13
|
module ClassMethods
|
|
10
14
|
def self.extended(klass)
|
|
11
15
|
return unless klass.active_scaffold_config
|
|
@@ -231,21 +235,21 @@ module ActiveScaffold
|
|
|
231
235
|
['(%<search_sql>s BETWEEN ? AND ?)', value[:from], value[:to]]
|
|
232
236
|
elsif ActiveScaffold::Finder::NUMERIC_COMPARATORS.include?(value[:opt])
|
|
233
237
|
["%<search_sql>s #{value[:opt]} ?", value[:from]]
|
|
234
|
-
elsif ActiveScaffold::Finder
|
|
238
|
+
elsif ActiveScaffold::Finder.logical_comparators&.include?(value[:opt])
|
|
235
239
|
operator =
|
|
236
240
|
case value[:opt]
|
|
237
241
|
when 'all_tokens' then 'AND'
|
|
238
242
|
when 'any_token' then 'OR'
|
|
239
243
|
end
|
|
240
|
-
parser = ActiveScaffold::Bridges::LogicalQueryParser::
|
|
241
|
-
[logical_search_condition(column, value[:from], parser)]
|
|
244
|
+
parser = ActiveScaffold::Bridges::LogicalQueryParser::KeywordQueryParser.new(operator) if operator
|
|
245
|
+
[logical_search_condition(column, value[:from], parser || ::LogicalQueryParser)]
|
|
242
246
|
end
|
|
243
247
|
end
|
|
244
248
|
|
|
245
|
-
def logical_search_condition(column, search, parser
|
|
249
|
+
def logical_search_condition(column, search, parser)
|
|
246
250
|
model = column.active_record_class
|
|
247
251
|
subquery = alias_query_for_same_table_exists(model.all) if column.logical_search.any?(Hash)
|
|
248
|
-
query =
|
|
252
|
+
query = parser.search(search, subquery || model, column.logical_search)
|
|
249
253
|
if subquery
|
|
250
254
|
model.where(same_table_exists_subquery(query))
|
|
251
255
|
else
|
|
@@ -526,7 +530,6 @@ module ActiveScaffold
|
|
|
526
530
|
doesnt_begin_with: 'not_?%',
|
|
527
531
|
doesnt_end_with: 'not_%?'
|
|
528
532
|
}.freeze
|
|
529
|
-
LOGICAL_COMPARATORS = [].freeze
|
|
530
533
|
NULL_COMPARATORS = %w[null not_null].freeze
|
|
531
534
|
DATE_COMPARATORS = %w[PAST FUTURE RANGE].freeze
|
|
532
535
|
DATE_UNITS = %w[DAYS WEEKS MONTHS YEARS].freeze
|
|
@@ -213,8 +213,8 @@ module ActiveScaffold
|
|
|
213
213
|
if column.search_sql.present?
|
|
214
214
|
select_options.concat(ActiveScaffold::Finder::STRING_COMPARATORS.collect { |title, comp| [as_(title), comp] })
|
|
215
215
|
end
|
|
216
|
-
if ActiveScaffold::Finder
|
|
217
|
-
select_options.concat(ActiveScaffold::Finder
|
|
216
|
+
if ActiveScaffold::Finder.logical_comparators.present? && column.logical_search.present?
|
|
217
|
+
select_options.concat(ActiveScaffold::Finder.logical_comparators.collect { |comp| [as_(comp.downcase.to_sym), comp] })
|
|
218
218
|
end
|
|
219
219
|
end
|
|
220
220
|
if column.search_sql.present?
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_scaffold
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.2.
|
|
4
|
+
version: 4.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Many, see README
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: dartsass-sprockets
|
|
@@ -38,6 +38,20 @@ dependencies:
|
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0.11'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: method_source
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.1'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.1'
|
|
41
55
|
- !ruby/object:Gem::Dependency
|
|
42
56
|
name: rails
|
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -242,6 +256,7 @@ files:
|
|
|
242
256
|
- lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb
|
|
243
257
|
- lib/active_scaffold/bridges/file_column/test/mock_model.rb
|
|
244
258
|
- lib/active_scaffold/bridges/logical_query_parser.rb
|
|
259
|
+
- lib/active_scaffold/bridges/logical_query_parser/keyword_query_parser.rb
|
|
245
260
|
- lib/active_scaffold/bridges/logical_query_parser/tokens_grammar.rb
|
|
246
261
|
- lib/active_scaffold/bridges/logical_query_parser/tokens_grammar.treetop
|
|
247
262
|
- lib/active_scaffold/bridges/paper_trail.rb
|