ignorable_columns 0.1.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ac94ca93373065385343ea60d4e28583e965998
4
+ data.tar.gz: fb1a0c2a16f227faf1ab78c7cb40af22fe419bb4
5
+ SHA512:
6
+ metadata.gz: '09d2a9502e1e110e46fcb40d31f4ef2cedbcffbe90ee132bd861bc4a3477e680f068ceb619f7915dafd299aff38fb0022d7b31cfb211802767482d568f07a27f'
7
+ data.tar.gz: ccead360f04467988ae439d1f21f22140ea5861e000fde99abbe5dd5bd058a84d8558e80851735534846e2ef7338671b8f393eb34a1cb0e00361b483a8ba1f09
@@ -0,0 +1,194 @@
1
+ require 'active_record'
2
+ require 'active_support/core_ext/class/attribute'
3
+
4
+ module IgnorableColumns
5
+ module InstanceMethods
6
+ def attributes # :nodoc:
7
+ if self.class.include_columns?
8
+ super.reject { |col, _val| self.class.ignored_column?(col) && !self.class.included_columns.include?(col) }
9
+ else
10
+ super.reject { |col, _val| self.class.ignored_column?(col) }
11
+ end
12
+ end
13
+
14
+ def attribute_names # :nodoc:
15
+ if self.class.include_columns?
16
+ super.reject { |col| self.class.ignored_column?(col) && !self.class.included_columns.include?(col) }
17
+ else
18
+ super.reject { |col| self.class.ignored_column?(col) }
19
+ end
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ # Prevent Rails from loading a table column.
25
+ # Useful for legacy database schemas with problematic column names,
26
+ # like 'class' or 'attributes'.
27
+ #
28
+ # class Topic < ActiveRecord::Base
29
+ # ignore_columns :attributes, :class
30
+ # end
31
+ #
32
+ # Topic.new.respond_to?(:attributes) => false
33
+ def ignore_columns(*cols)
34
+ self.ignorable_columns ||= []
35
+ self.ignorable_columns += (cols || []).map(&:to_s)
36
+ self.ignorable_columns.tap(&:uniq!)
37
+ reset_columns
38
+ columns
39
+ end
40
+ alias ignore_column ignore_columns
41
+
42
+ # Ignore columns for select statements.
43
+ # Useful for optimizing queries that load large amounts of rarely data.
44
+ # Exclude ignored columns from the sql queries.
45
+ # NOTE: should be called after #ignore_columns
46
+ #
47
+ # class Topic < ActiveRecord::Base
48
+ # ignore_columns :attributes, :class
49
+ # ignore_columns_in_sql
50
+ # end
51
+ def ignore_columns_in_sql
52
+ (self.default_scopes = orig_default_scopes) && return unless ignorable_columns.present?
53
+ unless default_scopes.include? default_scopes_cache[ignorable_columns]
54
+ default_scopes_cache[ignorable_columns] ||= proc { select(*(all_columns.map(&:name) - ignorable_columns)) }
55
+ self.default_scopes = (default_scopes.clone || []) << default_scopes_cache[ignorable_columns]
56
+ end
57
+ end
58
+ alias ignore_column_in_sql ignore_columns_in_sql
59
+
60
+ # Has a column been ignored?
61
+ # Accepts both ActiveRecord::ConnectionAdapter::Column objects,
62
+ # and actual column names ('title')
63
+ def ignored_column?(column)
64
+ self.ignorable_columns.present? && self.ignorable_columns.include?(
65
+ column.respond_to?(:name) ? column.name : column.to_s
66
+ )
67
+ end
68
+
69
+ # Execute block in a scope including all or some of the ignored columns.
70
+ # If no arguments are passed all ignored columns will be included, otherwise
71
+ # only the subset passed as argument will be included.
72
+ #
73
+ # class Topic < ActiveRecord::Base
74
+ # ignore_columns :attributes, :class
75
+ # ignore_columns_in_sql
76
+ # end
77
+ # ...
78
+ # Topic.including_ignored_columns { Topic.last(5).map(&:attributes) }
79
+ # Topic.including_ignored_columns(:class) { Topic.last(5).map(&:attributes) }
80
+ def including_ignored_columns(*cols)
81
+ st_cols = cols.map(&:to_s)
82
+ sy_cols = cols.map(&:to_sym)
83
+ if including_columns_subclass_cache[sy_cols].present?
84
+ return including_columns_subclass_cache[sy_cols]
85
+ else
86
+ subclass_name = including_ignored_columns_subclass_name(st_cols)
87
+ begin
88
+ including_columns_subclass_cache[sy_cols] = Object.const_get(subclass_name)
89
+ return including_columns_subclass_cache[sy_cols]
90
+ rescue NameError
91
+ including_columns_subclass_cache[sy_cols] = generate_subclass_for_ignored_cols(subclass_name, st_cols)
92
+ end
93
+ end
94
+ end
95
+
96
+ def columns # :nodoc:
97
+ if @all_columns
98
+ @columns ||= super.reject { |col| ignored_column?(col) }
99
+ else
100
+ @all_columns = super
101
+ @columns = super.reject { |col| ignored_column?(col) }
102
+ end
103
+ end
104
+
105
+ def column_names # :nodoc:
106
+ if @all_column_names
107
+ @column_names ||= @all_column_names.reject { |col| ignored_column?(col) }
108
+ else
109
+ @all_column_names = all_columns.map(&:name)
110
+ @column_names = @all_column_names.reject { |col| ignored_column?(col) }
111
+ end
112
+ end
113
+
114
+ def include_columns? # :nodoc:
115
+ @include_columns
116
+ end
117
+
118
+ def included_columns # :nodoc:
119
+ @included_columns
120
+ end
121
+
122
+ def reset_ignorable_columns
123
+ reset_columns
124
+ self.default_scopes = orig_default_scopes
125
+ end
126
+
127
+ def including_ignored_columns_subclass_name(cols = nil)
128
+ subclass_name = name + 'With'
129
+ subclass_name += if cols.present?
130
+ cols.sort.map(&:camelcase).join
131
+ else
132
+ 'All'
133
+ end
134
+ subclass_name
135
+ end
136
+
137
+ private
138
+
139
+ def generate_subclass_for_ignored_cols(name, st_cols)
140
+ new_subclass = Object.const_set(name, Class.new(self))
141
+ temp_ignorable_columns = st_cols.present? ? ignorable_columns - st_cols : []
142
+
143
+ new_subclass.reset_ignorable_columns
144
+ new_subclass.ignorable_columns = temp_ignorable_columns
145
+ new_subclass.default_scopes = orig_default_scopes
146
+ new_subclass.ignore_columns_in_sql if default_scopes != orig_default_scopes
147
+
148
+ new_subclass
149
+ end
150
+
151
+ def including_columns_subclass_cache
152
+ @including_columns_subclass_cache ||= {}
153
+ end
154
+
155
+ def default_scopes_cache
156
+ @default_scopes_cache ||= {}
157
+ end
158
+
159
+ def all_columns
160
+ columns unless @all_columns
161
+ @all_columns
162
+ end
163
+
164
+ def all_column_names
165
+ column_names unless @all_column_names
166
+ @all_column_names
167
+ end
168
+
169
+ def orig_default_scopes
170
+ default_scopes - default_scopes_cache.values
171
+ end
172
+
173
+ def init_columns(col_names = nil)
174
+ reset_columns
175
+ @columns = col_names.nil? ? all_columns : all_columns.select { |c| col_names.include? c.name }
176
+ @column_names = col_names.nil? ? all_column_names : all_column_names.select { |cn| col_names.include? cn }
177
+ end
178
+
179
+ def reset_columns
180
+ reset_column_information
181
+ descendants.each(&:reset_column_information)
182
+ @columns = nil
183
+ @column_names = nil
184
+ end
185
+ end
186
+
187
+ def self.included(base)
188
+ base.send :include, InstanceMethods
189
+ base.extend ClassMethods
190
+ base.send :class_attribute, :ignorable_columns
191
+ end
192
+ end
193
+
194
+ ActiveRecord::Base.send(:include, IgnorableColumns) unless ActiveRecord::Base.include?(IgnorableColumns::InstanceMethods)
@@ -0,0 +1,3 @@
1
+ module IgnorableColumns
2
+ VERSION = "0.1.2"
3
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ignorable_columns
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Calin Ciobanu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5'
33
+ - !ruby/object:Gem::Dependency
34
+ name: sqlite3
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '3'
75
+ description: Inspired by ignorable gem with support for sql queries ignore columns
76
+ and bypass ignored columns on demand
77
+ email:
78
+ - ciobanu.calin@gmail.com
79
+ executables: []
80
+ extensions: []
81
+ extra_rdoc_files: []
82
+ files:
83
+ - lib/ignorable_columns.rb
84
+ - lib/ignorable_columns/version.rb
85
+ homepage: https://github.com/calin-ciobanu/ignorable_columns
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.6.13
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Inspired by ignorable gem with several enhancements.
109
+ test_files: []