from_clause_translate 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0ef0f453b7b049fbbd56b0126065dcba8a5ab0b5
4
+ data.tar.gz: a9f8cf9715a75b690cd8fb4caae8d2bed506fac1
5
+ SHA512:
6
+ metadata.gz: 1e134c794ac0aebc741de3990ca797fe6378dbddfd2ef5ffc2d25ee53537be5be4a47a6d8946cded1459d6f6d6079d9d8ad9d09e69dafec4a3fcfa8798823651
7
+ data.tar.gz: b54da2a3cbcf67ecab08506c501092cc6b947308500ae07b88f5a77984f0804962738ef8286d8fbcb4da3af698c63c0f5d7b26ba32d92eab3180d756e47128cf
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Roman Kushin
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # FromClauseTranslate
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'from_clause_translate'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install from_clause_translate
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,3 @@
1
+ module FromClauseTranslate
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,250 @@
1
+ module ActiveRecord::Relation::Extended
2
+ def to_sql
3
+ apply_translates unless eager_loading?
4
+ super
5
+ end
6
+
7
+ def exec_queries &block
8
+ apply_translates
9
+ super(&block)
10
+ end
11
+
12
+ def pluck *columns
13
+ if !@translated_extra_columns && @klass.const_defined?(:TRANSLATED)
14
+ @translated_extra_columns = columns
15
+ end
16
+ super(*columns)
17
+ end
18
+
19
+ def arel aliases = nil
20
+ arel = super aliases
21
+ if @translated_extra_columns
22
+ add_translated_columns @translated_extra_columns
23
+ @translated_extra_columns = nil
24
+ apply_translates arel
25
+ end
26
+ arel
27
+ end
28
+
29
+ def add_translated_columns columns
30
+ (@values[:translated] ||= []).concat columns
31
+ end
32
+
33
+ def apply_translates arel = nil
34
+ arel ||= self.arel
35
+ return if @translates_applied || !@klass.const_defined?(:TRANSLATED)
36
+ @translates_applied = true
37
+ columns = translated_columns_get
38
+ return unless columns
39
+ from = @klass.select(columns).arel.to_sql
40
+ as = @klass.table_name
41
+ arel.from("(#{from}) #{as}")
42
+ end
43
+
44
+ def translated_columns_get without_projections = false
45
+ columns = []
46
+ has_translated = false
47
+
48
+ translated = @values[:translated]
49
+ if translated
50
+ translated.each do |column|
51
+ if column.is_a? Hash
52
+ has_translated = true
53
+ column.each do |key, value|
54
+ columns << "#{value} AS #{key}"
55
+ end
56
+ elsif @klass.translates? column
57
+ columns << @klass::TRANSLATED_SELECTION[I18n.locale][column.to_sym]
58
+ has_translated = true
59
+ else
60
+ columns << column
61
+ end
62
+ end
63
+ end
64
+
65
+ unless without_projections
66
+ arel.projections.each do |column|
67
+ if column.is_a? Arel::Attributes::Attribute
68
+ columns << column.name
69
+ elsif column.is_a? String
70
+ name = column.first == '"' ? column[1...-1] : column
71
+ if @klass.translates? name
72
+ has_translated = true
73
+ sym = name.to_sym
74
+ columns << @klass::TRANSLATED_SELECTION[I18n.locale][sym]
75
+ plural = @klass::TRANSLATED_PLURALS[sym]
76
+ if plural
77
+ column.replace plural
78
+ end
79
+ else
80
+ columns << column
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ arel.ast.cores.each do |core|
87
+ core.wheres.each do |where|
88
+ where.children.each do |child|
89
+ if child.respond_to? :left
90
+ name = child.left.name
91
+ if @klass.translates? name
92
+ has_translated = true
93
+ columns << @klass::TRANSLATED_SELECTION[I18n.locale][name.to_sym]
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ core.groups.each do |group|
100
+ expr = group.expr
101
+ name = expr[0] == '"' ? expr[1...-1] : expr
102
+ if @klass.translates? name
103
+ has_translated = true
104
+ columns << @klass::TRANSLATED_SELECTION[I18n.locale][name.to_sym]
105
+ end
106
+ end
107
+
108
+ core.havings.each do |having|
109
+ having.children.each do |child|
110
+ if child.respond_to? :left
111
+ name = child.left.name
112
+ if @klass.translates? name
113
+ has_translated = true
114
+ columns << @klass::TRANSLATED_SELECTION[I18n.locale][name.to_sym]
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ arel.ast.orders.each do |name|
122
+ name = name.respond_to?(:expr) ? name.expr.name : name.to_sym
123
+ if @klass.translates? name
124
+ has_translated = true
125
+ columns << @klass::TRANSLATED_SELECTION[I18n.locale][name.to_sym]
126
+ end
127
+ end
128
+
129
+ columns if has_translated
130
+ end
131
+
132
+ private
133
+
134
+ def perform_calculation operation, column_name
135
+ if column_name && !@translated_extra_columns &&
136
+ @klass.const_defined?(:TRANSLATED)
137
+ @translated_extra_columns = [column_name]
138
+ end
139
+ super operation, column_name
140
+ end
141
+ end
142
+
143
+ class ActiveRecord::Relation
144
+ prepend ActiveRecord::Relation::Extended
145
+ end
146
+
147
+ module FromClauseTranslate
148
+ def self.included model
149
+ model.instance_variable_set :@original_connection, model.connection
150
+ model.extend ClassMethods
151
+ model.const_set :TRANSLATED, {}
152
+ model.const_set :TRANSLATED_PLURALS, {}
153
+ model.const_set :TRANSLATED_SELECTION, Hash[
154
+ I18n.available_locales.map { |locale| [locale, {}] }
155
+ ]
156
+ end
157
+
158
+ module ClassMethods
159
+ def translates *columns
160
+ options = columns.extract_options!
161
+ filter_translated_columns(columns).each do |column|
162
+ self::TRANSLATED[column] = true
163
+ I18n.available_locales.each do |locale|
164
+ self::TRANSLATED_SELECTION[locale][column] =
165
+ "#{column}_#{locale} AS #{column}"
166
+ end
167
+ define_translated_column_methods column
168
+ end
169
+ plurals = options[:plurals]
170
+ if plurals
171
+ plurals.each do |plural|
172
+ plural = plural.to_sym
173
+ self::TRANSLATED[plural] = true
174
+ column = plural.to_s.singularize.to_sym
175
+ selection = I18n.available_locales.map do |locale|
176
+ "#{column}_#{locale}"
177
+ end.join ','
178
+ self::TRANSLATED_PLURALS[plural] = selection
179
+ I18n.available_locales.each do |locale|
180
+ self::TRANSLATED_SELECTION[locale][plural] = selection
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ def translates? column
187
+ self::TRANSLATED[column.to_sym]
188
+ end
189
+
190
+ def translated *columns
191
+ scope = current_scope || all
192
+ scope.add_translated_columns columns
193
+ scope
194
+ end
195
+
196
+ private
197
+
198
+ def filter_translated_columns columns
199
+ columns.keep_if do |column|
200
+ !translates?(column) &&
201
+ column_names.include?("#{column}_#{I18n.locale}")
202
+ end
203
+ end
204
+
205
+ def define_translated_column_methods column
206
+ column = column.to_s
207
+ with_dash = "#{column}_"
208
+
209
+ define_method column do
210
+ if @attributes.key?(column)
211
+ self[column]
212
+ else
213
+ send(with_dash + I18n.locale.to_s)
214
+ end
215
+ end
216
+
217
+ define_method column + '=' do |value|
218
+ send "#{with_dash}#{I18n.locale}=", value
219
+ end
220
+
221
+ define_method column + '_changed?' do
222
+ send "#{with_dash}#{I18n.locale}_changed?"
223
+ end
224
+
225
+ define_method 'saved_change_to_' + column do
226
+ send "saved_change_to_#{with_dash}#{I18n.locale}"
227
+ end
228
+
229
+ define_method 'saved_change_to_' + column + '?' do
230
+ send "saved_change_to_#{with_dash}#{I18n.locale}?"
231
+ end
232
+
233
+ define_method column + '_before_last_save' do
234
+ send "#{with_dash}#{I18n.locale}_before_last_save"
235
+ end
236
+
237
+ define_method 'will_save_change_to_' + column + '?' do
238
+ send "will_save_change_to_#{with_dash}#{I18n.locale}?"
239
+ end
240
+
241
+ define_method with_dash + 'change_to_be_saved' do
242
+ send "#{with_dash}#{I18n.locale}_change_to_be_saved"
243
+ end
244
+
245
+ define_method with_dash + 'in_database' do
246
+ send "#{with_dash}#{I18n.locale}_in_database"
247
+ end
248
+ end
249
+ end
250
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: from_clause_translate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Roman Kushin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ description: Translates record using SQL from clause.
28
+ email:
29
+ - romadzao@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - lib/from_clause_translate.rb
37
+ - lib/from_clause_translate/version.rb
38
+ homepage:
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.6.11
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: For database record translations
62
+ test_files: []