rails_select_on_includes 0.4.8 → 0.4.9

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: 6a2caeab29b58b5631fc738fa18f31f5256108e1
4
- data.tar.gz: 7d9fd421155250e63ed2557b8e60c60c3b9b8650
3
+ metadata.gz: 7b57b9f8c06e67c99cf4719b7bb192778e4da854
4
+ data.tar.gz: f551cd5aac2d88d2eb159e64002194cf892cc3b5
5
5
  SHA512:
6
- metadata.gz: fbe99ddb4401a7ddfbbec3d391880d3350e627e28ea75561a7aa39816439e9462ba75102c80aadc45ff1e70bf2e23e74e68d83faa8931f8659ad026c6977f13e
7
- data.tar.gz: 600c219a75816d2dce8fb54563e77ff9b185a2b014928e37de8550bf6f33dfc2e128d917448cbbf6a6254c46ba997c61dcf1057bede6d2eb0c01535f945b1f5a
6
+ metadata.gz: 5dd172b53816e4ddd23c827827f51a27811739496c4b446eed27d860e3dfb61e023e24b550a6a8cdcaa5c4df88f179bf566a6cf7642177ed9f37dd1f75752fc6
7
+ data.tar.gz: f45c2992a8f78bb673946ae334764b986cdcea5a8c90aae2c1d5438f8647a0358c105bfc6e2a5b14948f76ffe738342ca38a5e8e62822ac11fe8bf8d96d0de80
data/README.md CHANGED
@@ -1,9 +1,13 @@
1
+ #Rails version
2
+
3
+ Supports rails 4.x and rails 5 now!
4
+
1
5
  # RailsSelectOnIncludes
2
6
 
3
- This gem solves issue in rails: https://github.com/rails/rails/issues/15185 for base_class.
7
+ This gem solves issue in rails: https://github.com/rails/rails/issues/15185 for base_class.
4
8
 
5
9
  It was impossible to select virtual attributes to object from its relations or any other way
6
- when using includes and where.
10
+ when using includes and where ( actually when includes becomes eager_load, i.e. when you add not SOME_CONDITION, but SOME_CONDITION_ON_INCLUDES, http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html ).
7
11
 
8
12
  Example from upper rails issue:
9
13
 
@@ -30,7 +34,7 @@ post.comments.first.testval # Undefined method!
30
34
 
31
35
  Данный gem решает проблему в рельсах с виртуальными аттрибутами при использовании includes,
32
36
  когда рельсы собирают в запрос в joins с алиасами на все аттрибуты. В настоящий момент в модель не собираются
