effective_resources 2.1.4 → 2.2.1
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 +243 -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: 8f9e795410769087135de28ce4b8c46a48de30d72dc9feeaa48a96966f059c43
|
4
|
+
data.tar.gz: 488c2b300e0b05e1c111093e903aae654ab7867f952b66b81dbdd2c5fce46159
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6a2ca614bafbeef5787bcaf49a68d467c0707c3610e5b692d4d58d40295a630b15baa828c2ec71d8837c76372817db6a4ec78e4eb96b391517815d1edcfae99
|
7
|
+
data.tar.gz: 0deb208420dc1591c95cd23735ef4c4f843411d91a071cc515f492225e8c1a63f9d3415c66257357d7651aed58ca3f3f842a6508aa8eb1e1b0cd658325071879
|
@@ -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,279 @@ 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
|
+
|
91
|
+
raise("expected to find #{relation.klass.name} #{name} reflection") unless reflection
|
92
|
+
raise("unexpected search_associated operation #{operation || 'nil'}") unless [:eq, :matches, :does_not_match, :sql].include?(operation)
|
93
|
+
|
94
|
+
# Parse values
|
95
|
+
value_ids = value.kind_of?(Array) ? value : (value.to_s.split(/,|\s|\|/) - [nil, '', ' '])
|
96
|
+
value_sql = Arel.sql(value) if value.kind_of?(String)
|
97
|
+
|
98
|
+
# Foreign id and type
|
99
|
+
foreign_id = reflection.foreign_key
|
100
|
+
foreign_type = reflection.foreign_key.to_s.chomp('_id') + '_type'
|
101
|
+
|
102
|
+
# belongs_to polymorphic
|
103
|
+
retval = if as == :belongs_to_polymorphic
|
104
|
+
(type, id) = value.to_s.split('_')
|
105
|
+
|
106
|
+
if type.present? && id.present? # This was from a polymorphic select
|
107
|
+
case operation
|
108
|
+
when :eq
|
109
|
+
relation.where(foreign_type => type, foreign_id => id)
|
110
|
+
when :matches
|
111
|
+
relation.where(foreign_type => type, foreign_id => id)
|
112
|
+
when :does_not_match
|
113
|
+
relation.where.not(foreign_type => type, foreign_id => id)
|
114
|
+
when :sql
|
115
|
+
if (relation.where(value_sql).present? rescue :invalid) != :invalid
|
116
|
+
relation.where(value_sql)
|
117
|
+
else
|
118
|
+
relation
|
119
|
+
end
|
120
|
+
end
|
102
121
|
else # Maybe from a string field
|
103
|
-
|
122
|
+
associated = relation.none
|
104
123
|
|
105
|
-
relation.unscoped.distinct(
|
124
|
+
relation.unscoped.distinct(foreign_type).pluck(foreign_type).each do |klass_name|
|
106
125
|
next if klass_name.nil?
|
107
126
|
|
108
127
|
resource = Effective::Resource.new(klass_name)
|
109
128
|
next unless resource.klass.present?
|
110
129
|
|
111
|
-
|
130
|
+
associated = associated.or(relation.where(foreign_id => resource.search_any(value), foreign_type => klass_name))
|
112
131
|
end
|
113
132
|
|
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
|
133
|
+
case operation
|
134
|
+
when :eq
|
135
|
+
relation.where(id: associated.select(:id))
|
136
|
+
when :matches
|
137
|
+
relation.where(id: associated.select(:id))
|
138
|
+
when :does_not_match
|
139
|
+
relation.where.not(id: associated.select(:id))
|
140
|
+
when :sql
|
141
|
+
if (relation.where(value_sql).present? rescue :invalid) != :invalid
|
142
|
+
relation.where(value_sql)
|
143
|
+
else
|
144
|
+
relation
|
145
|
+
end
|
140
146
|
end
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
147
|
+
end
|
148
|
+
|
149
|
+
# belongs_to non-polymorphic
|
150
|
+
elsif as == :belongs_to
|
151
|
+
foreign_collection = reflection.klass.all
|
152
|
+
foreign_collection = reflection.klass.where(foreign_type => relation.klass.name) if reflection.klass.new.respond_to?(foreign_type)
|
153
|
+
|
154
|
+
case operation
|
155
|
+
when :eq
|
156
|
+
associated = foreign_collection.where(id: value_ids)
|
157
|
+
relation.where(foreign_id => associated.select(:id))
|
158
|
+
when :matches
|
159
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
160
|
+
relation.where(foreign_id => associated.select(:id))
|
161
|
+
when :does_not_match
|
162
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
163
|
+
relation.where.not(foreign_id => associated.select(:id))
|
164
|
+
when :sql
|
165
|
+
if (foreign_collection.where(value_sql).present? rescue :invalid) != :invalid
|
166
|
+
associated = foreign_collection.where(value_sql)
|
167
|
+
relation.where(foreign_id => associated.select(:id))
|
151
168
|
else
|
152
|
-
relation
|
169
|
+
relation
|
153
170
|
end
|
154
|
-
else
|
155
|
-
relation.where("#{sql_column} = ?", term)
|
156
171
|
end
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
172
|
+
|
173
|
+
# has_and_belongs_to_many
|
174
|
+
elsif as == :has_and_belongs_to_many
|
175
|
+
foreign_collection = reflection.source_reflection.klass.all
|
176
|
+
|
177
|
+
habtm = foreign_collection.klass.reflect_on_all_associations.find { |ass| ass.macro == :has_and_belongs_to_many && ass.join_table == reflection.join_table }
|
178
|
+
raise("expected a matching HABTM reflection") unless habtm
|
179
|
+
|
180
|
+
case operation
|
181
|
+
when :eq
|
182
|
+
associated = foreign_collection.where(id: value_ids)
|
183
|
+
relation.where(id: associated.joins(habtm.name).select(foreign_id))
|
184
|
+
when :matches
|
185
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
186
|
+
relation.where(id: associated.joins(habtm.name).select(foreign_id))
|
187
|
+
when :does_not_match
|
188
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
189
|
+
relation.where.not(id: associated.joins(habtm.name).select(foreign_id))
|
190
|
+
when :sql
|
191
|
+
if (foreign_collection.where(value_sql).present? rescue :invalid) != :invalid
|
192
|
+
associated = foreign_collection.where(value_sql)
|
193
|
+
relation.where(id: associated.joins(habtm.name).select(foreign_id))
|
161
194
|
else
|
162
|
-
relation
|
195
|
+
relation
|
163
196
|
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# has_many through
|
200
|
+
elsif reflection.options[:through].present?
|
201
|
+
reflected_klass = if reflection.source_reflection.options[:polymorphic]
|
202
|
+
reflection.klass
|
164
203
|
else
|
165
|
-
|
204
|
+
reflection.source_reflection.klass
|
166
205
|
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}%")
|
206
|
+
|
207
|
+
reflected_id = if reflection.source_reflection.macro == :belongs_to
|
208
|
+
reflection.source_reflection.foreign_key # to do check this
|
176
209
|
else
|
177
|
-
|
210
|
+
reflection.source_reflection.klass.primary_key # group_id
|
178
211
|
end
|
179
|
-
|
180
|
-
if
|
181
|
-
|
212
|
+
|
213
|
+
foreign_id = if reflection.through_reflection.macro == :belongs_to
|
214
|
+
reflection.through_reflection.klass.primary_key # to do check this
|
182
215
|
else
|
183
|
-
|
216
|
+
reflection.through_reflection.foreign_key # user_id
|
217
|
+
end
|
218
|
+
|
219
|
+
# Build the through collection
|
220
|
+
through = reflection.through_reflection.klass.all # group mates
|
221
|
+
|
222
|
+
if reflection.source_reflection.options[:polymorphic]
|
223
|
+
through = through.where(reflection.source_reflection.foreign_type => reflected_klass.name)
|
224
|
+
end
|
225
|
+
|
226
|
+
# Search the associated class
|
227
|
+
case operation
|
228
|
+
when :eq
|
229
|
+
associated = through.where(reflected_id => value_ids)
|
230
|
+
relation.where(id: associated.select(foreign_id))
|
231
|
+
when :matches
|
232
|
+
reflected = Resource.new(reflected_klass).search_any(value)
|
233
|
+
associated = through.where(reflected_id => reflected)
|
234
|
+
relation.where(id: associated.select(foreign_id))
|
235
|
+
when :does_not_match
|
236
|
+
reflected = Resource.new(reflected_klass).search_any(value)
|
237
|
+
associated = through.where(reflected_id => reflected)
|
238
|
+
relation.where.not(id: associated.select(foreign_id))
|
239
|
+
when :sql
|
240
|
+
if (reflected_klass.where(value_sql).present? rescue :invalid) != :invalid
|
241
|
+
reflected = reflected_klass.where(value_sql)
|
242
|
+
associated = through.where(reflected_id => reflected)
|
243
|
+
relation.where(id: associated.select(foreign_id))
|
244
|
+
else
|
245
|
+
relation
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# has_many and has_one
|
250
|
+
elsif (as == :has_many || as == :has_one)
|
251
|
+
foreign_collection = reflection.klass.all
|
252
|
+
foreign_collection = reflection.klass.where(foreign_type => relation.klass.name) if reflection.klass.new.respond_to?(foreign_type)
|
253
|
+
|
254
|
+
case operation
|
255
|
+
when :eq
|
256
|
+
associated = foreign_collection.where(id: value_ids)
|
257
|
+
relation.where(id: associated.select(foreign_id))
|
258
|
+
when :matches
|
259
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
260
|
+
relation.where(id: associated.select(foreign_id))
|
261
|
+
when :does_not_match
|
262
|
+
associated = Resource.new(foreign_collection).search_any(value)
|
263
|
+
relation.where.not(id: associated.select(foreign_id))
|
264
|
+
when :sql
|
265
|
+
if (foreign_collection.where(value_sql).present? rescue :invalid) != :invalid
|
266
|
+
associated = foreign_collection.where(value_sql)
|
267
|
+
relation.where(id: associated.select(foreign_id))
|
268
|
+
else
|
269
|
+
relation
|
270
|
+
end
|
184
271
|
end
|
185
|
-
|
186
|
-
|
272
|
+
end
|
273
|
+
|
274
|
+
retval || raise("unable to search associated #{as} #{operation} #{name} for #{value}")
|
275
|
+
end
|
276
|
+
|
277
|
+
def search_attribute(name, value, as:, operation:)
|
278
|
+
raise 'expected relation to be present' unless relation
|
279
|
+
|
280
|
+
attribute = relation.arel_table[name]
|
281
|
+
|
282
|
+
# Normalize the term.
|
283
|
+
# If you pass an email attribute it can return nil so we return the full value
|
284
|
+
term = Attribute.new(as).parse(value, name: name) || value
|
285
|
+
|
286
|
+
searched = case as
|
287
|
+
when :active_storage
|
288
|
+
relation.send("with_attached_#{name}").references("#{name}_attachment")
|
289
|
+
.where(ActiveStorage::Blob.arel_table[:filename].matches("%#{term}%"))
|
290
|
+
|
291
|
+
when :date, :datetime
|
292
|
+
if value.kind_of?(String)
|
293
|
+
end_at = (
|
294
|
+
case (value.to_s.scan(/(\d+)/).flatten).length
|
295
|
+
when 1 ; term.end_of_year # Year
|
296
|
+
when 2 ; term.end_of_month # Year-Month
|
297
|
+
when 3 ; term.end_of_day # Year-Month-Day
|
298
|
+
when 4 ; term.end_of_hour # Year-Month-Day Hour
|
299
|
+
when 5 ; term.end_of_minute # Year-Month-Day Hour-Minute
|
300
|
+
when 6 ; term + 1.second # Year-Month-Day Hour-Minute-Second
|
301
|
+
else term
|
302
|
+
end
|
303
|
+
)
|
304
|
+
|
305
|
+
relation.where(attribute.gteq(term)).where(attribute.lteq(end_at))
|
306
|
+
end
|
307
|
+
|
308
|
+
when :effective_obfuscation
|
309
|
+
term = Attribute.new(as, klass: (associated(name).try(:klass) || klass)).parse(value, name: name)
|
310
|
+
relation.where(attribute.eq((value == term ? 0 : term)))
|
311
|
+
|
312
|
+
when :effective_addresses
|
313
|
+
association = associated(name)
|
314
|
+
associated = Resource.new(association).search_any(value)
|
315
|
+
relation.where(id: associated.where(addressable_type: klass.name).select(:addressable_id))
|
316
|
+
|
317
|
+
when :effective_roles
|
318
|
+
relation.with_role(term)
|
319
|
+
|
320
|
+
when :time
|
321
|
+
timed = relation.where("EXTRACT(hour from #{sql_column}) = ?", term.utc.hour)
|
322
|
+
timed = timed.where("EXTRACT(minute from #{sql_column}) = ?", term.utc.min) if term.min > 0
|
323
|
+
timed
|
324
|
+
end
|
325
|
+
|
326
|
+
return searched if searched
|
327
|
+
|
328
|
+
# Simple operation search
|
329
|
+
case operation
|
330
|
+
when :eq then relation.where(attribute.eq(term))
|
331
|
+
when :not_eq then relation.where(attribute.not_eq(term))
|
332
|
+
when :matches then relation.where(attribute.matches("%#{term}%"))
|
333
|
+
when :does_not_match then relation.where(attribute.does_not_match("%#{term}%"))
|
334
|
+
when :starts_with then relation.where(attribute.matches("#{term}%"))
|
335
|
+
when :ends_with then relation.where(attribute.matches("%#{term}"))
|
336
|
+
when :gt then relation.where(attribute.gt(term))
|
337
|
+
when :gteq then relation.where(attribute.gteq(term))
|
338
|
+
when :lt then relation.where(attribute.lt(term))
|
339
|
+
when :lteq then relation.where(attribute.lteq(term))
|
340
|
+
else raise("Unexpected operation: #{operation}")
|
187
341
|
end
|
188
342
|
end
|
189
343
|
|
@@ -195,11 +349,6 @@ module Effective
|
|
195
349
|
return relation.where(klass.primary_key => value)
|
196
350
|
end
|
197
351
|
|
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
352
|
# If the user specifies columns. Filter out invalid ones for this klass
|
204
353
|
if columns.present?
|
205
354
|
columns = Array(columns).map(&:to_s) - [nil, '']
|
@@ -238,81 +387,6 @@ module Effective
|
|
238
387
|
|
239
388
|
private
|
240
389
|
|
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
390
|
def order_by_associated_conditions(association, sort: nil, direction: :asc, limit: nil)
|
317
391
|
resource = Effective::Resource.new(association)
|
318
392
|
|
@@ -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.1
|
4
|
+
version: 2.2.1
|
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
|