rails_select_on_includes 0.4.8 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
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