effective_resources 2.1.4 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/concerns/acts_as_purchasable_wizard.rb +1 -0
- data/app/models/effective/resources/forms.rb +4 -4
- data/app/models/effective/resources/relation.rb +238 -169
- data/app/models/effective/resources/sql.rb +9 -0
- data/lib/effective_resources/version.rb +1 -1
- data/lib/effective_resources.rb +6 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 570e952fca070a0e231d90c8f959a80055d6a32e0b1ec51e93ae9c88d90fd44a
|
4
|
+
data.tar.gz: c7b247bfb4f12f6368405ac21f0a8591dc5e000d3f4a02c2daf728489d171128
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb7ee9c3d1be22a10ad2b2d2b24e21a4af3bb084f8bdf07b484f67922ea68553bb31410562029e6b762076eec1bd6bf9eb510734c3c2c35f4c31d768479443a9
|
7
|
+
data.tar.gz: 1e905d78f87ddac0bfb423ad153c1066f9925739bf7f454296b9554c6c4ef6ff4a147b125f98b1a0cddeab61bfaa7e2f710d0121e7376ca7f03b62e2e7b9a09c
|
@@ -73,13 +73,13 @@ module Effective
|
|
73
73
|
{ as: :string }
|
74
74
|
else
|
75
75
|
if res.klass.unscoped.respond_to?(:datatables_scope)
|
76
|
-
{ collection: res.klass.datatables_scope.map { |obj| [obj.to_s, obj.
|
76
|
+
{ collection: res.klass.datatables_scope.map { |obj| [obj.to_s, obj.id] } }
|
77
77
|
elsif res.klass.unscoped.respond_to?(:datatables_filter)
|
78
|
-
{ collection: res.klass.datatables_filter.map { |obj| [obj.to_s, obj.
|
78
|
+
{ collection: res.klass.datatables_filter.map { |obj| [obj.to_s, obj.id] } }
|
79
79
|
elsif res.klass.unscoped.respond_to?(:sorted)
|
80
|
-
{ collection: res.klass.sorted.map { |obj| [obj.to_s, obj.
|
80
|
+
{ collection: res.klass.sorted.map { |obj| [obj.to_s, obj.id] } }
|
81
81
|
else
|
82
|
-
{ collection: res.klass.all.map { |obj| [obj.to_s, obj.
|
82
|
+
{ collection: res.klass.all.map { |obj| [obj.to_s, obj.id] }.sort { |x, y| x[0] <=> y[0] } }
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
@@ -65,125 +65,274 @@ module Effective
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
def search(name, value, as: nil,
|
68
|
+
def search(name, value, as: nil, column: nil, operation: nil)
|
69
69
|
raise 'expected relation to be present' unless relation
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
sql_as = (as || sql_type(name))
|
72
|
+
sql_column = (column || sql_column(name))
|
73
|
+
sql_operation = (operation || sql_operation(name, as: sql_as)).to_sym
|
74
74
|
|
75
75
|
if ['SUM(', 'COUNT(', 'MAX(', 'MIN(', 'AVG('].any? { |str| sql_column.to_s.include?(str) }
|
76
76
|
return relation.having("#{sql_column} = ?", value)
|
77
77
|
end
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
return relation.where(is_null(sql_column))
|
79
|
+
case sql_as
|
80
|
+
when :belongs_to, :belongs_to_polymorphic, :has_and_belongs_to_many, :has_many, :has_one
|
81
|
+
search_associated(name, value, as: sql_as, operation: sql_operation)
|
82
|
+
else
|
83
|
+
return relation.where(is_null(sql_column)) if value.to_s == 'nil'
|
84
|
+
search_attribute(name, value, as: sql_as, operation: sql_operation)
|
86
85
|
end
|
86
|
+
end
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
88
|
+
def search_associated(name, value, as:, operation:)
|
89
|
+
reflection = associated(name)
|
90
|
+
raise("expected to find #{relation.klass.name} #{name} reflection") unless reflection
|
91
|
+
raise("expected association operation") unless [:eq, :matches, :does_not_match, :sql].include?(operation)
|
92
|
+
|
93
|
+
# Parse values
|
94
|
+
value_ids = value.kind_of?(Array) ? value : (value.to_s.split(/,|\s|\|/) - [nil, '', ' '])
|
95
|
+
value_sql = Arel.sql(value) if value.kind_of?(String)
|
96
|
+
|
97
|
+
# Foreign id and type
|
98
|
+
foreign_id = reflection.foreign_key
|
99
|
+
foreign_type = reflection.foreign_key.to_s.chomp('_id') + '_type'
|
100
|
+
|
101
|
+
# belongs_to polymorphic
|
102
|
+
retval = if as == :belongs_to_polymorphic
|
103
|
+
(type, id) = value.to_s.split('_')
|
104
|
+
|
105
|
+
if type.present? && id.present? # This was from a polymorphic select
|
106
|
+
case operation
|
107
|
+
when :eq
|
108
|
+
relation.where(foreign_type => type, foreign_id => id)
|
109
|
+
when :matches
|
110
|
+
relation.where(foreign_type => type, foreign_id => id)
|
111
|
+
when :does_not_match
|
112
|
+
relation.where.not(foreign_type => type, foreign_id => id)
|
113
|
+
when :sql
|
114
|
+
if (relation.where(value_sql).present? rescue :invalid) != :invalid
|
115
|
+
relation.where(value_sql)
|
116
|
+
else
|
117
|
+
relation
|
118
|
+
end
|
119
|
+
end
|
102
120
|
else # Maybe from a string field
|
103
|
-
|
121
|
+
associated = relation.none
|
104
122
|
|
105
|
-
relation.unscoped.distinct(
|
123
|
+
relation.unscoped.distinct(foreign_type).pluck(foreign_type).each do |klass_name|
|
106
124
|
next if klass_name.nil?
|
107
125
|
|
108
126
|
resource = Effective::Resource.new(klass_name)
|
109
127
|
next unless resource.klass.present?
|
110
128
|
|
111
|
-
|
129
|
+
associated = associated.or(relation.where(foreign_id => resource.search_any(value), foreign_type => klass_name))
|
112
130
|
end
|
113
131
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
.where(ActiveStorage::Blob.arel_table[:filename].matches("%#{term}%"))
|
128
|
-
when :boolean
|
129
|
-
relation.where("#{sql_column} = ?", term)
|
130
|
-
when :datetime, :date
|
131
|
-
end_at = (
|
132
|
-
case (value.to_s.scan(/(\d+)/).flatten).length
|
133
|
-
when 1 ; term.end_of_year # Year
|
134
|
-
when 2 ; term.end_of_month # Year-Month
|
135
|
-
when 3 ; term.end_of_day # Year-Month-Day
|
136
|
-
when 4 ; term.end_of_hour # Year-Month-Day Hour
|
137
|
-
when 5 ; term.end_of_minute # Year-Month-Day Hour-Minute
|
138
|
-
when 6 ; term + 1.second # Year-Month-Day Hour-Minute-Second
|
139
|
-
else term
|
132
|
+
case operation
|
133
|
+
when :eq
|
134
|
+
relation.where(id: associated.select(:id))
|
135
|
+
when :matches
|
136
|
+
relation.where(id: associated.select(:id))
|
137
|
+
when :does_not_match
|
138
|
+
relation.where.not(id: associated.select(:id))
|
139
|
+
when :sql
|
140
|
+
if (relation.where(value_sql).present? rescue :invalid) != :invalid
|
141
|
+
relation.where(value_sql)
|
142
|
+
else
|
143
|
+
relation
|
144
|
+
end
|
140
145
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
146
|
+
end
|
147
|
+
|
148
|
+
# belongs_to non-polymorphic
|
149
|
+
elsif as == :belongs_to
|
150
|
+
foreign_collection = reflection.klass.all
|
151
|
+
foreign_collection = reflection.klass.where(foreign_type => relation.klass.name) if reflection.klass.new.respond_to?(foreign_type)
|
152
|
+
|
153
|
+
case operation
|
154
|
+
when :eq
|
155
|
+
associated = foreign_collection.where(id: value_ids)
|
156
|
+
relation.where(foreign_id => associated.select(:id))
|
157
|
+
when :matches
|
158
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
159
|
+
relation.where(foreign_id => associated.select(:id))
|
160
|
+
when :does_not_match
|
161
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
162
|
+
relation.where.not(foreign_id => associated.select(:id))
|
163
|
+
when :sql
|
164
|
+
if (foreign_collection.where(value_sql).present? rescue :invalid) != :invalid
|
165
|
+
associated = foreign_collection.where(value_sql)
|
166
|
+
relation.where(foreign_id => associated.select(:id))
|
151
167
|
else
|
152
|
-
relation
|
168
|
+
relation
|
153
169
|
end
|
154
|
-
else
|
155
|
-
relation.where("#{sql_column} = ?", term)
|
156
170
|
end
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
171
|
+
|
172
|
+
# has_and_belongs_to_many
|
173
|
+
elsif as == :has_and_belongs_to_many
|
174
|
+
foreign_collection = reflection.source_reflection.klass.all
|
175
|
+
|
176
|
+
habtm = foreign_collection.klass.reflect_on_all_associations.find { |ass| ass.macro == :has_and_belongs_to_many && ass.join_table == reflection.join_table }
|
177
|
+
raise("expected a matching HABTM reflection") unless habtm
|
178
|
+
|
179
|
+
case operation
|
180
|
+
when :eq
|
181
|
+
associated = foreign_collection.where(id: value_ids)
|
182
|
+
relation.where(id: associated.joins(habtm.name).select(foreign_id))
|
183
|
+
when :matches
|
184
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
185
|
+
relation.where(id: associated.joins(habtm.name).select(foreign_id))
|
186
|
+
when :does_not_match
|
187
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
188
|
+
relation.where.not(id: associated.joins(habtm.name).select(foreign_id))
|
189
|
+
when :sql
|
190
|
+
if (foreign_collection.where(value_sql).present? rescue :invalid) != :invalid
|
191
|
+
associated = foreign_collection.where(value_sql)
|
192
|
+
relation.where(id: associated.joins(habtm.name).select(foreign_id))
|
161
193
|
else
|
162
|
-
relation
|
194
|
+
relation
|
163
195
|
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# has_many through
|
199
|
+
elsif reflection.options[:through].present?
|
200
|
+
reflected_klass = if reflection.source_reflection.options[:polymorphic]
|
201
|
+
reflection.klass
|
164
202
|
else
|
165
|
-
|
203
|
+
reflection.source_reflection.klass
|
166
204
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
relation.where("#{sql_column} = ?", term)
|
171
|
-
when :price
|
172
|
-
relation.where("#{sql_column} = ?", term)
|
173
|
-
when :string, :text, :email
|
174
|
-
if fuzzy
|
175
|
-
relation.where("#{sql_column} #{ilike} ?", "%#{term}%")
|
205
|
+
|
206
|
+
reflected_id = if reflection.source_reflection.macro == :belongs_to
|
207
|
+
reflection.source_reflection.foreign_key # to do check this
|
176
208
|
else
|
177
|
-
|
209
|
+
reflection.source_reflection.klass.primary_key # group_id
|
178
210
|
end
|
179
|
-
|
180
|
-
if
|
181
|
-
|
211
|
+
|
212
|
+
foreign_id = if reflection.through_reflection.macro == :belongs_to
|
213
|
+
reflection.through_reflection.klass.primary_key # to do check this
|
182
214
|
else
|
183
|
-
|
215
|
+
reflection.through_reflection.foreign_key # user_id
|
216
|
+
end
|
217
|
+
|
218
|
+
# Build the through collection
|
219
|
+
through = reflection.through_reflection.klass.all # group mates
|
220
|
+
|
221
|
+
if reflection.source_reflection.options[:polymorphic]
|
222
|
+
through = through.where(reflection.source_reflection.foreign_type => reflected_klass.name)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Search the associated class
|
226
|
+
case operation
|
227
|
+
when :eq
|
228
|
+
associated = through.where(reflected_id => value_ids)
|
229
|
+
relation.where(id: associated.select(foreign_id))
|
230
|
+
when :matches
|
231
|
+
reflected = Resource.new(reflected_klass).search_any(value)
|
232
|
+
associated = through.where(reflected_id => reflected)
|
233
|
+
relation.where(id: associated.select(foreign_id))
|
234
|
+
when :does_not_match
|
235
|
+
reflected = Resource.new(reflected_klass).search_any(value)
|
236
|
+
associated = through.where(reflected_id => reflected)
|
237
|
+
relation.where.not(id: associated.select(foreign_id))
|
238
|
+
when :sql
|
239
|
+
if (reflected_klass.where(value_sql).present? rescue :invalid) != :invalid
|
240
|
+
reflected = reflected_klass.where(value_sql)
|
241
|
+
associated = through.where(reflected_id => reflected)
|
242
|
+
relation.where(id: associated.select(foreign_id))
|
243
|
+
else
|
244
|
+
relation
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# has_many and has_one
|
249
|
+
elsif (as == :has_many || as == :has_one)
|
250
|
+
foreign_collection = reflection.klass.all
|
251
|
+
foreign_collection = reflection.klass.where(foreign_type => relation.klass.name) if reflection.klass.new.respond_to?(foreign_type)
|
252
|
+
|
253
|
+
case operation
|
254
|
+
when :eq
|
255
|
+
associated = foreign_collection.where(id: value_ids)
|
256
|
+
relation.where(id: associated.select(foreign_id))
|
257
|
+
when :matches
|
258
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
259
|
+
relation.where(id: associated.select(foreign_id))
|
260
|
+
when :does_not_match
|
261
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
262
|
+
relation.where.not(id: associated.select(foreign_id))
|
263
|
+
when :sql
|
264
|
+
if (foreign_collection.where(value_sql).present? rescue :invalid) != :invalid
|
265
|
+
associated = foreign_collection.where(value_sql)
|
266
|
+
relation.where(id: associated.select(foreign_id))
|
267
|
+
else
|
268
|
+
relation
|
269
|
+
end
|
184
270
|
end
|
185
|
-
|
186
|
-
|
271
|
+
end
|
272
|
+
|
273
|
+
retval || raise("unable to search associated #{as} #{operation} #{name} for #{value}")
|
274
|
+
end
|
275
|
+
|
276
|
+
def search_attribute(name, value, as:, operation:)
|
277
|
+
raise 'expected relation to be present' unless relation
|
278
|
+
|
279
|
+
attribute = relation.arel_table[name]
|
280
|
+
|
281
|
+
# Normalize the term.
|
282
|
+
# If you pass an email attribute it can return nil so we return the full value
|
283
|
+
term = Attribute.new(as).parse(value, name: name) || value
|
284
|
+
|
285
|
+
searched = case as
|
286
|
+
when :date, :datetime
|
287
|
+
if value.kind_of?(String)
|
288
|
+
end_at = (
|
289
|
+
case (value.to_s.scan(/(\d+)/).flatten).length
|
290
|
+
when 1 ; term.end_of_year # Year
|
291
|
+
when 2 ; term.end_of_month # Year-Month
|
292
|
+
when 3 ; term.end_of_day # Year-Month-Day
|
293
|
+
when 4 ; term.end_of_hour # Year-Month-Day Hour
|
294
|
+
when 5 ; term.end_of_minute # Year-Month-Day Hour-Minute
|
295
|
+
when 6 ; term + 1.second # Year-Month-Day Hour-Minute-Second
|
296
|
+
else term
|
297
|
+
end
|
298
|
+
)
|
299
|
+
|
300
|
+
relation.where(attribute.gteq(term)).where(attribute.lteq(end_at))
|
301
|
+
end
|
302
|
+
|
303
|
+
when :effective_obfuscation
|
304
|
+
term = Attribute.new(as, klass: (associated(name).try(:klass) || klass)).parse(value, name: name)
|
305
|
+
relation.where(attribute.eq((value == term ? 0 : term)))
|
306
|
+
|
307
|
+
when :effective_addresses
|
308
|
+
association = associated(name)
|
309
|
+
associated = Resource.new(association).search_any(value)
|
310
|
+
relation.where(id: associated.where(addressable_type: klass.name).select(:addressable_id))
|
311
|
+
|
312
|
+
when :effective_roles
|
313
|
+
relation.with_role(term)
|
314
|
+
|
315
|
+
when :time
|
316
|
+
timed = relation.where("EXTRACT(hour from #{sql_column}) = ?", term.utc.hour)
|
317
|
+
timed = timed.where("EXTRACT(minute from #{sql_column}) = ?", term.utc.min) if term.min > 0
|
318
|
+
timed
|
319
|
+
end
|
320
|
+
|
321
|
+
return searched if searched
|
322
|
+
|
323
|
+
# Simple operation search
|
324
|
+
case operation
|
325
|
+
when :eq then relation.where(attribute.eq(term))
|
326
|
+
when :not_eq then relation.where(attribute.not_eq(term))
|
327
|
+
when :matches then relation.where(attribute.matches("%#{term}%"))
|
328
|
+
when :does_not_match then relation.where(attribute.does_not_match("%#{term}%"))
|
329
|
+
when :starts_with then relation.where(attribute.matches("#{term}%"))
|
330
|
+
when :ends_with then relation.where(attribute.matches("%#{term}"))
|
331
|
+
when :gt then relation.where(attribute.gt(term))
|
332
|
+
when :gteq then relation.where(attribute.gteq(term))
|
333
|
+
when :lt then relation.where(attribute.lt(term))
|
334
|
+
when :lteq then relation.where(attribute.lteq(term))
|
335
|
+
else raise("Unexpected operation: #{operation}")
|
187
336
|
end
|
188
337
|
end
|
189
338
|
|
@@ -195,11 +344,6 @@ module Effective
|
|
195
344
|
return relation.where(klass.primary_key => value)
|
196
345
|
end
|
197
346
|
|
198
|
-
# If the value is 3-something-like-this
|
199
|
-
if (values = value.to_s.split('-')).length > 0 && (maybe_id = values.first).present?
|
200
|
-
return relation.where(klass.primary_key => maybe_id) if (maybe_id.to_i.to_s == maybe_id)
|
201
|
-
end
|
202
|
-
|
203
347
|
# If the user specifies columns. Filter out invalid ones for this klass
|
204
348
|
if columns.present?
|
205
349
|
columns = Array(columns).map(&:to_s) - [nil, '']
|
@@ -238,81 +382,6 @@ module Effective
|
|
238
382
|
|
239
383
|
private
|
240
384
|
|
241
|
-
def search_by_associated_conditions(association, value, fuzzy: nil)
|
242
|
-
resource = Effective::Resource.new(association)
|
243
|
-
|
244
|
-
# Search the target model for its matching records / keys
|
245
|
-
relation = resource.search_any(value, fuzzy: fuzzy)
|
246
|
-
|
247
|
-
if association.options[:as] # polymorphic
|
248
|
-
relation = relation.where(association.type => klass.name)
|
249
|
-
end
|
250
|
-
|
251
|
-
# key: the id, or associated_id on my table
|
252
|
-
# keys: the ids themselves as per the target table
|
253
|
-
if association.macro == :belongs_to && association.options[:polymorphic]
|
254
|
-
key = sql_column(association.foreign_key)
|
255
|
-
keys = relation.pluck((relation.klass.primary_key rescue nil))
|
256
|
-
elsif association.macro == :belongs_to
|
257
|
-
key = sql_column(association.foreign_key)
|
258
|
-
keys = relation.pluck(association.klass.primary_key)
|
259
|
-
elsif association.macro == :has_and_belongs_to_many
|
260
|
-
key = sql_column(klass.primary_key)
|
261
|
-
values = relation.pluck(association.source_reflection.klass.primary_key).uniq.compact
|
262
|
-
|
263
|
-
keys = if value == 'nil'
|
264
|
-
klass.where.not(klass.primary_key => klass.joins(association.name)).pluck(klass.primary_key)
|
265
|
-
else
|
266
|
-
klass.joins(association.name)
|
267
|
-
.where(association.name => { association.source_reflection.klass.primary_key => values })
|
268
|
-
.pluck(klass.primary_key)
|
269
|
-
end
|
270
|
-
elsif association.options[:through].present?
|
271
|
-
scope = association.through_reflection.klass.all
|
272
|
-
|
273
|
-
if association.source_reflection.options[:polymorphic]
|
274
|
-
reflected_klass = association.klass
|
275
|
-
scope = scope.where(association.source_reflection.foreign_type => reflected_klass.name)
|
276
|
-
else
|
277
|
-
reflected_klass = association.source_reflection.klass
|
278
|
-
end
|
279
|
-
|
280
|
-
if association.through_reflection.macro == :belongs_to
|
281
|
-
key = association.through_reflection.foreign_key
|
282
|
-
pluck_key = association.through_reflection.klass.primary_key
|
283
|
-
else
|
284
|
-
key = sql_column(klass.primary_key)
|
285
|
-
pluck_key = association.through_reflection.foreign_key
|
286
|
-
end
|
287
|
-
|
288
|
-
if value == 'nil'
|
289
|
-
keys = klass.where.not(klass.primary_key => scope.pluck(pluck_key)).pluck(klass.primary_key)
|
290
|
-
else
|
291
|
-
keys = scope.where(association.source_reflection.foreign_key => relation).pluck(pluck_key)
|
292
|
-
end
|
293
|
-
|
294
|
-
elsif association.macro == :has_many
|
295
|
-
key = sql_column(klass.primary_key)
|
296
|
-
|
297
|
-
keys = if value == 'nil'
|
298
|
-
klass.where.not(klass.primary_key => resource.klass.pluck(association.foreign_key)).pluck(klass.primary_key)
|
299
|
-
else
|
300
|
-
relation.pluck(association.foreign_key)
|
301
|
-
end
|
302
|
-
|
303
|
-
elsif association.macro == :has_one
|
304
|
-
key = sql_column(klass.primary_key)
|
305
|
-
|
306
|
-
keys = if value == 'nil'
|
307
|
-
klass.where.not(klass.primary_key => resource.klass.pluck(association.foreign_key)).pluck(klass.primary_key)
|
308
|
-
else
|
309
|
-
relation.pluck(association.foreign_key)
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
"#{key} IN (#{(keys.uniq.compact.presence || [0]).join(',')})"
|
314
|
-
end
|
315
|
-
|
316
385
|
def order_by_associated_conditions(association, sort: nil, direction: :asc, limit: nil)
|
317
386
|
resource = Effective::Resource.new(association)
|
318
387
|
|
@@ -38,6 +38,15 @@ module Effective
|
|
38
38
|
name.to_s.downcase == 'desc' ? 'DESC' : 'ASC'
|
39
39
|
end
|
40
40
|
|
41
|
+
def sql_operation(name, as: nil)
|
42
|
+
sql_type = (as || sql_type(name))
|
43
|
+
|
44
|
+
case sql_type
|
45
|
+
when :boolean, :decimal, :integer, :price, :date, :datetime, :percent then :eq
|
46
|
+
else :matches
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
41
50
|
# This is for EffectiveDatatables (col as:)
|
42
51
|
# Might be :name, or 'users.name'
|
43
52
|
def sql_type(name)
|
data/lib/effective_resources.rb
CHANGED
@@ -172,4 +172,10 @@ module EffectiveResources
|
|
172
172
|
|
173
173
|
end
|
174
174
|
|
175
|
+
def self.replace_nested_attributes(attributes)
|
176
|
+
attributes.reject { |k, values| truthy?(values[:_destroy]) }.inject({}) do |h, (key, values)|
|
177
|
+
h[key] = values.reject { |k, v| k == 'id' || k == '_destroy' }; h
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
175
181
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|