cast_about_for 0.1.2 → 0.2.0

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
  SHA1:
3
- metadata.gz: f89b80544593269d2556df48a28845c7b9afb875
4
- data.tar.gz: f32a8afe8c775646c101a17976ff144d43d43076
3
+ metadata.gz: e5f49b9f0d9074c8dabf2932029de383179fb429
4
+ data.tar.gz: 1264283111f24c0fcad5d3e36576644dc1a5eaed
5
5
  SHA512:
6
- metadata.gz: c1ee3ad830d4fa24b31b4f45c000561120c72059b0945741909aa3e980ae952005f593eadea3ee95d2ce734387d88e63e8b6fff9b5cb9811302b10d6e84d3441
7
- data.tar.gz: 071d92105a788ec87ba1a930dd42c88962637a2feea7ad956e2b018ac02569288687d94abb2b4e9236519da367ab877d756c87fdfa5782ae35a7059c29f652f9
6
+ metadata.gz: 792179f701b91f51f0988452666e02c7c113839c74edd1a77af90b3a89b64c1bfcf5ffbd6db68ddba7072847e67fa3e0fba4fbf853c635d2692284412f554200
7
+ data.tar.gz: 20d77f0ac8bb4da57d80b61b80e37baa9cf262bcf8d39eebd9dd09e03d74bf4bb9b565a9b6569a368f871988c1428ec5950c43ec8cab05a8dc2f582f08491f72
data/Gemfile CHANGED
@@ -3,6 +3,6 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in cast_about_for.gemspec
4
4
  gemspec
5
5
 
6
- gem 'activerecord', '5.0.0'
7
- gem 'sqlite3'
6
+ gem 'activerecord', '~> 5.0.0.1'
7
+ gem 'sqlite3', '~> 1.3.11'
8
8
  gem 'minitest'
data/README.md CHANGED
@@ -231,6 +231,139 @@ class Product < ActiveRecord::Base
231
231
  # ...
232
232
  end
