ar_virtual_field 0.7.0 → 0.9.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
  SHA256:
3
- metadata.gz: 8c391b47a216fd9d3f4d88fded8000f516eb80cf8bcec72261ae11aba4db36da
4
- data.tar.gz: b2c66124f49c5ab41911619a6bb035dda7654c221b8968bbba37625ad0137351
3
+ metadata.gz: d7a9c50d5fa5be76b750cd68d22f5fe8ca0c15e2eb88c099c5d73b6a2b728815
4
+ data.tar.gz: 6801aa54d664672c35977025215fd5d1c00f030c2f1c3ddc78ba2d54a72aea15
5
5
  SHA512:
6
- metadata.gz: e7ff29785eeef3a6b1b1b77f7711fe0fb776304d7ab7e6f7b70028cd07f7be8d81a1b6b289c82a7be3ac852c4e41baea0cbe6f1be58a2e9ff68e1a9bde7a672a
7
- data.tar.gz: fd45c9a488e01424d808e6b16647419eb74dc5a3094159ccce1992745f94bf03723da47849a6abe8d9bb851304d3e50949bfcbc42fe3957cbe0c2a72cd9ccb42
6
+ metadata.gz: '09e2c21db4d2d3d9ea91056ba87d355a6c2ff27a2a4c9119182164bf5f201c76602ef9bc28f9298497fee79c56b50010f8adf4523fde81e7a1c65a4d9c8e3799'
7
+ data.tar.gz: d99b66f81f0ea83605448fe246bb432a3cdb93db4a4d80eeecbe3a92836ff44ef701482b8d2bf3669a1ac2e9d8ab80245e7315daf66f03f1203ef4bc3aa3ccb8
data/README.md CHANGED
@@ -39,12 +39,12 @@ Example:
39
39
  class User < ApplicationRecord
40
40
  virtual_field :total_orders,
41
41
  scope: -> { joins(:orders).group(:id) },
42
- select: -> { "COUNT(orders.id)" },
42
+ select: "COUNT(orders.id)",
43
43
  get: -> { orders.count },
44
44
  default: 0
45
45
 
46
46
  virtual_field :fullname,
47
- select: -> { "name || surname" },
47
+ select: "name || surname",
48
48
  get: -> { "#{name}#{surname}" }
49
49
  end
50
50
 
@@ -52,7 +52,7 @@ users_with_orders = User.with_total_orders # queries database once
52
52
 
53
53
  user = users_with_orders.first
54
54
  user.total_orders # => value computed by database
55
- user.fullname # => value computed by database
55
+ user.fullname # => value computed by ruby
56
56
  ```
57
57
 
58
58
  ### Scopes and querying:
@@ -60,12 +60,9 @@ user.fullname # => value computed by database
60
60
  - `with_#{name}`: Automatically generated scope to include the virtual field in queries. You can use this scope in your ActiveRecord queries like so:
61
61
 
62
62
  ```ruby
63
- User.with_total_orders.where(ArVirtualField[:total_orders] => 5)
63
+ User.with_total_orders.where(User.virtual_fields[:total_orders].eq(5))
64
64
  ```
65
65
 
66
- > [!WARNING]
67
- > `ArVirtualField[]` doesn't sanitize its value itself, this example relies on `#where` sanitation, use with caution
68
-
69
66
  This will include the total_orders virtual field in the SQL query and allow filtering by it.
70
67
 
71
68
  ## Contributing
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArVirtualField
4
- VERSION = "0.7.0"
4
+ VERSION = "0.9.0"
5
5
  end
@@ -21,11 +21,21 @@ module ArVirtualField
21
21
  end
22
22
  end
23
23
 
24
- def self.[](field)
25
- Arel.sql(HelperMethods.table_with_column(field))
24
+ class FieldsData < Hash
25
+ def [](field)
26
+ statement = super(field.to_sym)
27
+ raise "Unknown virtual field `#{field}`" unless statement
28
+ statement.()
29
+ end
30
+ end
31
+
32
+ def virtual_fields
33
+ @ar_virtual_fields || FieldsData.new
26
34
  end
27
35
 
28
36
  def virtual_field(name, scope: nil, select:, get:, default: nil)
37
+ @ar_virtual_fields ||= FieldsData.new
38
+
29
39
  name = name.to_s
30
40
  current_class = self
31
41
  unwrap_arel_expression = -> (exp) { exp.is_a?(Arel::Nodes::NodeExpression) ? exp : Arel.sql(exp) }
@@ -40,6 +50,8 @@ module ArVirtualField
40
50
  end
41
51
 
42
52
  if scope
53
+ @ar_virtual_fields[name.to_sym] = -> { Arel.sql(HelperMethods.table_with_column(name)) }
54
+
43
55
  scope_name = :"_scope_#{name}"
44
56
 
45
57
  scope(scope_name, scope)
@@ -51,10 +63,16 @@ module ArVirtualField
51
63
 
52
64
  HelperMethods.select_append(joins(<<~SQL.squish), "#{HelperMethods.table_with_column(name)} AS #{name}")
53
65
  LEFT JOIN (#{scope_query.to_sql}) #{HelperMethods.table_name(name)}
54
- ON #{HelperMethods.table_name(name)}.id = #{table_name}.id
66
+ ON #{
67
+ Array(primary_key).map do |pk|
68
+ "#{HelperMethods.table_name(name)}.#{pk} = #{table_name}.#{pk}"
69
+ end.join(' AND')
70
+ }
55
71
  SQL
56
72
  end)
57
73
  else
74
+ @ar_virtual_fields[name.to_sym] = -> { select_lambda.() }
75
+
58
76
  scope(:"with_#{name}", -> do
59
77
  HelperMethods.select_append(self, select_lambda.().as(name))
60
78
  end)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_virtual_field
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Egorov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-17 00:00:00.000000000 Z
11
+ date: 2024-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 6.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  description: Adds .virtual_field method to make it easy to define virtual fields
28
56
  email:
29
57
  - moonmeander47@ya.ru