effective_resources 2.1.4 → 2.2.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 +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
|