snusnu-dm-is-localizable 0.0.5

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.
data/TODO ADDED
@@ -0,0 +1,2 @@
1
+ * Add accessors for the localized properties in the localizable resource
2
+ * Think about validation and null constraints
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.5
@@ -0,0 +1,82 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{dm-is-localizable}
5
+ s.version = "0.0.5"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Martin Gamsjaeger (snusnu)"]
9
+ s.date = %q{2009-05-18}
10
+ s.email = %q{gamsnjaga@gmail.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.textile"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "CHANGELOG",
19
+ "LICENSE",
20
+ "README.textile",
21
+ "Rakefile",
22
+ "TODO",
23
+ "VERSION",
24
+ "dm-is-localizable.gemspec",
25
+ "features/dm-is-localizable.feature",
26
+ "features/step_definitions/dm-is-localizable_steps.rb",
27
+ "features/support/env.rb",
28
+ "lib/dm-is-localizable.rb",
29
+ "lib/dm-is-localizable/is/localizable.rb",
30
+ "lib/dm-is-localizable/storage/language.rb",
31
+ "lib/dm-is-localizable/storage/translation.rb",
32
+ "spec/fixtures/item.rb",
33
+ "spec/lib/rspec_tmbundle_support.rb",
34
+ "spec/shared/shared_examples_spec.rb",
35
+ "spec/spec.opts",
36
+ "spec/spec_helper.rb",
37
+ "spec/unit/auto_migrate_spec.rb",
38
+ "spec/unit/class_level_api_spec.rb",
39
+ "spec/unit/instance_level_api_spec.rb",
40
+ "spec/unit/is_localizable_spec.rb",
41
+ "spec/unit/language_spec.rb",
42
+ "spec/unit/translation_spec.rb",
43
+ "tasks/changelog.rb",
44
+ "tasks/whitespace.rb"
45
+ ]
46
+ s.homepage = %q{http://github.com/snusnu/dm-is-localizable}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.3}
50
+ s.summary = %q{Datamapper support for localization of content in multilanguage applications}
51
+ s.test_files = [
52
+ "spec/fixtures/item.rb",
53
+ "spec/lib/rspec_tmbundle_support.rb",
54
+ "spec/shared/shared_examples_spec.rb",
55
+ "spec/spec_helper.rb",
56
+ "spec/unit/auto_migrate_spec.rb",
57
+ "spec/unit/class_level_api_spec.rb",
58
+ "spec/unit/instance_level_api_spec.rb",
59
+ "spec/unit/is_localizable_spec.rb",
60
+ "spec/unit/language_spec.rb",
61
+ "spec/unit/translation_spec.rb"
62
+ ]
63
+
64
+ if s.respond_to? :specification_version then
65
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
66
+ s.specification_version = 3
67
+
68
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
69
+ s.add_runtime_dependency(%q<dm-core>, [">= 0.9.11"])
70
+ s.add_runtime_dependency(%q<dm-is-remixable>, [">= 0.9.11"])
71
+ s.add_runtime_dependency(%q<dm-validations>, [">= 0.9.11"])
72
+ else
73
+ s.add_dependency(%q<dm-core>, [">= 0.9.11"])
74
+ s.add_dependency(%q<dm-is-remixable>, [">= 0.9.11"])
75
+ s.add_dependency(%q<dm-validations>, [">= 0.9.11"])
76
+ end
77
+ else
78
+ s.add_dependency(%q<dm-core>, [">= 0.9.11"])
79
+ s.add_dependency(%q<dm-is-remixable>, [">= 0.9.11"])
80
+ s.add_dependency(%q<dm-validations>, [">= 0.9.11"])
81
+ end
82
+ end
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'dm-is-localizable'
3
+
4
+ require 'spec/expectations'
@@ -0,0 +1,8 @@
1
+ # Require plugin-files
2
+ dir = Pathname(__FILE__).dirname.expand_path / 'dm-is-localizable'
3
+ require dir / 'is' / 'localizable'
4
+ require dir / 'storage' / 'language'
5
+ require dir / 'storage' / 'translation'
6
+
7
+ # Include the plugin in Model
8
+ DataMapper::Model.append_extensions DataMapper::Is::Localizable
@@ -0,0 +1,89 @@
1
+ module DataMapper
2
+ module Is
3
+
4
+ module Localizable
5
+
6
+
7
+ def is_localizable(options = {}, &block)
8
+
9
+ extend ClassMethods
10
+ include InstanceMethods
11
+
12
+ options = {
13
+ :as => nil,
14
+ :class_name => "#{self}Translation"
15
+ }.merge(options)
16
+
17
+ remixer_fk = Extlib::Inflection.foreign_key(self.name).to_sym
18
+ remixer = remixer_fk.to_s.gsub('_id', '').to_sym
19
+ remixee = Extlib::Inflection.tableize(options[:class_name]).to_sym
20
+
21
+ remix n, Translation, :as => options[:as], :class_name => options[:class_name]
22
+
23
+ @translation_class = Extlib::Inflection.constantize(options[:class_name])
24
+ class_inheritable_accessor :translation_class
25
+
26
+ enhance :translation, @translation_class do
27
+
28
+ property remixer_fk, Integer, :nullable => false, :unique_index => :unique_languages
29
+ property :language_id, Integer, :nullable => false, :unique_index => :unique_languages
30
+
31
+ belongs_to remixer
32
+ belongs_to :language
33
+
34
+ class_eval &block
35
+
36
+ validates_is_unique :language_id, :scope => remixer_fk
37
+
38
+ end
39
+
40
+ has n, :languages, :through => remixee
41
+
42
+ self.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
43
+ alias :translations #{remixee}
44
+ EOS
45
+
46
+ end
47
+
48
+ module ClassMethods
49
+
50
+ # list all available languages for the localizable model
51
+ def available_languages
52
+ Language.all :id => translation_class.all.map { |t| t.language_id }.uniq
53
+ end
54
+
55
+ # the number of all available languages for the localizable model
56
+ def nr_of_available_languages
57
+ available_languages.size
58
+ end
59
+
60
+ # checks if all localizable resources are translated in all available languages
61
+ def translations_complete?
62
+ available_languages.size * all.size == translation_class.all.size
63
+ end
64
+
65
+ end
66
+
67
+ module InstanceMethods
68
+
69
+ # list all available languages for this instance
70
+ def available_languages
71
+ Language.all :id => translations.map { |t| t.language_id }.uniq
72
+ end
73
+
74
+ # the number of all available languages for this instance
75
+ def nr_of_available_languages
76
+ available_languages.size
77
+ end
78
+
79
+ # checks if this instance is translated into all available languages for this model
80
+ def translations_complete?
81
+ self.class.nr_of_available_languages == translations.size
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,15 @@
1
+ class Language
2
+
3
+ include DataMapper::Resource
4
+
5
+ # properties
6
+
7
+ property :id, Serial
8
+
9
+ property :code, String, :nullable => false, :unique => true, :unique_index => true
10
+ property :name, String, :nullable => false
11
+
12
+ # locale string like 'en-US'
13
+ validates_format :code, :with => /^[a-z]{2}-[A-Z]{2}$/
14
+
15
+ end
@@ -0,0 +1,18 @@
1
+ module DataMapper
2
+ module Is
3
+ module Localizable
4
+
5
+ module Translation
6
+
7
+ include DataMapper::Resource
8
+
9
+ is :remixable
10
+
11
+ property :id, Serial
12
+ property :language_id, Integer, :nullable => false
13
+
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ class Item
2
+
3
+ include DataMapper::Resource
4
+
5
+ property :id, Serial
6
+
7
+ is :localizable do
8
+ property :name, String
9
+ property :desc, String
10
+ end
11
+
12
+ end
@@ -0,0 +1,35 @@
1
+ # -----------------------------------------------
2
+ # support for nice html output in rspec tmbundle
3
+ # -----------------------------------------------
4
+
5
+ module RSpecTmBundleHelpers
6
+
7
+ class TextmateRspecLogger < DataMapper::Logger
8
+ def prep_msg(message, level)
9
+ "#{super}<br />"
10
+ end
11
+ end
12
+
13
+ def with_dm_logger(level = :debug)
14
+ DataMapper.logger.level = level
15
+ yield
16
+ ensure
17
+ DataMapper.logger.level = :off
18
+ end
19
+
20
+ def print_call_stack(from = 2, to = nil, html = true)
21
+ (from..(to ? to : caller.length)).each do |idx|
22
+ p "[#{idx}]: #{caller[idx]}#{html ? '<br />' : ''}"
23
+ end
24
+ end
25
+
26
+ def puth(html = nil)
27
+ print "#{h(html)}<br />"
28
+ end
29
+
30
+ ESCAPE_TABLE = { '&'=>'&amp;', '<'=>'&lt;', '>'=>'&gt;', '"'=>'&quot;', "'"=>'&#039;', }
31
+ def h(value)
32
+ value.to_s.gsub(/[&<>"]/) {|s| ESCAPE_TABLE[s] }
33
+ end
34
+
35
+ end
@@ -0,0 +1,70 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "all available_languages providers", :shared => true do
4
+
5
+ describe "with no translations" do
6
+
7
+ it "should return 0 languages" do
8
+ @provider.available_languages.size.should == 0
9
+ end
10
+
11
+ end
12
+
13
+ describe "with 1 translation in 1 language" do
14
+
15
+ before :each do
16
+ @l = Language.create :code => 'en-US', :name => 'English'
17
+ @t = ItemTranslation.create :item => @item, :language => @l, :name => "Book", :desc => "Literature"
18
+ end
19
+
20
+ it "should return 1 language" do
21
+ @provider.available_languages.size.should == 1
22
+ end
23
+
24
+ it "should return the right language" do
25
+ @provider.available_languages.first.should == @l
26
+ end
27
+
28
+ end
29
+
30
+ describe "with 2 translations in 1 language" do
31
+
32
+ before :each do
33
+ @l = Language.create :code => 'en-US', :name => 'English'
34
+ @t = ItemTranslation.create :item => @item, :language => @l, :name => "Book", :desc => "Literature"
35
+ @t = ItemTranslation.create :item => @item, :language => @l, :name => "Hook", :desc => "Tool"
36
+ @item.reload
37
+ end
38
+
39
+ it "should return 1 language" do
40
+ @provider.available_languages.size.should == 1
41
+ end
42
+
43
+ it "should return the right language" do
44
+ @provider.available_languages.first.should == @l
45
+ end
46
+
47
+ end
48
+
49
+ describe "with 3 translations in 2 languages" do
50
+
51
+ before :each do
52
+ @l1 = Language.create :code => 'en-US', :name => 'English'
53
+ @l2 = Language.create :code => 'de-AT', :name => 'Deutsch'
54
+ @t = ItemTranslation.create :item => @item, :language => @l1, :name => "Book", :desc => "Literature"
55
+ @t = ItemTranslation.create :item => @item, :language => @l1, :name => "Hook", :desc => "Tool"
56
+ @t = ItemTranslation.create :item => @item, :language => @l2, :name => "Haken", :desc => "Werkzeug"
57
+ end
58
+
59
+ it "should return 2 language" do
60
+ @provider.available_languages.size.should == 2
61
+ end
62
+
63
+ it "should return the right language" do
64
+ @provider.available_languages.first.should == @l1
65
+ @provider.available_languages.last.should == @l2
66
+ end
67
+
68
+ end
69
+
70
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,81 @@
1
+ require 'pathname'
2
+ require 'spec'
3
+
4
+ require 'dm-is-remixable'
5
+ require 'dm-validations'
6
+
7
+ require Pathname(__FILE__).dirname.parent.expand_path + 'lib/dm-is-localizable'
8
+
9
+ ENV["SQLITE3_SPEC_URI"] ||= 'sqlite3::memory:'
10
+ ENV["MYSQL_SPEC_URI"] ||= 'mysql://localhost/dm-accepts_nested_attributes_test'
11
+ ENV["POSTGRES_SPEC_URI"] ||= 'postgres://postgres@localhost/dm-accepts_nested_attributes_test'
12
+
13
+
14
+ def setup_adapter(name, default_uri = nil)
15
+ begin
16
+ DataMapper.setup(name, ENV["#{ENV['ADAPTER'].to_s.upcase}_SPEC_URI"] || default_uri)
17
+ Object.const_set('ADAPTER', ENV['ADAPTER'].to_sym) if name.to_s == ENV['ADAPTER']
18
+ true
19
+ rescue Exception => e
20
+ if name.to_s == ENV['ADAPTER']
21
+ Object.const_set('ADAPTER', nil)
22
+ warn "Could not load do_#{name}: #{e}"
23
+ end
24
+ false
25
+ end
26
+ end
27
+
28
+ # have the loggers handy
29
+ # DataObjects::Logger.new(STDOUT, :debug)
30
+ # DataObjects::Sqlite3.logger = DataObjects::Logger.new(STDOUT, :debug)
31
+
32
+ # -----------------------------------------------
33
+ # support for nice html output in rspec tmbundle
34
+ # -----------------------------------------------
35
+
36
+ USE_TEXTMATE_RSPEC_BUNDLE = true # set to false if not using textmate
37
+
38
+ if USE_TEXTMATE_RSPEC_BUNDLE
39
+
40
+ require Pathname(__FILE__).dirname.expand_path + 'lib/rspec_tmbundle_support'
41
+
42
+ # use the tmbundle logger
43
+ RSpecTmBundleHelpers::TextmateRspecLogger.new(STDOUT, :off)
44
+
45
+
46
+ class Object
47
+ include RSpecTmBundleHelpers
48
+ end
49
+
50
+ end
51
+
52
+ ENV['ADAPTER'] ||= 'sqlite3'
53
+ setup_adapter(:default)
54
+ Dir[Pathname(__FILE__).dirname.to_s + "/fixtures/**/*.rb"].each { |rb| require(rb) }
55
+
56
+
57
+ Spec::Runner.configure do |config|
58
+
59
+ config.before(:all) do
60
+ DataMapper.auto_migrate!
61
+ end
62
+
63
+ config.before(:each) do
64
+ DataMapper.repository(:default) do |r|
65
+ transaction = DataMapper::Transaction.new(r)
66
+ transaction.begin
67
+ r.adapter.push_transaction(transaction)
68
+ end
69
+ end
70
+
71
+ config.after(:each) do
72
+ DataMapper.repository(:default) do |r|
73
+ adapter = r.adapter
74
+ while adapter.current_transaction
75
+ adapter.current_transaction.rollback
76
+ adapter.pop_transaction
77
+ end
78
+ end
79
+ end
80
+
81
+ end