Skip to content

Loading…

Add missing specs #3

Merged
merged 12 commits into from

3 participants

@indrekj

I also made some refactoring and fixed few bugs.

I used i('string') to construct strings in the tests. The i method just froze the string. This was to ensure that original input was never mutated.

@coveralls

Coverage Status

Coverage increased (+0%) when pulling 4b53f72 on indrekj:master into 366533c on mbj:master.

@mbj mbj commented on an outdated diff
lib/inflecto.rb
@@ -23,7 +23,7 @@ module Inflecto
# @api public
#
def self.camelize(input)
- input.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
+ input.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
@mbj Owner
mbj added a note

I'd prefer using the \A anchor for "begin of string matches". @indrekj Not your fault at all. I also missed this when I did my initial pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on an outdated diff
lib/inflecto.rb
@@ -79,7 +79,7 @@ def self.dasherize(input)
# @api public
#
def self.demodulize(input)
- input.to_s.gsub(/^.*::/, '')
+ input.gsub(/^.*::/, '')
@mbj Owner
mbj added a note

Same here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on the diff
lib/inflecto.rb
@@ -247,13 +234,13 @@ def self.singularize(word)
# @api private
#
def self.humanize(input)
- result = input.to_s.dup
-
- inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
@mbj Owner
mbj added a note

Lets use \z anchor for true end of string.

@mbj Owner
mbj added a note

Sorry this was a comment on deleted code ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on an outdated diff
lib/inflecto.rb
@@ -247,13 +234,13 @@ def self.singularize(word)
# @api private
#
def self.humanize(input)
- result = input.to_s.dup
-
- inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
+ result = inflections.humans.apply_to(input)
+ result.gsub!(/_id$/, "")
@mbj Owner
mbj added a note

Also here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on an outdated diff
lib/inflecto/inflections.rb
@@ -220,5 +190,37 @@ def clear
self
end
+ private
+
+ # Add irregular inflection
+ #
+ # @param [String] rule
+ # @param [String] replacement
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def add_irregular(rule, replacement, target)
+ head, *tail = rule.chars.to_a
+ rule(/(#{head})#{tail.join}$/i, '\1' + replacement[1..-1], target)
@mbj Owner
mbj added a note

And here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on an outdated diff
lib/inflecto.rb
((6 lines not shown))
end
+ # Detects uncountable words
@mbj Owner
mbj added a note

I prefer predicates to be documented as:

# Test $subject

This would be in-line with the rest of the code I write.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on an outdated diff
spec/spec_helper.rb
@@ -28,5 +28,22 @@
require file
end
+# Mutant is already using inflecto. If it mutates inflecto methods then our
+# tests start to fail. Instead, we force mutant to use unmutated version of
+# inflecto.
+module Mutant
+ module Inflecto
@mbj Owner
mbj added a note

I like this workaround! Especially as you improved my suggestion for copying the method body into "dynamically copying it". Nice +1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj mbj commented on an outdated diff
spec/unit/inflecto/inflections/irregular_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#irregular' do
+ subject { object.irregular(singular, plural) }
+
+ let(:object) { described_class.new }
+ let(:singular) { 'person' }
+ let(:plural) { 'people' }
+
+ it { should be(object) }
+
+ its(:plurals) { should include([/(p)erson$/i, "\\1eople"]) }
@mbj Owner
mbj added a note

For some kind of "completeness" lets also use strong anchors in specs. \z instead of $.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@mbj
Owner

Lets test for the presence of mutant instead for the environment mutant "currently" runs under. Yeah it is unlikely I'll support < 1.9 but IMHO it is more correct this way. Also lets put the guard around the whole monkeypatch:

if defined?(Mutant)
  module Inflecto
    ...
  end
end

Your version creates the constant Mutant under 1.8 and thus maybe cheats some other code that tests via defined?(Mutant).

@indrekj

Thanks for your feedback. I'll continue with these changes tomorrow.

@coveralls

Coverage Status

Coverage increased (+0%) when pulling 225d054 on indrekj:master into 366533c on mbj:master.

@mbj mbj merged commit 80fbcf6 into mbj:master

1 check passed

Details default The Travis CI build passed
@mbj
Owner

@indrekj Just merged it in. Huge thx from my side!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Showing with 637 additions and 307 deletions.
  1. +0 −4 .travis.yml
  2. +11 −14 Gemfile.devtools
  3. +2 −2 config/flay.yml
  4. +1 −1 config/flog.yml
  5. +72 −57 config/reek.yml
  6. +40 −34 lib/inflecto.rb
  7. +38 −36 lib/inflecto/inflections.rb
  8. +20 −0 lib/inflecto/rules_collection.rb
  9. +0 −9 spec/shared/invertible_method_behaviour.rb
  10. +0 −44 spec/shared/mutator_behavior.rb
  11. +18 −1 spec/spec_helper.rb
  12. +19 −0 spec/unit/inflecto/class_methods/camelize_spec.rb
  13. +19 −0 spec/unit/inflecto/class_methods/classify_spec.rb
  14. +35 −0 spec/unit/inflecto/class_methods/constantize_spec.rb
  15. +7 −0 spec/unit/inflecto/class_methods/dasherize_spec.rb
  16. +11 −0 spec/unit/inflecto/class_methods/demodulize_spec.rb
  17. +11 −0 spec/unit/inflecto/class_methods/foreign_key_spec.rb
  18. +20 −0 spec/unit/inflecto/class_methods/humanize_spec.rb
  19. +21 −0 spec/unit/inflecto/class_methods/inflections_spec.rb
  20. +51 −0 spec/unit/inflecto/class_methods/ordinalize_spec.rb
  21. +1 −1 spec/unit/{inflector → inflecto}/class_methods/pluralize_spec.rb
  22. +2 −2 spec/unit/{inflector → inflecto}/class_methods/singularize_spec.rb
  23. +6 −6 spec/unit/{inflector/class_methods/tabelize_spec.rb → inflecto/class_methods/tableize_spec.rb}
  24. +35 −0 spec/unit/inflecto/class_methods/underscore_spec.rb
  25. +11 −0 spec/unit/inflecto/inflections/class_methods/instance_spec.rb
  26. +21 −0 spec/unit/inflecto/inflections/clear_spec.rb
  27. +22 −0 spec/unit/inflecto/inflections/human_spec.rb
  28. +30 −0 spec/unit/inflecto/inflections/irregular_spec.rb
  29. +38 −0 spec/unit/inflecto/inflections/plural_spec.rb
  30. +38 −0 spec/unit/inflecto/inflections/singular_spec.rb
  31. +20 −0 spec/unit/inflecto/inflections/uncountable_spec.rb
  32. +17 −0 spec/unit/inflecto/rules_collection/apply_to_spec.rb
  33. +0 −21 spec/unit/inflector/class_methods/camelize_spec.rb
  34. +0 −15 spec/unit/inflector/class_methods/classify_spec.rb
  35. +0 −13 spec/unit/inflector/class_methods/demodulize_spec.rb
  36. +0 −13 spec/unit/inflector/class_methods/foreign_key_spec.rb
  37. +0 −13 spec/unit/inflector/class_methods/humanize_spec.rb
  38. +0 −21 spec/unit/inflector/class_methods/underscore_spec.rb
View
4 .travis.yml
@@ -29,7 +29,3 @@ matrix:
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
- rvm: jruby-head
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
- allow_failures:
- # mutant fails
- - rvm: 1.9.3
- - rvm: rbx-19mode
View
25 Gemfile.devtools
@@ -1,9 +1,9 @@
# encoding: utf-8
group :development do
- gem 'rake', '~> 10.0.3'
+ gem 'rake', '~> 10.0.4'
gem 'rspec', '~> 2.13.0'
- gem 'yard', '~> 0.8.5'
+ gem 'yard', '~> 0.8.6.1'
end
group :yard do
@@ -11,17 +11,16 @@ group :yard do
end
group :guard do
- gem 'guard', '~> 1.6.2'
+ gem 'guard', '~> 1.8.0'
gem 'guard-bundler', '~> 1.0.0'
- gem 'guard-rspec', '~> 2.5.1'
+ gem 'guard-rspec', '~> 2.5.4'
# file system change event handling
+ gem 'listen', '~> 1.0.2'
gem 'rb-fchange', '~> 0.0.6', :require => false
gem 'rb-fsevent', '~> 0.9.3', :require => false
gem 'rb-inotify', '~> 0.9.0', :require => false
- gem 'listen', '~> 0.7.3'
-
# notification handling
gem 'libnotify', '~> 0.8.0', :require => false
gem 'rb-notifu', '~> 0.0.4', :require => false
@@ -29,17 +28,15 @@ group :guard do
end
group :metrics do
- gem 'backports', '~> 3.1', '>= 3.1.1'
- gem 'coveralls', '~> 0.6.2'
- gem 'flay', '~> 2.1.0'
- gem 'flog', '~> 3.2.2'
+ gem 'backports', '~> 3.3', '>= 3.3.0'
+ gem 'coveralls', '~> 0.6.6'
+ gem 'flay', '~> 2.2.0'
+ gem 'flog', '~> 4.0.0'
gem 'reek', '~> 1.3.1', :git => 'https://github.com/troessner/reek.git'
- gem 'metric_fu-roodi', '~> 2.2.1'
gem 'simplecov', '~> 0.7.1'
- gem 'yardstick', '~> 0.9.4'
+ gem 'yardstick', '~> 0.9.6'
- platforms :ruby_18, :ruby_19 do
- # this indirectly depends on ffi which does not build on ruby-head
+ platforms :ruby_19 do
gem 'yard-spellcheck', '~> 0.1.5'
end
View
4 config/flay.yml
@@ -1,3 +1,3 @@
---
-threshold: 14
-total_score: 71
+threshold: 12
+total_score: 69
View
2 config/flog.yml
@@ -1,2 +1,2 @@
---
-threshold: 16.7
+threshold: 13
View
129 config/reek.yml
@@ -1,95 +1,110 @@
---
-UncommunicativeParameterName:
- accept: []
- exclude: []
+Attribute:
+ enabled: true
+ exclude:
+ - Inflecto::Inflections
+BooleanParameter:
enabled: true
- reject:
- - !ruby/regexp /^.$/
- - !ruby/regexp /[0-9]$/
- - !ruby/regexp /[A-Z]/
-LargeClass:
- max_methods: 14
exclude: []
+ClassVariable:
enabled: true
- max_instance_variables: 8
-UncommunicativeMethodName:
- accept: []
exclude: []
+ControlParameter:
enabled: true
- reject:
- - !ruby/regexp /^[a-z]$/
- - !ruby/regexp /[0-9]$/
- - !ruby/regexp /[A-Z]/
-LongParameterList:
- max_params: 3
exclude: []
+DataClump:
enabled: true
- overrides: {}
-FeatureEnvy:
exclude:
- - Inflecto::Inflections#irregular
+ - Inflecto::Inflections
+ max_copies: 2
+ min_clump_size: 2
+DuplicateMethodCall:
enabled: true
-ClassVariable:
- exclude: []
+ exclude:
+ - Inflecto#self.camelize
+ max_calls: 1
+ allow_calls: []
+FeatureEnvy:
enabled: true
-BooleanParameter:
exclude: []
- enabled: true
IrresponsibleModule:
- exclude: []
enabled: true
-UncommunicativeModuleName:
- accept: []
exclude: []
+LongParameterList:
enabled: true
- reject:
- - !ruby/regexp /^.$/
- - !ruby/regexp /[0-9]$/
+ exclude:
+ - Inflecto::Inflections#add_irregular
+ - Inflecto::Inflections#rule
+ max_params: 2
+ overrides:
+ initialize:
+ max_params: 3
+LongYieldList:
+ enabled: true
+ exclude: []
+ max_params: 2
NestedIterators:
+ enabled: true
+ exclude: []
+ max_allowed_nesting: 1
ignore_iterators: []
+NilCheck:
+ enabled: true
exclude: []
+RepeatedConditional:
enabled: true
- max_allowed_nesting: 2
-LongMethod:
- max_statements: 8
- exclude:
- - Inflecto::Inflections#irregular
+ exclude: []
+ max_ifs: 1
+TooManyInstanceVariables:
enabled: true
-Duplication:
- allow_calls: []
exclude:
- - Inflecto::Inflections#irregular
+ - Inflecto::Inflections
+ max_instance_variables: 3
+TooManyMethods:
enabled: true
- max_calls: 2
-UtilityFunction:
- max_helper_calls: 1
exclude: []
+ max_methods: 10
+TooManyStatements:
+ enabled: true
+ exclude:
+ - each
+ - Inflecto#self.underscore
+ max_statements: 5
+UncommunicativeMethodName:
enabled: true
-Attribute:
exclude: []
- enabled: false
-UncommunicativeVariableName:
+ reject:
+ - !ruby/regexp /^[a-z]$/
+ - !ruby/regexp /[0-9]$/
+ - !ruby/regexp /[A-Z]/
accept: []
+UncommunicativeModuleName:
+ enabled: true
exclude: []
+ reject:
+ - !ruby/regexp /^.$/
+ - !ruby/regexp /[0-9]$/
+ accept: []
+UncommunicativeParameterName:
enabled: true
+ exclude: []
reject:
- !ruby/regexp /^.$/
- !ruby/regexp /[0-9]$/
- !ruby/regexp /[A-Z]/
-SimulatedPolymorphism:
- exclude: []
- enabled: true
- max_ifs: 2
-DataClump:
- exclude:
- - Inflecto::Inflections
+ accept: []
+UncommunicativeVariableName:
enabled: true
- max_copies: 2
- min_clump_size: 2
-ControlCouple:
exclude: []
+ reject:
+ - !ruby/regexp /^.$/
+ - !ruby/regexp /[0-9]$/
+ - !ruby/regexp /[A-Z]/
+ accept: []
+UnusedParameters:
enabled: true
-LongYieldList:
- max_params: 1
exclude: []
+UtilityFunction:
enabled: true
+ exclude: []
+ max_helper_calls: 0
View
74 lib/inflecto.rb
@@ -23,7 +23,7 @@ module Inflecto
# @api public
#
def self.camelize(input)
- input.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
+ input.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:\A|_)(.)/) { $1.upcase }
end
# Convert input to underscored, lowercase string
@@ -41,11 +41,11 @@ def self.camelize(input)
# @api public
#
def self.underscore(input)
- word = input.to_s.dup
+ word = input.dup
word.gsub!(/::/, '/')
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
- word.tr!("-", "_")
+ word.tr!('-', '_')
word.downcase!
word
end
@@ -79,7 +79,7 @@ def self.dasherize(input)
# @api public
#
def self.demodulize(input)
- input.to_s.gsub(/^.*::/, '')
+ input.gsub(/\A.*::/, '')
end
# Creates a foreign key name
@@ -144,10 +144,12 @@ def self.constantize(input)
# @api private
#
def self.ordinalize(number)
- if (11..13).include?(number.to_i % 100)
+ abs_value = number.abs
+
+ if (11..13).include?(abs_value % 100)
"#{number}th"
else
- case number.to_i % 10
+ case abs_value % 10
when 1; "#{number}st"
when 2; "#{number}nd"
when 3; "#{number}rd"
@@ -169,11 +171,8 @@ def self.ordinalize(number)
# @api public
#
def self.inflections
- if block_given?
- yield Inflections.instance
- else
- Inflections.instance
- end
+ instance = Inflections.instance
+ block_given? ? yield(instance) : instance
end
# Convert input word string to plural
@@ -193,14 +192,8 @@ def self.inflections
# @api public
#
def self.pluralize(word)
- result = word.to_s.dup
-
- if result.empty? || inflections.uncountables.include?(result.downcase)
- result
- else
- inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result
- end
+ return word if uncountable?(word)
+ inflections.plurals.apply_to(word)
end
# Convert word to singular
@@ -220,14 +213,8 @@ def self.pluralize(word)
# @api public
#
def self.singularize(word)
- result = word.to_s.dup
-
- if inflections.uncountables.any? { |inflection| result =~ /\b(#{inflection})\Z/i }
- result
- else
- inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result
- end
+ return word if uncountable?(word)
+ inflections.singulars.apply_to(word)
end
# Humanize string
@@ -247,13 +234,13 @@ def self.singularize(word)
# @api private
#
def self.humanize(input)
- result = input.to_s.dup
-
- inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
@mbj Owner
mbj added a note

Lets use \z anchor for true end of string.

@mbj Owner
mbj added a note

Sorry this was a comment on deleted code ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ result = inflections.humans.apply_to(input)
+ result.gsub!(/_id\z/, "")
+ result.gsub!(/_/, " ")
+ result.capitalize!
+ result
end
-
# Tabelize input string
#
# @param [String] input
@@ -272,7 +259,7 @@ def self.humanize(input)
# @api private
#
def self.tableize(input)
- pluralize(underscore(input).gsub('/','_'))
+ pluralize(underscore(input).gsub('/', '_'))
end
# Classify input
@@ -296,10 +283,29 @@ def self.tableize(input)
#
def self.classify(table_name)
# strip out any leading schema name
- camelize(singularize(table_name.to_s.sub(/.*\./, '')))
+ camelize(singularize(table_name.sub(/.*\./, '')))
end
+ # Test if word is uncountable
+ #
+ # @example
+ #
+ # Inflecto.uncountable?('rice') #=> true
+ # Inflecto.uncountable?('apple') #=> false
+ #
+ # @param [String] word
+ #
+ # @return [Boolean]
+ # true, if word is uncountable
+ #
+ # @api private
+ #
+ def self.uncountable?(word)
+ word.empty? || inflections.uncountables.include?(word.downcase)
+ end
+ private_class_method :uncountable?
end
+require 'inflecto/rules_collection'
require 'inflecto/inflections'
require 'inflecto/defaults'
View
74 lib/inflecto/inflections.rb
@@ -67,7 +67,10 @@ def self.instance
# @api private
#
def initialize
- @plurals, @singulars, @uncountables, @humans = [], [], [], []
+ @plurals = RulesCollection.new
+ @singulars = RulesCollection.new
+ @humans = RulesCollection.new
+ @uncountables = []
end
# Add a new plural role
@@ -84,7 +87,6 @@ def initialize
#
def plural(rule, replacement)
rule(rule, replacement, @plurals)
- @plurals.insert(0, [rule, replacement])
self
end
@@ -105,23 +107,6 @@ def singular(rule, replacement)
self
end
- # Add a new rule
- #
- # @param [String, Regexp] rule
- # @param [String, Regexp] replacement
- # @param [Array] target
- #
- # @return [undefined]
- #
- # @api private
- #
- def rule(rule, replacement, target)
- @uncountables.delete(rule) if rule.is_a?(String)
- @uncountables.delete(replacement)
- target.insert(0, [rule, replacement])
- end
- private :rule
-
# Add a new irregular pluralization
#
# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
@@ -147,21 +132,6 @@ def irregular(singular, plural)
self
end
- # Add irregular inflection
- #
- # @param [String] rule
- # @param [String] replacement
- #
- # @return [undefined]
- #
- # @api private
- #
- def add_irregular(rule, replacement, target)
- head, *tail = rule.chars.to_a
- rule(Regexp.new("(#{head})#{tail.join}$", 'i'), '\1' + replacement[1..-1], target)
- end
- private :add_irregular
-
# Add uncountable words
#
# Uncountable will not be inflected
@@ -178,8 +148,8 @@ def add_irregular(rule, replacement, target)
#
# @api private
#
- def uncountable(words)
- @uncountables.concat(words)
+ def uncountable(*words)
+ @uncountables.concat(words.flatten)
self
end
@@ -220,5 +190,37 @@ def clear
self
end
+ private
+
+ # Add irregular inflection
+ #
+ # @param [String] rule
+ # @param [String] replacement
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def add_irregular(rule, replacement, target)
+ head, *tail = rule.chars.to_a
+ rule(/(#{head})#{tail.join}\z/i, '\1' + replacement[1..-1], target)
+ end
+
+ # Add a new rule
+ #
+ # @param [String, Regexp] rule
+ # @param [String, Regexp] replacement
+ # @param [Array] target
+ #
+ # @return [undefined]
+ #
+ # @api private
+ #
+ def rule(rule, replacement, target)
+ @uncountables.delete(rule)
+ @uncountables.delete(replacement)
+ target.insert(0, [rule, replacement])
+ end
+
end
end
View
20 lib/inflecto/rules_collection.rb
@@ -0,0 +1,20 @@
+module Inflecto
+ # Wraps inflections array
+ #
+ class RulesCollection < Array
+ # Applies first found rule to given word
+ #
+ # @param [String] word
+ #
+ # @return [String]
+ # modified word
+ #
+ # @api private
+ #
+ def apply_to(word)
+ result = word.dup
+ each { |rule, replacement| break if result.gsub!(rule, replacement) }
+ result
+ end
+ end
+end
View
9 spec/shared/invertible_method_behaviour.rb
@@ -1,9 +0,0 @@
-# encoding: utf-8
-
-shared_examples_for 'an invertible method' do
- it_should_behave_like 'an idempotent method'
-
- it 'is invertible' do
- subject.inverse.should equal(object)
- end
-end
View
44 spec/shared/mutator_behavior.rb
@@ -1,44 +0,0 @@
-shared_examples_for 'a mutator' do
- subject { object.each(node) { |item| yields << item } }
-
- let(:yields) { [] }
- let(:object) { described_class }
-
- unless instance_methods.map(&:to_s).include?('node')
- let(:node) { source.to_ast }
- end
-
- it_should_behave_like 'a command method'
-
- context 'with no block' do
- subject { object.each(node) }
-
- it { should be_instance_of(to_enum.class) }
-
- let(:expected_mutations) do
- mutations.map do |mutation|
- if mutation.respond_to?(:to_ast)
- mutation.to_ast.to_sexp
- else
- mutation
- end
- end.to_set
- end
-
- it 'generates the expected mutations' do
- subject = self.subject.map(&:to_sexp).to_set
-
- unless subject == expected_mutations
- message = "Missing mutations: %s\nUnexpected mutations: %s" %
- [expected_mutations - subject, subject - expected_mutations ].map(&:to_a).map(&:inspect)
- fail message
- end
- end
- end
-end
-
-shared_examples_for 'a noop mutator' do
- let(:mutations) { [] }
-
- it_should_behave_like 'a mutator'
-end
View
19 spec/spec_helper.rb
@@ -17,7 +17,7 @@
command_name 'spec:unit'
add_filter 'config'
add_filter 'spec'
- minimum_coverage 88.31
+ minimum_coverage 100
end
end
@@ -28,5 +28,22 @@
require file
end
+# Mutant is already using inflecto. If it mutates inflecto methods then our
+# tests start to fail. Instead, we force mutant to use unmutated version of
+# inflecto.
+if defined?(Mutant)
+ module Mutant
+ module Inflecto
+ ::Inflecto.singleton_methods.each do |name|
+ define_singleton_method name, ::Inflecto.method(name).to_proc
+ end
+ end
+ end
+end
+
RSpec.configure do |config|
+ # Helps to ensure that inflecto does not modify original input
+ def i(object)
+ object.freeze
+ end
end
View
19 spec/unit/inflecto/class_methods/camelize_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe Inflecto, '.camelize' do
+ it 'camelizes data_mapper as DataMapper' do
+ Inflecto.camelize(i('data_mapper')).should == 'DataMapper'
+ end
+
+ it 'camelizes merb as Merb' do
+ Inflecto.camelize(i('merb')).should == 'Merb'
+ end
+
+ it 'camelizes data_mapper/resource as DataMapper::Resource' do
+ Inflecto.camelize(i('data_mapper/resource')).should == 'DataMapper::Resource'
+ end
+
+ it 'camelizes data_mapper/associations/one_to_many as DataMapper::Associations::OneToMany' do
+ Inflecto.camelize(i('data_mapper/associations/one_to_many')).should == 'DataMapper::Associations::OneToMany'
+ end
+end
View
19 spec/unit/inflecto/class_methods/classify_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe Inflecto, '.classify' do
+ it 'classifies data_mapper as DataMapper' do
+ Inflecto.classify(i('data_mapper')).should == 'DataMapper'
+ end
+
+ it 'classifies data.mapper as Mapper' do
+ Inflecto.classify(i('data.mapper')).should == 'Mapper'
+ end
+
+ it 'classifies enlarged_testes as EnlargedTestis' do
+ Inflecto.classify(i('enlarged_testes')).should == 'EnlargedTestis'
+ end
+
+ it 'singularizes string first: classifies data_mappers as egg_and_hams as EggAndHam' do
+ Inflecto.classify(i('egg_and_hams')).should == 'EggAndHam'
+ end
+end
View
35 spec/unit/inflecto/class_methods/constantize_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe Inflecto, '.constantize' do
+ it 'constantizes Module' do
+ Inflecto.constantize(i('Module')).should == Module
+ end
+
+ it 'constantizes ::Module' do
+ Inflecto.constantize(i('::Module')).should == Module
+ end
+
+ it 'constantizes nested constant Inflecto::Inflections' do
+ Inflecto.constantize(i('Inflecto::Inflections')).should == Inflecto::Inflections
+ end
+
+ it 'does not search ancestors' do
+ module Foo
+ class Bar
+ VAL = 10
+ end
+
+ class Baz < Bar; end
+ end
+
+ expect {
+ Inflecto.constantize(i('Foo::Baz::VAL'))
+ }.to raise_error(NameError)
+ end
+
+ it 'raises exception when constant not found' do
+ expect {
+ Inflecto.constantize(i('Qwerty'))
+ }.to raise_error(NameError)
+ end
+end
View
7 spec/unit/inflecto/class_methods/dasherize_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe Inflecto, '.dasherize' do
+ it 'dasherizes data_mapper as data-mapper' do
+ Inflecto.dasherize(i('data_mapper')).should == 'data-mapper'
+ end
+end
View
11 spec/unit/inflecto/class_methods/demodulize_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe Inflecto, '.demodulize' do
+ it 'demodulizes module name: DataMapper::Inflecto => Inflecto' do
+ Inflecto.demodulize(i('DataMapper::Inflecto')).should == 'Inflecto'
+ end
+
+ it 'demodulizes module name: A::B::C::D::E => E' do
+ Inflecto.demodulize(i('A::B::C::D::E')).should == 'E'
+ end
+end
View
11 spec/unit/inflecto/class_methods/foreign_key_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe Inflecto, '.foreign_key' do
+ it 'adds _id to downcased string: Message => message_id' do
+ Inflecto.foreign_key(i('Message')).should == 'message_id'
+ end
+
+ it 'demodulizes string first: Admin::Post => post_id' do
+ Inflecto.foreign_key(i('Admin::Post')).should == 'post_id'
+ end
+end
View
20 spec/unit/inflecto/class_methods/humanize_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Inflecto, '.humanize' do
+ it 'replaces _ with space: humanizes employee_salary as Employee salary' do
+ Inflecto.humanize(i('employee_salary')).should == 'Employee salary'
+ end
+
+ it 'strips _id endings: humanizes author_id as Author' do
+ Inflecto.humanize(i('author_id')).should == 'Author'
+ end
+
+ it 'uses user added rules when possible' do
+ Inflecto.inflections do |inflect|
+ inflect.human('Question', 'Fancy question')
+ inflect.human('questionary', 'Questionnaire')
+ end
+
+ Inflecto.humanize(i('questionary')).should == 'Questionnaire'
+ end
+end
View
21 spec/unit/inflecto/class_methods/inflections_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe Inflecto, '.inflections' do
+ context 'when block given' do
+ it 'yields inflections instance' do
+ yielded = nil
+
+ described_class.inflections do |inflect|
+ yielded = inflect
+ end
+
+ yielded.should eq(Inflecto::Inflections.instance)
+ end
+ end
+
+ context 'when without block' do
+ subject { described_class.inflections }
+
+ it { should be(Inflecto::Inflections.instance) }
+ end
+end
View
51 spec/unit/inflecto/class_methods/ordinalize_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Inflecto, '.ordinalize' do
+ context 'when number ends with digit 1' do
+ it 'adds -th suffix when number ends with 11' do
+ [-1011, -111, -11, 11, 111, 1011].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}th")
+ end
+ end
+
+ it 'adds -st suffix when number does not end with 11' do
+ [-1001, -101, -21, -1, 1, 21, 101, 1001].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}st")
+ end
+ end
+ end
+
+ context 'when number ends with digit 2' do
+ it 'adds -th suffix when number ends with 12' do
+ [-1012, -112, -12, 12, 112, 1012].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}th")
+ end
+ end
+
+ it 'adds -nd suffix when number does not end with 12' do
+ [-1002, -102, -22, -2, 2, 22, 102, 1002].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}nd")
+ end
+ end
+ end
+
+ context 'when number ends with digit 3' do
+ it 'adds -th suffix when number ends with 13' do
+ [-1013, -113, -13, 13, 113, 1013].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}th")
+ end
+ end
+
+ it 'adds -rd suffix when number does not end with 13' do
+ [-1003, -103, -23, -3, 3, 23, 103, 1003].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}rd")
+ end
+ end
+ end
+
+ it 'ordinalizes other numbers with -th suffix' do
+ [-4, 4, 5, 6, 7, 8, 9, 10, 14, 15, 16].each do |number|
+ Inflecto.ordinalize(number).should eq("#{number}th")
+ end
+ end
+end
View
2 ...inflector/class_methods/pluralize_spec.rb → .../inflecto/class_methods/pluralize_spec.rb
@@ -186,7 +186,7 @@
SINGULAR_TO_PLURAL.each do |singular, plural|
it "pluralizes #{singular} => #{plural}" do
- Inflecto.pluralize(singular).should eql(plural)
+ Inflecto.pluralize(i(singular)).should eql(plural)
end
end
View
4 ...flector/class_methods/singularize_spec.rb → ...nflecto/class_methods/singularize_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Inflecto, '#singular' do
+describe Inflecto, '.singularize' do
# ==== exceptional cases
PLURAL_TO_SINGULAR = {
@@ -147,7 +147,7 @@
PLURAL_TO_SINGULAR.each do |plural, singular|
it "should signularize #{plural} => #{singular}" do
- Inflecto.singularize(plural).should eql(singular)
+ Inflecto.singularize(i(plural)).should eql(singular)
end
end
end
View
12 .../inflector/class_methods/tabelize_spec.rb → ...t/inflecto/class_methods/tableize_spec.rb
@@ -2,26 +2,26 @@
describe Inflecto, '.tableize' do
it 'pluralizes last word in snake_case strings: fancy_category => fancy_categories' do
- Inflecto.tableize('fancy_category').should == 'fancy_categories'
+ Inflecto.tableize(i('fancy_category')).should == 'fancy_categories'
end
it 'underscores CamelCase strings before pluralization: enlarged_testis => enlarged_testes' do
- Inflecto.tableize('enlarged_testis').should == 'enlarged_testes'
+ Inflecto.tableize(i('enlarged_testis')).should == 'enlarged_testes'
end
it 'underscores CamelCase strings before pluralization: FancyCategory => fancy_categories' do
- Inflecto.tableize('FancyCategory').should == 'fancy_categories'
+ Inflecto.tableize(i('FancyCategory')).should == 'fancy_categories'
end
it 'underscores CamelCase strings before pluralization: EnlargedTestis => enlarged_testes' do
- Inflecto.tableize('EnlargedTestis').should == 'enlarged_testes'
+ Inflecto.tableize(i('EnlargedTestis')).should == 'enlarged_testes'
end
it 'replaces :: with underscores: Fancy::Category => fancy_categories' do
- Inflecto.tableize('Fancy::Category').should == 'fancy_categories'
+ Inflecto.tableize(i('Fancy::Category')).should == 'fancy_categories'
end
it 'underscores CamelCase strings before pluralization: Enlarged::Testis => enlarged_testes' do
- Inflecto.tableize('Enlarged::Testis').should == 'enlarged_testes'
+ Inflecto.tableize(i('Enlarged::Testis')).should == 'enlarged_testes'
end
end
View
35 spec/unit/inflecto/class_methods/underscore_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+
+describe Inflecto, '.underscore' do
+ it 'underscores DataMapper as data_mapper' do
+ Inflecto.underscore(i('DataMapper')).should == 'data_mapper'
+ end
+
+ it 'underscores Merb as merb' do
+ Inflecto.underscore(i('Merb')).should == 'merb'
+ end
+
+ it 'underscores DataMapper::Resource as data_mapper/resource' do
+ Inflecto.underscore(i('DataMapper::Resource')).should == 'data_mapper/resource'
+ end
+
+ it 'underscores Merb::BootLoader::Rackup as merb/boot_loader/rackup' do
+ Inflecto.underscore(i('Merb::BootLoader::Rackup')).should == 'merb/boot_loader/rackup'
+ end
+
+ it 'underscores data-mapper as data_mapper' do
+ Inflecto.underscore(i('data-mapper')).should == 'data_mapper'
+ end
+
+ it 'underscores CLI as cli' do
+ Inflecto.underscore(i('CLI')).should == 'cli'
+ end
+
+ it 'underscores castleKing as castle_king' do
+ Inflecto.underscore(i('castleKing')).should == 'castle_king'
+ end
+
+ it 'underscores CLIRunner as cli_runner' do
+ Inflecto.underscore(i('CLIRunner')).should == 'cli_runner'
+ end
+end
View
11 spec/unit/inflecto/inflections/class_methods/instance_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '.instance' do
+ subject { described_class.instance }
+
+ it { should be_instance_of(described_class) }
+
+ it 'returns always same instance' do
+ subject.should equal(described_class.instance)
+ end
+end
View
21 spec/unit/inflecto/inflections/clear_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#clear' do
+ subject { object.clear }
+
+ let(:object) { described_class.new }
+
+ before do
+ object.uncountable('apple')
+ object.plural('people', 'person')
+ object.singular('apple', 'apples')
+ object.human('person_name', 'Name')
+ end
+
+ it { should be(object) }
+
+ its(:plurals) { should be_empty }
+ its(:singulars) { should be_empty }
+ its(:uncountables) { should be_empty }
+ its(:humans) { should be_empty }
+end
View
22 spec/unit/inflecto/inflections/human_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#human' do
+ subject { object.human(rule, replacement) }
+
+ let(:object) { described_class.new }
+ let(:rule) { mock(:rule) }
+ let(:replacement) { mock(:replacement) }
+
+ it { should be(object) }
+
+ its(:humans) { should eq([[rule, replacement]]) }
+
+ it 'adds rule as a first item' do
+ subject
+ object.human(mock, mock)
+
+ humans = object.humans
+ humans.size.should be(2)
+ humans.last.should eq([rule, replacement])
+ end
+end
View
30 spec/unit/inflecto/inflections/irregular_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#irregular' do
+ subject { object.irregular(singular, plural) }
+
+ let(:object) { described_class.new }
+ let(:singular) { 'person' }
+ let(:plural) { 'people' }
+
+ it { should be(object) }
+
+ its(:plurals) { should include([/(p)erson\z/i, "\\1eople"]) }
+ its(:singulars) { should include([/(p)eople\z/i, "\\1erson"]) }
+
+ context 'when singular form is in uncountables' do
+ before { object.uncountable('person') }
+
+ it 'removes it from uncountables' do
+ subject.uncountables.should_not include('person')
+ end
+ end
+
+ context 'when plural form is in uncountables' do
+ before { object.uncountable('people') }
+
+ it 'removes it from uncountables' do
+ subject.uncountables.should_not include('people')
+ end
+ end
+end
View
38 spec/unit/inflecto/inflections/plural_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#plural' do
+ subject { object.plural(rule, replacement) }
+
+ let(:object) { described_class.new }
+ let(:rule) { mock(:rule) }
+ let(:replacement) { mock(:replacement) }
+
+ it { should be(object) }
+
+ its(:plurals) { should eq([[rule, replacement]]) }
+
+ it 'adds rule as a first item' do
+ subject
+ object.plural(mock, mock)
+
+ plurals = object.plurals
+ plurals.size.should be(2)
+ plurals.last.should eq([rule, replacement])
+ end
+
+ context 'when rule is in the uncountables' do
+ before { object.uncountable(rule) }
+
+ it 'removes it from uncountables' do
+ subject.uncountables.should eq([])
+ end
+ end
+
+ context 'when replacement is in the uncountables' do
+ before { object.uncountable(replacement) }
+
+ it 'removes it from uncountables' do
+ subject.uncountables.should eq([])
+ end
+ end
+end
View
38 spec/unit/inflecto/inflections/singular_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#singular' do
+ subject { object.singular(rule, replacement) }
+
+ let(:object) { described_class.new }
+ let(:rule) { mock(:rule) }
+ let(:replacement) { mock(:replacement) }
+
+ it { should be(object) }
+
+ its(:singulars) { should eq([[rule, replacement]]) }
+
+ it 'adds rule as a first item' do
+ subject
+ object.singular(mock, mock)
+
+ singulars = object.singulars
+ singulars.size.should be(2)
+ singulars.last.should eq([rule, replacement])
+ end
+
+ context 'when rule is in the uncountables' do
+ before { object.uncountable(rule) }
+
+ it 'removes it from uncountables' do
+ subject.uncountables.should eq([])
+ end
+ end
+
+ context 'when replacement is in the uncountables' do
+ before { object.uncountable(replacement) }
+
+ it 'removes it from uncountables' do
+ subject.uncountables.should eq([])
+ end
+ end
+end
View
20 spec/unit/inflecto/inflections/uncountable_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe Inflecto::Inflections, '#uncountable' do
+ let(:object) { described_class.new }
+
+ context 'when word given' do
+ subject { object.uncountable('water') }
+ its(:uncountables) { should eq(['water']) }
+ end
+
+ context 'when array of words given' do
+ subject { object.uncountable(['water', 'sugar']) }
+ its(:uncountables) { should eq(%w[water sugar]) }
+ end
+
+ context 'when multiple words given' do
+ subject { object.uncountable('water', 'sugar') }
+ its(:uncountables) { should eq(%w[water sugar]) }
+ end
+end
View
17 spec/unit/inflecto/rules_collection/apply_to_spec.rb
@@ -0,0 +1,17 @@
+require 'spec_helper'
+
+describe Inflecto::RulesCollection, '#apply_to' do
+ subject { described_class.new(rules).apply_to(input) }
+
+ let(:rules) do
+ [
+ ['question', 'questions'],
+ ['quest', 'quests']
+ ]
+ end
+ let(:input) { 'question' }
+
+ it { should eq('questions') }
+
+ it { should_not equal(input) }
+end
View
21 spec/unit/inflector/class_methods/camelize_spec.rb
@@ -1,21 +0,0 @@
-require 'spec_helper'
-
-describe Inflecto do
- describe '.camelize' do
- it 'camelizes data_mapper as DataMapper' do
- Inflecto.camelize('data_mapper').should == 'DataMapper'
- end
-
- it 'camelizes merb as Merb' do
- Inflecto.camelize('merb').should == 'Merb'
- end
-
- it 'camelizes data_mapper/resource as DataMapper::Resource' do
- Inflecto.camelize('data_mapper/resource').should == 'DataMapper::Resource'
- end
-
- it 'camelizes data_mapper/associations/one_to_many as DataMapper::Associations::OneToMany' do
- Inflecto.camelize('data_mapper/associations/one_to_many').should == 'DataMapper::Associations::OneToMany'
- end
- end
-end
View
15 spec/unit/inflector/class_methods/classify_spec.rb
@@ -1,15 +0,0 @@
-require 'spec_helper'
-
-describe Inflecto, '.classify' do
- it 'classifies data_mapper as DataMapper' do
- Inflecto.classify('data_mapper').should == 'DataMapper'
- end
-
- it 'classifies enlarged_testes as EnlargedTestis' do
- Inflecto.classify('enlarged_testes').should == 'EnlargedTestis'
- end
-
- it 'singularizes string first: classifies data_mappers as egg_and_hams as EggAndHam' do
- Inflecto.classify('egg_and_hams').should == 'EggAndHam'
- end
-end
View
13 spec/unit/inflector/class_methods/demodulize_spec.rb
@@ -1,13 +0,0 @@
-require 'spec_helper'
-
-describe Inflecto do
- describe '.demodulize' do
- it 'demodulizes module name: DataMapper::Inflecto => Inflecto' do
- Inflecto.demodulize('DataMapper::Inflecto').should == 'Inflecto'
- end
-
- it 'demodulizes module name: A::B::C::D::E => E' do
- Inflecto.demodulize('A::B::C::D::E').should == 'E'
- end
- end
-end
View
13 spec/unit/inflector/class_methods/foreign_key_spec.rb
@@ -1,13 +0,0 @@
-require 'spec_helper'
-
-describe Inflecto do
- describe '.foreign_key' do
- it 'adds _id to downcased string: Message => message_id' do
- Inflecto.foreign_key('Message').should == 'message_id'
- end
-
- it 'demodulizes string first: Admin::Post => post_id' do
- Inflecto.foreign_key('Admin::Post').should == 'post_id'
- end
- end
-end
View
13 spec/unit/inflector/class_methods/humanize_spec.rb
@@ -1,13 +0,0 @@
-require 'spec_helper'
-
-describe Inflecto do
- describe '.humanize' do
- it 'replaces _ with space: humanizes employee_salary as Employee salary' do
- Inflecto.humanize('employee_salary').should == 'Employee salary'
- end
-
- it 'strips _id endings: humanizes author_id as Author' do
- Inflecto.humanize('author_id').should == 'Author'
- end
- end
-end
View
21 spec/unit/inflector/class_methods/underscore_spec.rb
@@ -1,21 +0,0 @@
-require 'spec_helper'
-
-describe Inflecto do
- describe '.underscore' do
- it 'underscores DataMapper as data_mapper' do
- Inflecto.underscore('DataMapper').should == 'data_mapper'
- end
-
- it 'underscores Merb as merb' do
- Inflecto.underscore('Merb').should == 'merb'
- end
-
- it 'underscores DataMapper::Resource as data_mapper/resource' do
- Inflecto.underscore('DataMapper::Resource').should == 'data_mapper/resource'
- end
-
- it 'underscores Merb::BootLoader::Rackup as merb/boot_loader/rackup' do
- Inflecto.underscore('Merb::BootLoader::Rackup').should == 'merb/boot_loader/rackup'
- end
- end
-end
Something went wrong with that request. Please try again.