globalize2 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.
- data/.gitignore +4 -0
- data/LICENSE +21 -0
- data/README.textile +202 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/generators/db_backend.rb +0 -0
- data/generators/templates/db_backend_migration.rb +25 -0
- data/globalize2.gemspec +100 -0
- data/init.rb +8 -0
- data/lib/globalize/backend/chain.rb +102 -0
- data/lib/globalize/backend/pluralizing.rb +37 -0
- data/lib/globalize/backend/static.rb +61 -0
- data/lib/globalize/i18n/missing_translations_log_handler.rb +41 -0
- data/lib/globalize/i18n/missing_translations_raise_handler.rb +27 -0
- data/lib/globalize/load_path.rb +63 -0
- data/lib/globalize/locale/fallbacks.rb +63 -0
- data/lib/globalize/locale/language_tag.rb +81 -0
- data/lib/globalize/model/active_record.rb +56 -0
- data/lib/globalize/model/active_record/adapter.rb +100 -0
- data/lib/globalize/model/active_record/translated.rb +174 -0
- data/lib/globalize/translation.rb +32 -0
- data/lib/locale/root.yml +3 -0
- data/lib/rails_edge_load_path_patch.rb +40 -0
- data/notes.textile +51 -0
- data/test/all.rb +2 -0
- data/test/backends/chained_test.rb +175 -0
- data/test/backends/pluralizing_test.rb +63 -0
- data/test/backends/static_test.rb +147 -0
- data/test/data/locale/all.yml +2 -0
- data/test/data/locale/de-DE.yml +2 -0
- data/test/data/locale/en-US.yml +2 -0
- data/test/data/locale/en-US/module.yml +2 -0
- data/test/data/locale/fi-FI/module.yml +2 -0
- data/test/data/locale/root.yml +0 -0
- data/test/data/models.rb +40 -0
- data/test/data/no_globalize_schema.rb +11 -0
- data/test/data/schema.rb +39 -0
- data/test/i18n/missing_translations_test.rb +36 -0
- data/test/load_path_test.rb +49 -0
- data/test/locale/fallbacks_test.rb +154 -0
- data/test/locale/language_tag_test.rb +130 -0
- data/test/model/active_record/migration_test.rb +123 -0
- data/test/model/active_record/sti_translated_test.rb +75 -0
- data/test/model/active_record/translated_test.rb +487 -0
- data/test/test_helper.rb +36 -0
- data/test/translation_test.rb +54 -0
- metadata +116 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
|
3
|
+
module Globalize
|
4
|
+
module Model
|
5
|
+
class MigrationError < StandardError; end
|
6
|
+
class MigrationMissingTranslatedField < MigrationError; end
|
7
|
+
class BadMigrationFieldType < MigrationError; end
|
8
|
+
|
9
|
+
module ActiveRecord
|
10
|
+
module Translated
|
11
|
+
def self.included(base)
|
12
|
+
base.extend ActMethods
|
13
|
+
end
|
14
|
+
|
15
|
+
module ActMethods
|
16
|
+
def translates(*attr_names)
|
17
|
+
options = attr_names.extract_options!
|
18
|
+
options[:translated_attributes] = attr_names
|
19
|
+
|
20
|
+
# Only set up once per class
|
21
|
+
unless included_modules.include? InstanceMethods
|
22
|
+
class_inheritable_accessor :globalize_options, :globalize_proxy
|
23
|
+
|
24
|
+
include InstanceMethods
|
25
|
+
extend ClassMethods
|
26
|
+
|
27
|
+
self.globalize_proxy = Globalize::Model::ActiveRecord.create_proxy_class(self)
|
28
|
+
has_many(
|
29
|
+
:globalize_translations,
|
30
|
+
:class_name => globalize_proxy.name,
|
31
|
+
:extend => Extensions,
|
32
|
+
:dependent => :delete_all,
|
33
|
+
:foreign_key => class_name.foreign_key
|
34
|
+
)
|
35
|
+
|
36
|
+
after_save :update_globalize_record
|
37
|
+
end
|
38
|
+
|
39
|
+
self.globalize_options = options
|
40
|
+
Globalize::Model::ActiveRecord.define_accessors(self, attr_names)
|
41
|
+
|
42
|
+
# Import any callbacks that have been defined by extensions to Globalize2
|
43
|
+
# and run them.
|
44
|
+
extend Callbacks
|
45
|
+
Callbacks.instance_methods.each { |callback| send(callback) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def locale=(locale)
|
49
|
+
@@locale = locale
|
50
|
+
end
|
51
|
+
|
52
|
+
def locale
|
53
|
+
(defined?(@@locale) && @@locale) || I18n.locale
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Dummy Callbacks module. Extensions to Globalize2 can insert methods into here
|
58
|
+
# and they'll be called at the end of the translates class method.
|
59
|
+
module Callbacks
|
60
|
+
end
|
61
|
+
|
62
|
+
# Extension to the has_many :globalize_translations association
|
63
|
+
module Extensions
|
64
|
+
def by_locales(locales)
|
65
|
+
find :all, :conditions => { :locale => locales.map(&:to_s) }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
module ClassMethods
|
70
|
+
def method_missing(method, *args)
|
71
|
+
if method.to_s =~ /^find_by_(\w+)$/ && globalize_options[:translated_attributes].include?($1.to_sym)
|
72
|
+
find(:first, :joins => :globalize_translations,
|
73
|
+
:conditions => [ "#{i18n_attr($1)} = ? AND #{i18n_attr('locale')} IN (?)",
|
74
|
+
args.first,I18n.fallbacks[I18n.locale].map{|tag| tag.to_s}])
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_translation_table!(fields)
|
81
|
+
translated_fields = self.globalize_options[:translated_attributes]
|
82
|
+
translated_fields.each do |f|
|
83
|
+
raise MigrationMissingTranslatedField, "Missing translated field #{f}" unless fields[f]
|
84
|
+
end
|
85
|
+
|
86
|
+
fields.each do |name, type|
|
87
|
+
if translated_fields.include?(name) && ![:string, :text].include?(type)
|
88
|
+
raise BadMigrationFieldType, "Bad field type for #{name}, should be :string or :text"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
self.connection.create_table(translation_table_name) do |t|
|
93
|
+
t.references self.table_name.singularize
|
94
|
+
t.string :locale
|
95
|
+
fields.each do |name, type|
|
96
|
+
t.column name, type
|
97
|
+
end
|
98
|
+
t.timestamps
|
99
|
+
end
|
100
|
+
|
101
|
+
self.connection.add_index(translation_table_name, "#{self.table_name.singularize}_id", :name => translation_index_name)
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_translation_table_name(table_name)
|
105
|
+
globalize_proxy.set_table_name(table_name)
|
106
|
+
end
|
107
|
+
|
108
|
+
def translation_table_name
|
109
|
+
globalize_proxy.table_name
|
110
|
+
end
|
111
|
+
|
112
|
+
def translation_index_name
|
113
|
+
# FIXME what's the max size of an index name?
|
114
|
+
index_name = "index_#{translation_table_name}_on_#{self.table_name.singularize}_id"
|
115
|
+
index_name.size < 50 ? index_name : "index_#{Digest::SHA1.hexdigest(index_name)}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def drop_translation_table!
|
119
|
+
self.connection.remove_index(translation_table_name, :name => translation_index_name)
|
120
|
+
self.connection.drop_table translation_table_name
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def i18n_attr(attribute_name)
|
126
|
+
self.base_class.name.underscore.gsub('/', '_') + "_translations.#{attribute_name}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
module InstanceMethods
|
131
|
+
def reload(options = nil)
|
132
|
+
globalize.clear_cache
|
133
|
+
|
134
|
+
# clear all globalized attributes
|
135
|
+
# TODO what's the best way to handle this?
|
136
|
+
self.class.globalize_options[:translated_attributes].each do |attr|
|
137
|
+
@attributes.delete(attr.to_s)
|
138
|
+
end
|
139
|
+
|
140
|
+
super(options)
|
141
|
+
end
|
142
|
+
|
143
|
+
def translated_attributes
|
144
|
+
self.class.globalize_options[:translated_attributes].inject({}) {|h, tf| h[tf] = send(tf); h }
|
145
|
+
end
|
146
|
+
|
147
|
+
def globalize
|
148
|
+
@globalize ||= Adapter.new self
|
149
|
+
end
|
150
|
+
|
151
|
+
def update_globalize_record
|
152
|
+
globalize.update_translations!
|
153
|
+
end
|
154
|
+
|
155
|
+
def translated_locales
|
156
|
+
globalize_translations.scoped(:select => 'DISTINCT locale').map do |translation|
|
157
|
+
translation.locale.to_sym
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def set_translations(options)
|
162
|
+
options.keys.each do |key|
|
163
|
+
translation = globalize_translations.find_by_locale(key.to_s) ||
|
164
|
+
globalize_translations.build(:locale => key.to_s)
|
165
|
+
translation.update_attributes!(options[key])
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
ActiveRecord::Base.send(:include, Globalize::Model::ActiveRecord::Translated)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Globalize
|
2
|
+
# Translations are simple value objects that carry some context information
|
3
|
+
# alongside the actual translation string.
|
4
|
+
|
5
|
+
class Translation < String
|
6
|
+
class Attribute < Translation
|
7
|
+
attr_accessor :requested_locale, :locale, :key
|
8
|
+
end
|
9
|
+
|
10
|
+
class Static < Translation
|
11
|
+
attr_accessor :requested_locale, :locale, :key, :options, :plural_key, :original
|
12
|
+
|
13
|
+
def initialize(string, meta = nil)
|
14
|
+
self.original = string
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(string, meta = nil)
|
20
|
+
set_meta meta
|
21
|
+
super string
|
22
|
+
end
|
23
|
+
|
24
|
+
def fallback?
|
25
|
+
locale.to_sym != requested_locale.to_sym
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_meta(meta)
|
29
|
+
meta.each {|name, value| send :"#{name}=", value } if meta
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/locale/root.yml
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module I18n
|
2
|
+
@@load_path = nil
|
3
|
+
@@default_locale = :'en-US'
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def load_path
|
7
|
+
@@load_path ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_path=(load_path)
|
11
|
+
@@load_path = load_path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
I18n::Backend::Simple.module_eval do
|
17
|
+
def initialized?
|
18
|
+
@initialized ||= false
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def init_translations
|
24
|
+
load_translations(*I18n.load_path)
|
25
|
+
@initialized = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def lookup(locale, key, scope = [])
|
29
|
+
return unless key
|
30
|
+
init_translations unless initialized?
|
31
|
+
keys = I18n.send :normalize_translation_keys, locale, key, scope
|
32
|
+
keys.inject(translations){|result, k| result[k.to_sym] or return nil }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
rails_dir = File.expand_path "#{File.dirname(__FILE__)}/../../../rails/"
|
37
|
+
paths = %w(actionpack/lib/action_view/locale/en-US.yml
|
38
|
+
activerecord/lib/active_record/locale/en-US.yml
|
39
|
+
activesupport/lib/active_support/locale/en-US.yml)
|
40
|
+
paths.each{|path| I18n.load_path << "#{rails_dir}/#{path}" }
|
data/notes.textile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
Stopped DB Backend in the middle, here's where we left off:
|
2
|
+
|
3
|
+
h1. Some Notes
|
4
|
+
|
5
|
+
* Started doing the migration generator in generators/db_backend.rb
|
6
|
+
* Translation keys will be in dotted string format
|
7
|
+
* Question: Do we need a plural_key column, or can we build it in to the dotted key?
|
8
|
+
* We will probably have to code the following methods from scratch, to optimize db calls:
|
9
|
+
** translate
|
10
|
+
** localize
|
11
|
+
** pluralize
|
12
|
+
* We should refactor @interpolation@ code so that it can be included into backend code without inheriting SimpleBackend
|
13
|
+
** Rationale: interpolation is something done entirely after a string is fetched from the data store
|
14
|
+
** Alternately, it could be done from within the I18n module
|
15
|
+
|
16
|
+
h1. Schema
|
17
|
+
|
18
|
+
There will be two db tables.
|
19
|
+
|
20
|
+
# globalize_translations will have: locale, key, translation, created_at, updated_at.
|
21
|
+
# globalize_translations_map will have: key, translation_id.
|
22
|
+
|
23
|
+
globalize_translations_map will let us easily fetch entire sub-trees of namespaces.
|
24
|
+
However, this table may not be necessary, as it may be feasible to just use key LIKE "some.namespace.%".
|
25
|
+
|
26
|
+
h1. Caching
|
27
|
+
|
28
|
+
We'll almost certainly want to implement caching in the backend. Should probably be a customized
|
29
|
+
implementation based on the Rails caching mechanism, to support memcached, etc.
|
30
|
+
|
31
|
+
h1. Queries
|
32
|
+
|
33
|
+
We'll want to pull in lots of stuff at once and return a single translation based on some
|
34
|
+
quick Ruby selection. The query will look something like this:
|
35
|
+
|
36
|
+
<pre>
|
37
|
+
<code>
|
38
|
+
SELECT * FROM globalize_translations
|
39
|
+
WHERE locale in (<fallbacks>) AND
|
40
|
+
key IN (key, default_key)
|
41
|
+
</code>
|
42
|
+
</pre>
|
43
|
+
|
44
|
+
The Ruby code would then pick the first translation that satisfies a fallback, in fallback order.
|
45
|
+
Of course, the records with the supplied key would take precedence of those with the default key.
|
46
|
+
|
47
|
+
h1. Misc
|
48
|
+
|
49
|
+
We should revisit the :zero plural code. On the one hand it's certainly useful for
|
50
|
+
many apps in many languages. On the other hand it's not mentioned in CLDR, and not a real
|
51
|
+
concept in language pluralization. Right now, I'm feeling it's still a good idea to keep it in.
|
data/test/all.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', 'test_helper' )
|
2
|
+
require 'globalize/backend/chain'
|
3
|
+
|
4
|
+
module Globalize
|
5
|
+
module Backend
|
6
|
+
class Dummy
|
7
|
+
def translate(locale, key, options = {})
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ChainedTest < ActiveSupport::TestCase
|
14
|
+
|
15
|
+
test "instantiates a chained backend and sets test as backend" do
|
16
|
+
assert_nothing_raised { I18n.chain_backends }
|
17
|
+
assert_instance_of Globalize::Backend::Chain, I18n.backend
|
18
|
+
end
|
19
|
+
|
20
|
+
test "passes all given arguments to the chained backends #initialize method" do
|
21
|
+
Globalize::Backend::Chain.expects(:new).with(:spec, :simple)
|
22
|
+
I18n.chain_backends :spec, :simple
|
23
|
+
end
|
24
|
+
|
25
|
+
test "passes all given arguments to #add assuming that they are backends" do
|
26
|
+
# no idea how to spec that
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class AddChainedTest < ActiveSupport::TestCase
|
31
|
+
def setup
|
32
|
+
I18n.backend = Globalize::Backend::Chain.new
|
33
|
+
end
|
34
|
+
|
35
|
+
test "accepts an instance of a backend" do
|
36
|
+
assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy.new }
|
37
|
+
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
|
38
|
+
end
|
39
|
+
|
40
|
+
test "accepts a class and instantiates the backend" do
|
41
|
+
assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy }
|
42
|
+
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
|
43
|
+
end
|
44
|
+
|
45
|
+
test "accepts a symbol, constantizes test as a backend class and instantiates the backend" do
|
46
|
+
assert_nothing_raised { I18n.backend.add :dummy }
|
47
|
+
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
|
48
|
+
end
|
49
|
+
|
50
|
+
test "accepts any number of backend instances, classes or symbols" do
|
51
|
+
assert_nothing_raised { I18n.backend.add Globalize::Backend::Dummy.new, Globalize::Backend::Dummy, :dummy }
|
52
|
+
assert_instance_of Globalize::Backend::Dummy, I18n.backend.send(:backends).first
|
53
|
+
assert_equal [ Globalize::Backend::Dummy, Globalize::Backend::Dummy, Globalize::Backend::Dummy ],
|
54
|
+
I18n.backend.send(:backends).map{|backend| backend.class }
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
class TranslateChainedTest < ActiveSupport::TestCase
|
60
|
+
def setup
|
61
|
+
I18n.locale = :en
|
62
|
+
I18n.backend = Globalize::Backend::Chain.new
|
63
|
+
@first_backend = I18n::Backend::Simple.new
|
64
|
+
@last_backend = I18n::Backend::Simple.new
|
65
|
+
I18n.backend.add @first_backend
|
66
|
+
I18n.backend.add @last_backend
|
67
|
+
end
|
68
|
+
|
69
|
+
test "delegates #translate to all backends in the order they were added" do
|
70
|
+
@first_backend.expects(:translate).with(:en, :foo, {})
|
71
|
+
@last_backend.expects(:translate).with(:en, :foo, {})
|
72
|
+
I18n.translate :foo
|
73
|
+
end
|
74
|
+
|
75
|
+
test "returns the result from #translate from the first backend if test's not nil" do
|
76
|
+
@first_backend.store_translations :en, {:foo => 'foo from first backend'}
|
77
|
+
@last_backend.store_translations :en, {:foo => 'foo from last backend'}
|
78
|
+
result = I18n.translate :foo
|
79
|
+
assert_equal 'foo from first backend', result
|
80
|
+
end
|
81
|
+
|
82
|
+
test "returns the result from #translate from the second backend if the first one returned nil" do
|
83
|
+
@first_backend.store_translations :en, {}
|
84
|
+
@last_backend.store_translations :en, {:foo => 'foo from last backend'}
|
85
|
+
result = I18n.translate :foo
|
86
|
+
assert_equal 'foo from last backend', result
|
87
|
+
end
|
88
|
+
|
89
|
+
test "looks up a namespace from all backends and merges them (if a result is a hash and no count option is present)" do
|
90
|
+
@first_backend.store_translations :en, {:foo => {:bar => 'bar from first backend'}}
|
91
|
+
@last_backend.store_translations :en, {:foo => {:baz => 'baz from last backend'}}
|
92
|
+
result = I18n.translate :foo
|
93
|
+
assert_equal( {:bar => 'bar from first backend', :baz => 'baz from last backend'}, result )
|
94
|
+
end
|
95
|
+
|
96
|
+
test "raises a MissingTranslationData exception if no translation was found" do
|
97
|
+
assert_raise( I18n::MissingTranslationData ) { I18n.translate :not_here, :raise => true }
|
98
|
+
end
|
99
|
+
|
100
|
+
test "raises an InvalidLocale exception if the locale is nil" do
|
101
|
+
assert_raise( I18n::InvalidLocale ) { Globalize::Backend::Chain.new.translate nil, :foo }
|
102
|
+
end
|
103
|
+
|
104
|
+
test "bulk translates a number of keys from different backends" do
|
105
|
+
@first_backend.store_translations :en, {:foo => 'foo from first backend'}
|
106
|
+
@last_backend.store_translations :en, {:bar => 'bar from last backend'}
|
107
|
+
result = I18n.translate [:foo, :bar]
|
108
|
+
assert_equal( ['foo from first backend', 'bar from last backend'], result )
|
109
|
+
end
|
110
|
+
|
111
|
+
test "still calls #translate on all the backends" do
|
112
|
+
@last_backend.expects :translate
|
113
|
+
I18n.translate :not_here, :default => 'default'
|
114
|
+
end
|
115
|
+
|
116
|
+
test "returns a given default string when no backend returns a translation" do
|
117
|
+
result = I18n.translate :not_here, :default => 'default'
|
118
|
+
assert_equal 'default', result
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
class CustomLocalizeBackend < I18n::Backend::Simple
|
124
|
+
def localize(locale, object, format = :default)
|
125
|
+
"result from custom localize backend" if locale == 'custom'
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class LocalizeChainedTest < ActiveSupport::TestCase
|
130
|
+
def setup
|
131
|
+
I18n.locale = :en
|
132
|
+
I18n.backend = Globalize::Backend::Chain.new
|
133
|
+
@first_backend = CustomLocalizeBackend.new
|
134
|
+
@last_backend = I18n::Backend::Simple.new
|
135
|
+
I18n.backend.add @first_backend
|
136
|
+
I18n.backend.add @last_backend
|
137
|
+
@time = Time.now
|
138
|
+
end
|
139
|
+
|
140
|
+
test "delegates #localize to all backends in the order they were added" do
|
141
|
+
@first_backend.expects(:localize).with(:en, @time, :default)
|
142
|
+
@last_backend.expects(:localize).with(:en, @time, :default)
|
143
|
+
I18n.localize @time
|
144
|
+
end
|
145
|
+
|
146
|
+
test "returns the result from #localize from the first backend if test's not nil" do
|
147
|
+
@last_backend.expects(:localize).never
|
148
|
+
result = I18n.localize @time, :locale => 'custom'
|
149
|
+
assert_equal 'result from custom localize backend', result
|
150
|
+
end
|
151
|
+
|
152
|
+
test "returns the result from #localize from the second backend if the first one returned nil" do
|
153
|
+
@last_backend.expects(:localize).returns "value from last backend"
|
154
|
+
result = I18n.localize @time
|
155
|
+
assert_equal 'value from last backend', result
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class NamespaceChainedTest < ActiveSupport::TestCase
|
160
|
+
def setup
|
161
|
+
@backend = Globalize::Backend::Chain.new
|
162
|
+
end
|
163
|
+
|
164
|
+
test "returns false if the given result is not a Hash" do
|
165
|
+
assert !@backend.send(:namespace_lookup?, 'foo', {})
|
166
|
+
end
|
167
|
+
|
168
|
+
test "returns false if a count option is present" do
|
169
|
+
assert !@backend.send(:namespace_lookup?, {:foo => 'foo'}, {:count => 1})
|
170
|
+
end
|
171
|
+
|
172
|
+
test "returns true if the given result is a Hash AND no count option is present" do
|
173
|
+
assert @backend.send(:namespace_lookup?, {:foo => 'foo'}, {})
|
174
|
+
end
|
175
|
+
end
|