33
- никаким боком виртуальные аттрибуты.
37
+ никаким боком виртуальные аттрибуты ( имеется ввиду когда includes ведет себя как eager_load и создает сложный одинарный запрос, подробнее: http://blog.bigbinary.com/2013/07/01/preload-vs-eager-load-vs-joins-vs-includes.html ).
34
38
 
35
39
  В частности проблема описана здесь: https://github.com/rails/rails/issues/15185
36
40
 
@@ -56,12 +60,16 @@ post.comments.first.testval # Undefined method!
56
60
  ```
57
61
 
58
62
 
59
- ## Installation
63
+ ## Installation
60
64
 
61
65
  Add this line to your application's Gemfile:
62
66
 
63
67
  ```ruby
64
- gem 'rails_select_on_includes'
68
+ #rails 4
69
+ gem 'rails_select_on_includes', '~> 0.4.3'
70
+
71
+ #rails 5
72
+ gem 'rails_select_on_includes', '~> 0.5.0'
65
73
  ```
66
74
 
67
75
  And then execute:
@@ -1,112 +1,106 @@
1
1
  require 'active_support/deprecation'
2
2
  require 'active_support/core_ext/string/filters'
3
3
 
4
- module ActiveRecord
5
- module Associations
6
- class JoinDependency # :nodoc:
7
-
8
- class Aliases # :nodoc:
9
- def initialize(tables)
10
- @tables = tables
11
- @alias_cache = tables.each_with_object({}) { |table,h|
12
- h[table.node] = table.columns.each_with_object({}) { |column,i|
13
- i[column.name] = column.alias
14
- }
15
- }
16
- @name_and_alias_cache = tables.each_with_object({}) { |table,h|
17
- h[table.node] = table.columns.map { |column|
18
- [column.name, column.alias]
19
- }
20
- @base_class_node_aliases ||= h[table.node] if table.node.is_a?(ActiveRecord::Associations::JoinDependency::JoinBase)
21
- }
22
-
23
- @virtual_attributes_names = []
24
- end
25
- # valid formats are:
26
- # 1 'table_name.column' or 'table_name.column as column_1' will be parsed! distinct on can be used also
27
- # 2 {table_name: column} or { table_name: [column1, column2] }
28
- # 3 table_name: 2
29
- def update_aliases_to_select_values( select_values )
30
- return if select_values.blank?
31
- select_values.each do |sv|
32
- # if sv is symbol that we assume that its a base table column and it will be aliased and added as usual
33
- # all we need is some specials joins+select from related tables
34
- if sv.is_a?(Hash)
35
- flatten_hash_values(sv).each{|sub_sv| @base_class_node_aliases << [sub_sv, sub_sv]; @virtual_attributes_names << sub_sv }
36
- elsif sv.is_a?(String)
37
- # this is the case of long raw select
38
- sv.split( ", " ).each do |sub_sv|
39
- if sub_sv[/.+ as .+/i]
40
- selected_column = sub_sv[/ as .+/i][4..-1]
41
- @base_class_node_aliases << [selected_column, selected_column]
42
- @virtual_attributes_names << selected_column
43
- elsif sub_sv[/.+\.[^\*]+/]
44
- selected_column = sub_sv[/\..+/][1..-1]
45
- @base_class_node_aliases << [selected_column, selected_column]
46
- @virtual_attributes_names << selected_column
47
- end
48
- end
49
- end
50
- end
51
- end
52
4
 
53
- def slice_selected_attr_types( column_types )
54
- column_types.slice( *@virtual_attributes_names )
55
- end
56
-
57
- private
58
- def flatten_hash_values( some_hash )
59
- some_hash.values.map{ |value| value.is_a?(Hash) ? flatten_hash_values( value ) : value }.flatten
5
+ ::ActiveRecord::Associations::JoinDependency::Aliases.class_eval do # :nodoc:
6
+ def initialize(tables)
7
+ @tables = tables
8
+ @alias_cache = tables.each_with_object({}) { |table,h|
9
+ h[table.node] = table.columns.each_with_object({}) { |column,i|
10
+ i[column.name] = column.alias
11
+ }
12
+ }
13
+ @name_and_alias_cache = tables.each_with_object({}) { |table,h|
14
+ h[table.node] = table.columns.map { |column|
15
+ [column.name, column.alias]
16
+ }
17
+ @base_class_node_aliases ||= h[table.node] if table.node.is_a?(ActiveRecord::Associations::JoinDependency::JoinBase)
18
+ }
19
+
20
+ @virtual_attributes_names = []
21
+ end
22
+ # valid formats are:
23
+ # 1 'table_name.column' or 'table_name.column as column_1' will be parsed! distinct on can be used also
24
+ # 2 {table_name: column} or { table_name: [column1, column2] }
25
+ # 3 table_name: 2
26
+ def update_aliases_to_select_values( select_values )
27
+ return if select_values.blank?
28
+ select_values.each do |sv|
29
+ # if sv is symbol that we assume that its a base table column and it will be aliased and added as usual
30
+ # all we need is some specials joins+select from related tables
31
+ if sv.is_a?(Hash)
32
+ flatten_hash_values(sv).each{|sub_sv| @base_class_node_aliases << [sub_sv, sub_sv]; @virtual_attributes_names << sub_sv }
33
+ elsif sv.is_a?(String)
34
+ # this is the case of long raw select
35
+ sv.split( ", " ).each do |sub_sv|
36
+ if sub_sv[/.+ as .+/i]
37
+ selected_column = sub_sv[/ as .+/i][4..-1]
38
+ @base_class_node_aliases << [selected_column, selected_column]
39
+ @virtual_attributes_names << selected_column
40
+ elsif sub_sv[/.+\.[^\*]+/]
41
+ selected_column = sub_sv[/\..+/][1..-1]
42
+ @base_class_node_aliases << [selected_column, selected_column]
43
+ @virtual_attributes_names << selected_column
44
+ end
60
45
  end
61
46
  end
47
+ end
48
+ end
62
49
 
63
- class JoinBase
64
- def instantiate(row, aliases, column_types = {}, &block)
65
- base_klass.instantiate(extract_record(row, aliases), column_types, &block)
66
- end
67
- end
50
+ def slice_selected_attr_types( column_types )
51
+ column_types.slice( *@virtual_attributes_names )
52
+ end
68
53
 
69
- def instantiate(result_set, aliases)
70
- primary_key = aliases.column_alias(join_root, join_root.primary_key)
71
-
72
- seen = Hash.new { |h,parent_klass|
73
- h[parent_klass] = Hash.new { |i,parent_id|
74
- i[parent_id] = Hash.new { |j,child_klass| j[child_klass] = {} }
75
- }
76
- }
77
-
78
- model_cache = Hash.new { |h,klass| h[klass] = {} }
79
- parents = model_cache[join_root]
80
- column_aliases = aliases.column_aliases join_root
81
-
82
- message_bus = ActiveSupport::Notifications.instrumenter
83
-
84
- payload = {
85
- record_count: result_set.length,
86
- class_name: join_root.base_klass.name
87
- }
88
-
89
- message_bus.instrument('instantiation.active_record', payload) do
90
- result_set.each { |row_hash|
91
- parent_key = primary_key ? row_hash[primary_key] : row_hash
92
- # DISTINCTION PART > join_root.instantiate(row_hash, column_aliases, aliases.slice_selected_attr_types( result_set.column_types ) )
93
- # PREVIOUS > join_root.instantiate(row_hash, column_aliases )
94
- parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, aliases.slice_selected_attr_types( result_set.column_types ) )
95
- construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
96
- }
97
- end
54
+ private
55
+ def flatten_hash_values( some_hash )
56
+ some_hash.values.map{ |value| value.is_a?(Hash) ? flatten_hash_values( value ) : value }.flatten
57
+ end
58
+ end
98
59
 
99
- parents.values
100
- end
60
+ ::ActiveRecord::Associations::JoinDependency::JoinBase.class_eval do
61
+ def instantiate(row, aliases, column_types = {}, &block)
62
+ base_klass.instantiate(extract_record(row, aliases), column_types, &block)
63
+ end
64
+ end
101
65
 
66
+ ::ActiveRecord::Associations::JoinDependency.class_eval do
67
+ def instantiate(result_set, aliases)
68
+ primary_key = aliases.column_alias(join_root, join_root.primary_key)
69
+
70
+ seen = Hash.new { |h,parent_klass|
71
+ h[parent_klass] = Hash.new { |i,parent_id|
72
+ i[parent_id] = Hash.new { |j,child_klass| j[child_klass] = {} }
73
+ }
74
+ }
75
+
76
+ model_cache = Hash.new { |h,klass| h[klass] = {} }
77
+ parents = model_cache[join_root]
78
+ column_aliases = aliases.column_aliases join_root
79
+
80
+ message_bus = ActiveSupport::Notifications.instrumenter
81
+
82
+ payload = {
83
+ record_count: result_set.length,
84
+ class_name: join_root.base_klass.name
85
+ }
86
+
87
+ message_bus.instrument('instantiation.active_record', payload) do
88
+ result_set.each { |row_hash|
89
+ parent_key = primary_key ? row_hash[primary_key] : row_hash
90
+ # DISTINCTION PART > join_root.instantiate(row_hash, column_aliases, aliases.slice_selected_attr_types( result_set.column_types ) )
91
+ # PREVIOUS > join_root.instantiate(row_hash, column_aliases )
92
+ parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases, aliases.slice_selected_attr_types( result_set.column_types ) )
93
+ construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
94
+ }
102
95
  end
96
+
97
+ parents.values
103
98
  end
104
99
  end
105
100
 
106
- module ActiveRecord
107
- module FinderMethods
108
101
 
109
- def find_with_associations
102
+ ::ActiveRecord::FinderMethods.class_eval do
103
+ def find_with_associations
110
104
  # NOTE: the JoinDependency constructed here needs to know about
111
105
  # any joins already present in `self`, so pass them in
112
106
  #
@@ -138,7 +132,6 @@ module ActiveRecord
138
132
  end
139
133
  end
140
134
  end
141
-
142
- end
143
135
  end
144
136
 
137
+
@@ -1,3 +1,3 @@
1
1
  module RailsSelectOnIncludes
2
- VERSION = "0.4.8"
2
+ VERSION = "0.4.9"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_select_on_includes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8
4
+ version: 0.4.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - alekseyl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-14 00:00:00.000000000 Z
11
+ date: 2017-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord