multilang 0.0.1

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.
@@ -0,0 +1,71 @@
1
+ require 'multilang/language_names'
2
+
3
+ module Multilang
4
+ class Slot
5
+ def initialize
6
+ @items = {}
7
+ end
8
+
9
+ # Register the object to the slot.
10
+ #
11
+ # @param [String, Symbol] language_spec the language specifier
12
+ # @param [Object] object object to register
13
+ # @yield called once at getting the object first
14
+ #
15
+ # @see Multilang::Slot#[]
16
+ def register(language_spec, object, &first)
17
+ item = {:object => object}
18
+ item[:first] = first if first
19
+ @items[LanguageNames[language_spec]] = item
20
+ end
21
+
22
+ # Determine if registered with the language specifier in the slot.
23
+ #
24
+ # @param [String, Symbol] language_spec the language specifier
25
+ # @return whether registered with the language specifier in the slot
26
+ def exists?(language_spec)
27
+ !!@items[LanguageNames[language_spec]]
28
+ end
29
+
30
+ # Get the object by the language specifier. And call once the block that was
31
+ # given at registration the object.
32
+ #
33
+ # @param [String, Symbol] language_spec the language specifier
34
+ # @return [Object] registered object in the slot
35
+ #
36
+ # @see Multilang::Slot#register
37
+ def [](language_spec)
38
+ language_name = LanguageNames[language_spec]
39
+ raise ArgumentError, "#{language_spec.inspect} does not register" unless @items.key?(language_name)
40
+ item = @items[language_name]
41
+
42
+ if item[:first]
43
+ item[:first].call
44
+ item.delete(:first)
45
+ end
46
+
47
+ item[:object]
48
+ end
49
+
50
+ module Access
51
+
52
+ # @attribute [r] slot
53
+ # @return [Multilang::Slot] slot that is bound to class or module
54
+ def slot
55
+ instance_variable_get(Multilang::SLOT_KEY)
56
+ end
57
+
58
+ # Get registered object in the slot.
59
+ #
60
+ # @param [String, Symbol] language_spec
61
+ # @return [Object] registered object to the slot
62
+ #
63
+ # @see Multilang::Slot::Access#slot
64
+ # @see Multilang::Slot#[]
65
+ def [](language_spec)
66
+ slot[language_spec]
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ module Multilang
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multilang/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'multilang'
8
+ gem.version = Multilang::VERSION
9
+ gem.authors = ['Takahiro Kondo']
10
+ gem.email = ['heartery@gmail.com']
11
+ gem.description = %q{Support multilingualization}
12
+ gem.summary = %q{Foundation for multilingualization}
13
+ gem.homepage = ''
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_development_dependency('rspec')
21
+ gem.add_development_dependency('nokogiri')
22
+ end
@@ -0,0 +1 @@
1
+ module ForTest end
@@ -0,0 +1 @@
1
+ module ForTest2 end
@@ -0,0 +1,20 @@
1
+ require 'multilang/language_names'
2
+
3
+ describe Multilang::LanguageNames, '.#[]' do
4
+ it 'returns normalized language name if the language specifier is string' do
5
+ described_class['english'].should == 'English'
6
+ end
7
+
8
+ it 'returns language name if the language specifier is symbol' do
9
+ described_class[:en ].should == 'English'
10
+ described_class[:eng].should == 'English'
11
+ end
12
+
13
+ it 'raises TypeError if the language specifier is not string and symbol' do
14
+ lambda { described_class[1] }.should raise_error(TypeError, "can't convert Fixnum into String or Symbol")
15
+ end
16
+
17
+ it 'raises ArgumentError if the language specifier does not exist' do
18
+ lambda { described_class['unknown'] }.should raise_error(ArgumentError, '"unknown" language specifier does not defined')
19
+ end
20
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'multilang/slot'
3
+
4
+ describe Multilang::Slot, '#register' do
5
+ before do
6
+ @slot = described_class.new
7
+ end
8
+
9
+ it 'registers the object to the slot' do
10
+ object = Object.new
11
+ @slot.register(:en, object)
12
+ @slot.should be_exists('English')
13
+ @slot['English'].should == object
14
+ end
15
+ end
16
+
17
+ describe Multilang::Slot, '#[]' do
18
+ before do
19
+ @slot = described_class.new
20
+ end
21
+
22
+ it 'returns registered object' do
23
+ object = Object.new
24
+ @slot.register(:en, object)
25
+ @slot['English'].should == object
26
+ end
27
+
28
+ it 'calls the block once if gives a block at construction' do
29
+ count = 0
30
+ @slot.register(:en, Object.new) { count += 1 }
31
+ @slot['English']
32
+ count.should == 1
33
+ @slot['English']
34
+ count.should == 1
35
+ end
36
+
37
+ it 'raises ArgumentError if the language specifier does not register to the slot' do
38
+ lambda { @slot[:en] }.should raise_error(ArgumentError, ':en does not register')
39
+ end
40
+ end
41
+
42
+ describe Multilang::Slot::Access, '#slot' do
43
+ before do
44
+ @slot = slot_stub
45
+ @class = Class.new
46
+ @class.extend(described_class)
47
+ @class.instance_variable_set(Multilang::SLOT_KEY, @slot)
48
+ end
49
+
50
+ it 'returns the value of instance variable named with Multilang::SLOT_KEY' do
51
+ @class.slot.should == @slot
52
+ end
53
+ end
54
+
55
+ describe Multilang::Slot::Access, '#[]' do
56
+ before do
57
+ @slot = slot_stub
58
+ @class = Class.new
59
+ @class.extend(described_class)
60
+ @class.instance_variable_set(Multilang::SLOT_KEY, @slot)
61
+ end
62
+
63
+ it 'calls #[] of the slot with the language specifier' do
64
+ @class.slot.should_receive(:[]).with('English')
65
+ @class['English']
66
+ end
67
+
68
+ it 'returns the return value from #[] of the slot' do
69
+ @class['English'].should == 'item for English'
70
+ end
71
+ end
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+ require 'multilang'
3
+
4
+ describe Multilang, '.#register' do
5
+ before do
6
+ define_const Class, 'SampleClass::English'
7
+ define_const Module, 'SampleModule::English'
8
+ end
9
+
10
+ after do
11
+ remove_const 'SampleClass::English'
12
+ remove_const 'SampleModule::English'
13
+ end
14
+
15
+ it 'extends parent class (parent class of Foo::Bar::Baz is Foo::Bar)' do
16
+ described_class.register SampleClass::English
17
+ SampleClass.should be_respond_to(:slot)
18
+ SampleClass.should be_respond_to(:[])
19
+ end
20
+
21
+ it 'extends parent module' do
22
+ described_class.register SampleModule::English
23
+ SampleModule.should be_respond_to(:slot)
24
+ SampleModule.should be_respond_to(:[])
25
+ end
26
+
27
+ it 'registers to the slot' do
28
+ described_class.register SampleClass::English
29
+ SampleClass.slot.should be_exists('English')
30
+ end
31
+
32
+ it 'raises TypeError if gives non-module' do
33
+ lambda { described_class.register 1 }.should raise_error(TypeError, "can't convert Fixnum into Module")
34
+ lambda { described_class.register 'English' }.should raise_error(TypeError, "can't convert String into Module")
35
+ lambda { described_class.register SampleClass::English }.should_not raise_error(TypeError)
36
+ lambda { described_class.register SampleModule::English }.should_not raise_error(TypeError)
37
+ end
38
+
39
+ it 'raises ArgumentError if gives anonymous class' do
40
+ lambda { described_class.register Class.new }.should raise_error(ArgumentError, "anonymous class can't register")
41
+ lambda { described_class.register SampleClass::English }.should_not raise_error(ArgumentError)
42
+ end
43
+
44
+ it 'raises ArgumentError if gives anonymous module' do
45
+ lambda { described_class.register Module.new }.should raise_error(ArgumentError, "anonymous module can't register")
46
+ lambda { described_class.register SampleModule::English }.should_not raise_error(ArgumentError)
47
+ end
48
+
49
+ it 'raises ArgumentError if gives top-level class' do
50
+ lambda { described_class.register SampleClass }.should raise_error(ArgumentError, "can't permit top-level class")
51
+ end
52
+
53
+ it 'raises ArgumentError if gives top-level module' do
54
+ lambda { described_class.register SampleModule }.should raise_error(ArgumentError, "can't permit top-level module")
55
+ end
56
+
57
+ context 'with :as option' do
58
+ before { define_const Class, 'SampleClass::E' }
59
+ after { remove_const 'SampleClass::E' }
60
+
61
+ it 'registers to the slot with the value of :as option' do
62
+ described_class.register SampleClass::E, :as => 'English'
63
+ SampleClass.slot.should be_exists('English')
64
+ end
65
+ end
66
+
67
+ context 'with :with option' do
68
+ it 'calls Kernel#.require with the value of :with option at initialization' do
69
+ Object.should_not be_const_defined(:ForTest)
70
+ described_class.register SampleClass::English, :with => 'for_test'
71
+ SampleClass['English']
72
+ Object.should be_const_defined(:ForTest)
73
+ end
74
+
75
+ context 'with a block' do
76
+ it 'considers both the value of :with option and the block' do
77
+ Object.should_not be_const_defined(:ForTest2)
78
+ passed = false
79
+
80
+ described_class.register SampleClass::English, :with => 'for_test2' do
81
+ passed = true
82
+ end
83
+
84
+ SampleClass['English']
85
+ Object.should be_const_defined(:ForTest2)
86
+ passed.should be_true
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ describe Multilang, ' including' do
93
+ before do
94
+ define_const Class, 'SampleClass::English'
95
+ end
96
+
97
+ after do
98
+ remove_const 'SampleClass::English'
99
+ end
100
+
101
+ it "calls #{described_class}.#register" do
102
+ described_class.should_receive(:register).with(SampleClass::English)
103
+ mod = described_class
104
+ SampleClass::English.class_eval { include mod }
105
+ end
106
+ end
@@ -0,0 +1,29 @@
1
+ def define_const(type, name)
2
+ klass = name.split('::').inject(Object) do |parent, name|
3
+ if parent.const_defined?(name)
4
+ parent.const_get(name)
5
+ else
6
+ parent.const_set(name, type.new)
7
+ end
8
+ end
9
+ end
10
+
11
+ def remove_const(name)
12
+ names = name.split('::')
13
+
14
+ parents = names[0..-2].inject([Object]) do |parents, name|
15
+ parents << parents.last.const_get(name)
16
+ end
17
+
18
+ names.reverse.each do |name|
19
+ parent = parents.pop
20
+ parent.class_eval { remove_const name }
21
+ break unless parent.constants.empty?
22
+ end
23
+ end
24
+
25
+ def slot_stub
26
+ stub.tap do |s|
27
+ s.stub!(:[]).and_return { |language_spec| "item for #{language_spec}" }
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multilang
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Takahiro Kondo
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: nokogiri
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Support multilingualization
47
+ email:
48
+ - heartery@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - lib/multilang.rb
59
+ - lib/multilang/language_names.rb
60
+ - lib/multilang/language_names.yaml
61
+ - lib/multilang/slot.rb
62
+ - lib/multilang/version.rb
63
+ - multilang.gemspec
64
+ - spec/for_test.rb
65
+ - spec/for_test2.rb
66
+ - spec/multilang/language_names_spec.rb
67
+ - spec/multilang/slot_spec.rb
68
+ - spec/multilang_spec.rb
69
+ - spec/spec_helper.rb
70
+ homepage: ''
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 1.8.24
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Foundation for multilingualization
94
+ test_files:
95
+ - spec/for_test.rb
96
+ - spec/for_test2.rb
97
+ - spec/multilang/language_names_spec.rb
98
+ - spec/multilang/slot_spec.rb
99
+ - spec/multilang_spec.rb
100
+ - spec/spec_helper.rb
101
+ has_rdoc: