acts_as_multilingual 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: da09ca7f531d12c0464a238d1fb3564a789c2273
4
+ data.tar.gz: 827435cb797c5619de6547906d8fb9f833b07089
5
+ SHA512:
6
+ metadata.gz: 9e5657dcf968ca26b02200fd1642460a4e801759f002777d2bc3d76e5c8e3a57e1fc7c15ecbdbd0e25ac94c0f5c91d087e6f302c15a27e6ac6bbc188a51c5d36
7
+ data.tar.gz: 388383e5cf6e79d04345e036bd05289853693e18f002eebfa658aa30496d4ca798c83b732f8142cf5b341a020654a6ed528dbba0ace3288e2f375b7ccb9c03ae
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ pkg/
3
+ vendor/bundle/
4
+
5
+ .ruby-version
6
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
@@ -0,0 +1,2 @@
1
+ Style/Documentation:
2
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,3 @@
1
+ # Acts As Multilingual
2
+
3
+ Don't forget to add some meaningful description here.
@@ -0,0 +1,15 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ RuboCop::RakeTask.new(:rubocop) do |task|
9
+ task.fail_on_error = false
10
+ task.options = %w(--force-exclusion)
11
+ task.patterns = %w({lib,spec}/**/*.rb)
12
+ task.requires << 'rubocop-rspec'
13
+ end
14
+
15
+ task default: %w(spec rubocop)
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'acts_as_multilingual/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'acts_as_multilingual'
8
+ spec.version = ActsAsMultilingual::VERSION
9
+ spec.authors = ['Alexander Tipugin']
10
+ spec.email = ['atipugin@gmail.com']
11
+ spec.summary = 'Store multilingual columns in JSON'
12
+ spec.homepage = 'https://github.com/atipugin/acts_as_multilingual'
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.bindir = 'exe'
16
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.require_paths = ['lib']
18
+
19
+ spec.add_development_dependency 'bundler', '~> 1.10'
20
+ spec.add_development_dependency 'rake', '~> 10.4'
21
+ spec.add_development_dependency 'pry', '~> 0.10'
22
+ spec.add_development_dependency 'rspec', '~> 3.4'
23
+ spec.add_development_dependency 'rubocop', '~> 0.35'
24
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.3'
25
+ spec.add_development_dependency 'sqlite3'
26
+
27
+ spec.add_dependency 'activerecord', '>= 3.2'
28
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'pry'
4
+
5
+ require 'acts_as_multilingual'
6
+
7
+ Pry.start
@@ -0,0 +1,7 @@
1
+ require 'active_record'
2
+
3
+ require 'acts_as_multilingual/version'
4
+ require 'acts_as_multilingual/extension'
5
+ require 'acts_as_multilingual/builder'
6
+ require 'acts_as_multilingual/exceptions'
7
+ require 'acts_as_multilingual/attribute_proxy'
@@ -0,0 +1,19 @@
1
+ module ActsAsMultilingual
2
+ class AttributeProxy
3
+ attr_reader :owner, :column
4
+
5
+ def initialize(owner, column)
6
+ @owner = owner
7
+ @column = column
8
+ end
9
+
10
+ def read(locale)
11
+ owner[column][locale]
12
+ end
13
+
14
+ def write(locale, value)
15
+ owner[column][locale] = value
16
+ owner[column].delete(locale) unless value
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,90 @@
1
+ module ActsAsMultilingual
2
+ class Builder
3
+ JSON_TYPES = [:json, :jsonb].freeze
4
+ TEXT_TYPES = [:text, :string].freeze
5
+
6
+ attr_reader :klass, :options, :columns
7
+
8
+ def initialize(klass, *args)
9
+ @klass = klass
10
+ @options = args.extract_options!.merge(default_options)
11
+ @columns = args.map(&:to_s)
12
+
13
+ check_columns!
14
+ prepare_klass
15
+ define_accessors
16
+ end
17
+
18
+ private
19
+
20
+ def default_options
21
+ { locales: I18n.available_locales, default_locale: I18n.locale }
22
+ end
23
+
24
+ def check_columns!
25
+ columns.each do |column|
26
+ check_column_presence!(column)
27
+ check_column_type!(column)
28
+ end
29
+ end
30
+
31
+ def check_column_presence!(column)
32
+ return if klass.columns_hash.keys.include?(column)
33
+ fail Exceptions::MissingColumn,
34
+ "Column `#{column}` is missing in table `#{klass.table_name}`"
35
+ end
36
+
37
+ def check_column_type!(column)
38
+ if (JSON_TYPES + TEXT_TYPES).include?(klass.columns_hash[column].type)
39
+ return
40
+ end
41
+
42
+ fail Exceptions::InvalidColumnType,
43
+ "Column `#{column}` has invalid column type"
44
+ end
45
+
46
+ def prepare_klass
47
+ columns.each do |column|
48
+ if TEXT_TYPES.include?(klass.columns_hash[column].type)
49
+ klass.send(:serialize, column, Hash)
50
+ end
51
+ end
52
+ end
53
+
54
+ def define_accessors
55
+ columns.each do |column|
56
+ options[:locales].each do |locale|
57
+ define_reader(column, locale)
58
+ define_writer(column, locale)
59
+ end
60
+
61
+ alias_default_locale(column)
62
+ end
63
+ end
64
+
65
+ def define_reader(column, locale)
66
+ klass.send(:define_method, "#{column}_#{locale}") do
67
+ (@_acts_as_multilingual_cache ||= {}).fetch(column) do
68
+ @_acts_as_multilingual_cache[column] =
69
+ AttributeProxy.new(self, column)
70
+ end.read(locale)
71
+ end
72
+ end
73
+
74
+ def define_writer(column, locale)
75
+ klass.send(:define_method, "#{column}_#{locale}=") do |value|
76
+ (@_acts_as_multilingual_cache ||= {}).fetch(column) do
77
+ @_acts_as_multilingual_cache[column] =
78
+ AttributeProxy.new(self, column)
79
+ end.write(locale, value)
80
+ end
81
+ end
82
+
83
+ def alias_default_locale(column)
84
+ klass.send(:alias_method, column, "#{column}_#{options[:default_locale]}")
85
+ klass.send(:alias_method,
86
+ "#{column}=",
87
+ "#{column}_#{options[:default_locale]}=")
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,2 @@
1
+ require 'acts_as_multilingual/exceptions/base'
2
+ require 'acts_as_multilingual/exceptions/missing_column'
@@ -0,0 +1,6 @@
1
+ module ActsAsMultilingual
2
+ module Exceptions
3
+ class Base < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module ActsAsMultilingual
2
+ module Exceptions
3
+ class InvalidColumnType < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module ActsAsMultilingual
2
+ module Exceptions
3
+ class MissingColumn < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ module ActsAsMultilingual
2
+ module Extension
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def acts_as_multilingual(*args)
9
+ ActsAsMultilingual::Builder.new(self, *args)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ ActiveRecord::Base.send(:include, ActsAsMultilingual::Extension)
@@ -0,0 +1,3 @@
1
+ module ActsAsMultilingual
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,14 @@
1
+ RSpec.describe ActsAsMultilingual::AttributeProxy do
2
+ let(:owner) { User.new }
3
+ let(:column) { :first_name }
4
+
5
+ subject { described_class.new(owner, column) }
6
+
7
+ describe '#read' do
8
+ # ...
9
+ end
10
+
11
+ describe '#write' do
12
+ # ...
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ RSpec.describe ActsAsMultilingual::Builder do
2
+ let(:klass) { User }
3
+ let(:columns) { %w(first_name last_name) }
4
+ let(:object) { subject.klass.new }
5
+ let(:attr_name) { subject.columns.sample }
6
+
7
+ subject { described_class.new(klass, *columns) }
8
+
9
+ it 'has options' do
10
+ expect(subject.options).to be
11
+ end
12
+
13
+ describe '#check_columns!' do
14
+ context 'when column is missing' do
15
+ let(:columns) { %w(hola) }
16
+
17
+ it 'raises an error' do
18
+ expect { subject }
19
+ .to raise_error(ActsAsMultilingual::Exceptions::MissingColumn)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe '#define_accessors' do
25
+ it 'defines getters' do
26
+ expect(object).to respond_to(attr_name)
27
+ end
28
+
29
+ it 'defines setters' do
30
+ expect(object).to respond_to("#{attr_name}=")
31
+ end
32
+ end
33
+
34
+ describe '#define_reader' do
35
+ it 'instantiates cache' do
36
+ object.send(attr_name)
37
+ expect(object.instance_variable_get('@_acts_as_multilingual_cache')).to be
38
+ end
39
+
40
+ it 'reads value properly' do
41
+ val = 'hey'
42
+ object.send("#{attr_name}=", val)
43
+ expect(object.send(attr_name)).to eq(val)
44
+ end
45
+ end
46
+
47
+ describe '#define_writer' do
48
+ it 'instantiates cache' do
49
+ object.send("#{attr_name}=", 'hello')
50
+ expect(object.instance_variable_get('@_acts_as_multilingual_cache')).to be
51
+ end
52
+
53
+ it 'writes value properly' do
54
+ val = 'hoi'
55
+ expect { object.send("#{attr_name}=", val) }
56
+ .to change { object.send(attr_name) }.to(val)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,10 @@
1
+ RSpec.describe ActsAsMultilingual::Extension do
2
+ it 'extends AR methods' do
3
+ expect(ActiveRecord::Base).to respond_to(:acts_as_multilingual)
4
+ end
5
+
6
+ it 'invokes builder' do
7
+ expect(ActsAsMultilingual::Builder).to receive(:new)
8
+ ActiveRecord::Base.acts_as_multilingual
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ require 'acts_as_multilingual'
2
+
3
+ Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
@@ -0,0 +1,13 @@
1
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3',
2
+ database: ':memory:')
3
+
4
+ ActiveRecord::Schema.define do
5
+ create_table :users do |t|
6
+ t.text :first_name
7
+ t.text :last_name
8
+ end
9
+ end
10
+
11
+ class User < ActiveRecord::Base
12
+ acts_as_multilingual :first_name, :last_name
13
+ end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_multilingual
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Tipugin
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.35'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.35'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sqlite3
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: activerecord
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '3.2'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '3.2'
125
+ description:
126
+ email:
127
+ - atipugin@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".rspec"
134
+ - ".rubocop.yml"
135
+ - Gemfile
136
+ - README.md
137
+ - Rakefile
138
+ - acts_as_multilingual.gemspec
139
+ - bin/console
140
+ - lib/acts_as_multilingual.rb
141
+ - lib/acts_as_multilingual/attribute_proxy.rb
142
+ - lib/acts_as_multilingual/builder.rb
143
+ - lib/acts_as_multilingual/exceptions.rb
144
+ - lib/acts_as_multilingual/exceptions/base.rb
145
+ - lib/acts_as_multilingual/exceptions/invalid_column_type.rb
146
+ - lib/acts_as_multilingual/exceptions/missing_column.rb
147
+ - lib/acts_as_multilingual/extension.rb
148
+ - lib/acts_as_multilingual/version.rb
149
+ - spec/lib/acts_as_multilingual/attribute_proxy_spec.rb
150
+ - spec/lib/acts_as_multilingual/builder_spec.rb
151
+ - spec/lib/acts_as_multilingual/extension_spec.rb
152
+ - spec/spec_helper.rb
153
+ - spec/support/schema.rb
154
+ homepage: https://github.com/atipugin/acts_as_multilingual
155
+ licenses: []
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.4.5.1
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Store multilingual columns in JSON
177
+ test_files: []