233
233
  ```
234
+
235
+ ### Comparison
236
+ If you want to compare a column, the sql like this: The SQL: `SELECT "products".* FROM "products" WHERE (weight >= '100' AND weight <= '1000')`
237
+ you can do it like this:
238
+ ```ruby
239
+ # params = {weight_min: 100, weight_max: 1000}
240
+ # Product.cast_about_for(params)
241
+
242
+ class Product < ActiveRecord::Base
243
+ cast_about_for_params comparison: [{"weight >= ?" => "weight_min"}, {"weight <= ?" => "weight_max"}]
244
+
245
+ end
246
+ ```
247
+
248
+ ###Includes
249
+ If you want to `includes` other models, you can do it like this
250
+ ```ruby
251
+ class Product < ActiveRecord::Base
252
+ cast_about_for_params includes: [:user, :items]
253
+
254
+ #This will make `product` include `user` and `items` automatically
255
+ #Like: Product.includes(:user, :items)
256
+ end
257
+
258
+ ```
259
+ ###Joins
260
+
261
+ If you want to join a model you can do it like this:
262
+
263
+ ```ruby
264
+ Example 1
265
+
266
+ class Product < ActiveRecord::Base
267
+ cast_about_for_params joins: [{user: [equal: :name]}]
268
+
269
+ end
270
+
271
+ # params = {name: "user"}
272
+ # Product.cast_about_for(params)
273
+ # It will be generates like this: Product.joins(:user).where("users.name = ?", "user")
274
+ # The sql would like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name = 'user')`
275
+
276
+ If you want to query the condition of "LIKE", do it like this
277
+
278
+ class Product < ActiveRecord::Base
279
+ cast_about_for_params joins: [{user: [like: :name]}]
280
+
281
+ end
282
+ Then the sql would be like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name Like 'user')`
283
+
284
+
285
+ --------
286
+ Example 2
287
+ If you want to nickname the `name` of the params like:
288
+ # params = {user_name: "user"}
289
+ # Product.cast_about_for(params)
290
+
291
+ class Product < ActiveRecord::Base
292
+ cast_about_for_params joins: [{user: [equal: {name: :user_name}]}]
293
+
294
+ end
295
+
296
+ # Also will generates like this: Product.joins(:user).where("users.name = ?", "user")
297
+ # The sql would like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name = 'user')`
298
+
299
+ --------
300
+ Example 3
301
+ If multiple user columns that you want to query, you can do it like this:
302
+ # params = {name: "user", age: 18}
303
+ # Product.cast_about_for(params)
304
+
305
+ class Product < ActiveRecord::Base
306
+ cast_about_for_params joins: [{user: [equal: [:name, :age]}]
307
+
308
+ end
309
+ # Also will generates like this: Product.joins(:user).where("users.name = ? AND users.age = ?", "user", "18")
310
+ # The sql would like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name = 'user' AND users.age = 18)`
311
+
312
+
313
+ If you want to nickname the params:
314
+ # params = {user_name: "user", user_age: 18}
315
+ # Product.cast_about_for(params)
316
+ class Product < ActiveRecord::Base
317
+ cast_about_for_params joins: [{user: [equal: [{name: :user_name}, {age: :user_age}]}]
318
+
319
+ end
320
+
321
+ --------
322
+ Example 4
323
+ You can use the `equal` and `like` at the same time:
324
+ class Product < ActiveRecord::Base
325
+ cast_about_for_params joins: [{user: [equal: :age], [like: :name]}]
326
+
327
+ end
328
+
329
+ `OR`
330
+ class Product < ActiveRecord::Base
331
+ cast_about_for_params joins: [{user: [equal: [:age, :height]], [like: [:name, :roles]]}]
332
+
333
+ end
334
+
335
+ --------
336
+ Example 5
337
+ Nested joins:
338
+
339
+ Now, I have `product` `user` `company` models,
340
+
341
+ class Product < ActiveRecord::Base
342
+ belongs_to :user
343
+ end
344
+
345
+ class User < ActiveRecord::Base
346
+ belongs_to :company
347
+ has_many :products
348
+ end
349
+
350
+ class Company < ActiveRecord::Base
351
+ has_many :user
352
+ end
353
+
354
+ I have company `name`, and now I want to query the products through the user who belong to the company, so I can do it like this:
355
+
356
+ class Product < ActiveRecord::Base
357
+ cast_about_for_params joins: [{{user: :company} => [like: {name: :company_name}]}]
358
+
359
+ end
360
+ # params = {company_name: "Teo"}
361
+ # Product.cast_about_for(params)
362
+ # The sql would like this: SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" INNER JOIN "companies" ON "companies"."id" = "users"."company_id" WHERE (companies.name LIKE 'Teo')
363
+
364
+ ```
365
+
366
+
234
367
  ## Advanced Usage
235
368
 
236
369
  ### JSON API
@@ -1,11 +1,12 @@
1
1
  require 'cast_about_for/search'
2
+ require 'cast_about_for/validate_macro'
2
3
  module CastAboutFor
3
4
  module Base
4
5
  extend ActiveSupport::Concern
5
6
 
6
7
  module ClassMethods
7
8
  include Search
8
- CAST_ABOUT_FOR_KEY = [:equal, :like, :enum, :after, :before]
9
+ CAST_ABOUT_FOR_KEY = [:equal, :like, :enum, :joins, :includes, :after, :before, :comparison]
9
10
  def cast_about_for_params *args
10
11
 
11
12
  options = args.extract_options!.dup
@@ -14,14 +15,9 @@ module CastAboutFor
14
15
  raise ArgumentError, "Unknown cast_about_for key: '#{key}" unless CAST_ABOUT_FOR_KEY.include?(key)
15
16
  end
16
17
 
17
- validate_keys = options.slice(*CAST_ABOUT_FOR_KEY.first(3))
18
+ validate_keys = options.slice(*CAST_ABOUT_FOR_KEY.first(5))
18
19
 
19
- validate_keys.each do |key, value|
20
- value.each do |attribute|
21
- attribute = attribute.is_a?(Hash) ? attribute.first.first : attribute
22
- raise ArgumentError, "Unknown column: #{attribute}" unless self.respond_to?(attribute) || self.column_names.include?(attribute.to_s)
23
- end
24
- end
20
+ ValidateMacro.validate(self, validate_keys)
25
21
 
26
22
  class_variable_set(:@@cast_about_for_params, options)
27
23
  end
@@ -68,6 +68,33 @@ module CastAboutFor
68
68
  seach_model
69
69
  end
70
70
 
71
+ def cast_about_for_by_comparison search_values, params, seach_model
72
+ search_values.each do |comparison|
73
+ comparison.each do |seach_mod, search_name|
74
+ seach_model = seach_model.where("#{seach_mod}", params[search_name.to_sym]) if params.present? && params[search_name.to_sym].present?
75
+ end
76
+ end
77
+ seach_model
78
+ end
79
+
80
+ def cast_about_for_by_joins search_values, params, seach_model
81
+ search_values.each do |associations|
82
+ associations.each do |association, association_operations|
83
+ association_operations.each do |operations|
84
+ operations.each do |action, columns|
85
+ seach_model = send("#{action.to_s}_operation", association, columns, params, seach_model)
86
+ end
87
+ end
88
+ end
89
+ end
90
+ seach_model
91
+ end
92
+
93
+ def cast_about_for_by_includes search_values, params, seach_model
94
+ seach_model = seach_model.includes(search_values)
95
+ seach_model
96
+ end
97
+
71
98
  def obtain_value(value)
72
99
  case value
73
100
  when Hash then [value.first.first, value.first.last]
@@ -87,5 +114,37 @@ module CastAboutFor
87
114
  raise ArgumentError, "Unknown column: #{column}" unless self.respond_to?(column) || self.column_names.include?(column.to_s)
88
115
  [column.to_sym, value[:time]]
89
116
  end
117
+
118
+ def like_operation(association, columns, params, seach_model)
119
+ association, association_name = obtain_joins_value(association)
120
+ columns = columns.is_a?(Array) ? columns : [columns]
121
+ columns.each do |column|
122
+ search_column, search_name = obtain_value(column)
123
+ seach_model = seach_model.joins(association).where("#{association_name.to_s.pluralize}.#{search_column} LIKE ?", "%#{params[search_name.to_sym]}%") if params.present? && params[search_name.to_sym].present?
124
+ end
125
+ p
126
+ seach_model
127
+ end
128
+
129
+ def equal_operation(association, columns, params, seach_model)
130
+ association, association_name = obtain_joins_value(association)
131
+ columns = columns.is_a?(Array) ? columns : [columns]
132
+ columns.each do |column|
133
+ search_column, search_name = obtain_value(column)
134
+ seach_model = seach_model.joins(association).where("#{association_name.to_s.pluralize}.#{search_column} = ?", params[search_name.to_sym]) if params.present? && params[search_name.to_sym].present?
135
+ end
136
+ seach_model
137
+ end
138
+
139
+
140
+ def obtain_joins_value(value)
141
+ if Hash === value #如果是hash则使用嵌入式joins
142
+ association = {}
143
+ value.each{|k, v| association[k.to_sym] = v.to_sym}
144
+ [association, value.flatten.last]
145
+ else
146
+ [value.to_sym, value]
147
+ end
148
+ end
90
149
  end
91
150
  end
@@ -0,0 +1,69 @@
1
+ module CastAboutFor
2
+ module ValidateMacro
3
+
4
+ class << self
5
+
6
+ def validate(record, options)
7
+ options.each do |key, value|
8
+ case key
9
+ when :joins then send("validate_join", record, value)
10
+ when :includes then send("validate_includes", record, value)
11
+ else send("validate_others", record, value)
12
+ end
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def validate_join(record, value)
19
+ value.each do |association|
20
+ association.each do |association_name, association_operations|
21
+ validate_join_associations(record, association_name)
22
+
23
+ association_operations.each do |operations|
24
+ operations.each_value do |columns|
25
+ association_name = association_name.is_a?(Hash) ? association_name.flatten.last : association_name
26
+ klass = Object.const_get("#{association_name}".camelize.singularize)
27
+ columns = columns.is_a?(Array) ? columns : [columns]
28
+ columns.each do |column|
29
+ column = column.is_a?(Hash) ? column.first.first : column
30
+ raise ArgumentError, "Unknown column: #{column} for #{klass}" unless klass.column_names.include?("#{column}")
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ def validate_includes(record, value)
39
+ value = value.is_a?(Array) ? value : [value]
40
+ value.each do |association|
41
+ raise ArgumentError, "Unknown association #{association} fo #{record}" unless record._reflections.keys.include?(association.to_s)
42
+ end
43
+ end
44
+
45
+ def validate_others(record, value)
46
+ value.each do |attribute|
47
+ attribute = attribute.is_a?(Hash) ? attribute.first.first : attribute
48
+ raise ArgumentError, "Unknown column: #{attribute} fo #{record}" unless record.respond_to?(attribute) || record.column_names.include?(attribute.to_s)
49
+ end
50
+ end
51
+
52
+ def validate_join_associations(record, association_name)
53
+ if association_name.is_a?(Hash) #检查是否为嵌入式的joins,例如: A.joins(b: :c)
54
+ association_name.each do |key, value|
55
+ validate_join_association(record, key)
56
+ validate_join_association(Object.const_get("#{key}".camelize.singularize), value)
57
+ end
58
+ else
59
+ validate_join_association(record, association_name)
60
+ end
61
+ end
62
+
63
+ def validate_join_association(record, association_name)
64
+ # _reflections method come from rails ActiveRecord::Reflection
65
+ raise ArgumentError, "Unknown association #{association_name} fo #{record}" unless record._reflections.keys.include?(association_name.to_s)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,3 +1,3 @@
1
1
  module CastAboutFor
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cast_about_for
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JeskTop
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-22 00:00:00.000000000 Z
11
+ date: 2016-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -156,6 +156,7 @@ files:
156
156
  - lib/cast_about_for.rb
157
157
  - lib/cast_about_for/base.rb
158
158
  - lib/cast_about_for/search.rb
159
+ - lib/cast_about_for/validate_macro.rb
159
160
  - lib/cast_about_for/version.rb
160
161
  homepage: https://github.com/minnowlab/cast_about_for/
161
162
  licenses: