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 +7 -0
- data/lib/ignorable_columns.rb +194 -0
- data/lib/ignorable_columns/version.rb +3 -0
- metadata +109 -0
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)
|
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: []
|