inflecto-0.0.2/0000755000175000017500000000000012310435424012320 5ustar jonasjonasinflecto-0.0.2/.travis.yml0000644000175000017500000000060712310435424014434 0ustar jonasjonaslanguage: ruby bundler_args: --without guard metrics script: "bundle exec rake spec" rvm: - 1.8.7 - ree - 1.9.2 - 1.9.3 - 2.0.0 - jruby-18mode - jruby-19mode - rbx-18mode - rbx-19mode - ruby-head matrix: allow_failures: - rvm: ruby-head - rvm: rbx-18mode - rvm: rbx-19mode - rvm: jruby-head - rvm: 2.0.0 notifications: email: - mbj@seonic.net inflecto-0.0.2/Changelog.md0000644000175000017500000000014512310435424014531 0ustar jonasjonas# v0.0.2 2013-01-20 [change] Do not depend on backports # v0.0.1 2012-12-12 First public release! inflecto-0.0.2/spec/0000755000175000017500000000000012310435424013252 5ustar jonasjonasinflecto-0.0.2/spec/shared/0000755000175000017500000000000012310435424014520 5ustar jonasjonasinflecto-0.0.2/spec/shared/mutator_behavior.rb0000644000175000017500000000213612310435424020421 0ustar jonasjonasshared_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 inflecto-0.0.2/spec/shared/invertible_method_behaviour.rb0000644000175000017500000000027412310435424022617 0ustar jonasjonas# 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 inflecto-0.0.2/spec/shared/command_method_behavior.rb0000644000175000017500000000016712310435424021706 0ustar jonasjonas# encoding: utf-8 shared_examples_for 'a command method' do it 'returns self' do should equal(object) end end inflecto-0.0.2/spec/shared/hash_method_behavior.rb0000644000175000017500000000050612310435424021210 0ustar jonasjonas# encoding: utf-8 shared_examples_for 'a hash method' do it_should_behave_like 'an idempotent method' specification = proc do should be_instance_of(Fixnum) end it 'is a fixnum' do instance_eval(&specification) end it 'memoizes the hash code' do subject.should eql(object.memoized(:hash)) end end inflecto-0.0.2/spec/shared/each_method_behaviour.rb0000644000175000017500000000046712310435424021360 0ustar jonasjonas# encoding: utf-8 shared_examples_for 'an #each method' do it_should_behave_like 'a command method' context 'with no block' do subject { object.each } it { should be_instance_of(to_enum.class) } it 'yields the expected values' do subject.to_a.should eql(object.to_a) end end end inflecto-0.0.2/spec/shared/idempotent_method_behavior.rb0000644000175000017500000000023012310435424022427 0ustar jonasjonas# encoding: utf-8 shared_examples_for 'an idempotent method' do it 'is idempotent' do should equal(instance_eval(&self.class.subject)) end end inflecto-0.0.2/spec/integration/0000755000175000017500000000000012310435424015575 5ustar jonasjonasinflecto-0.0.2/spec/integration/inflector_spec.rb0000644000175000017500000000027412310435424021124 0ustar jonasjonasrequire 'spec_helper' describe Inflecto, 'underscore' do specify 'allows to create snake_case from CamelCase' do Inflecto.underscore('CamelCase').should eql('camel_case') end end inflecto-0.0.2/spec/unit/0000755000175000017500000000000012310435424014231 5ustar jonasjonasinflecto-0.0.2/spec/unit/inflector/0000755000175000017500000000000012310435424016216 5ustar jonasjonasinflecto-0.0.2/spec/unit/inflector/class_methods/0000755000175000017500000000000012310435424021046 5ustar jonasjonasinflecto-0.0.2/spec/unit/inflector/class_methods/singularize_spec.rb0000644000175000017500000000732612310435424024751 0ustar jonasjonasrequire 'spec_helper' describe Inflecto, '#singular' do # ==== exceptional cases PLURAL_TO_SINGULAR = { 'equipment' => 'equipment', 'mysql' => 'mysql', 'information' => 'information', 'money' => 'money', 'species' => 'species', 'series' => 'series', 'fish' => 'fish', 'sheep' => 'sheep', 'news' => 'news', 'rain' => 'rain', 'milk' => 'milk', 'moose' => 'moose', 'hovercraft' => 'hovercraft', 'matrices' => 'matrix', 'lives' => 'life', 'wives' => 'wife', 'aliases' => 'alias', 'statuses' => 'status', 'axes' => 'axis', 'crises' => 'crisis', 'testes' => 'testis', 'children' => 'child', 'people' => 'person', 'potatoes' => 'potato', 'tomatoes' => 'tomato', 'buffaloes' => 'buffalo', 'torpedoes' => 'torpedo', 'quizzes' => 'quiz', 'vertices' => 'vertex', 'indices' => 'index', 'indexes' => 'index', 'oxen' => 'ox', 'mice' => 'mouse', 'lice' => 'louse', 'theses' => 'thesis', 'analyses' => 'analysis', 'octopi' => 'octopus', 'grass' => 'grass', # ==== bugs, typos and reported issues # ==== rules 'forums' => 'forum', 'hives' => 'hive', 'athletes' => 'athlete', 'dwarves' => 'dwarf', 'heroes' => 'hero', 'zeroes' => 'zero', 'men' => 'man', 'women' => 'woman', 'sportsmen' => 'sportsman', 'branches' => 'branch', 'crunches' => 'crunch', 'trashes' => 'trash', 'mashes' => 'mash', 'crosses' => 'cross', 'errata' => 'erratum', # FIXME: add -ia => -ium cases # FIXME: add -ra => -rum cases 'rays' => 'ray', 'sprays' => 'spray', # Merriam-Webster dictionary says # preys is correct, too. 'preys' => 'prey', 'toys' => 'toy', 'joys' => 'joy', 'buys' => 'buy', 'guys' => 'guy', 'cries' => 'cry', 'flies' => 'fly', 'foxes' => 'fox', 'elves' => 'elf', 'shelves' => 'shelf', 'cats' => 'cat', 'rats' => 'rat', 'roses' => 'rose', 'projects' => 'project', 'posts' => 'post', 'articles' => 'article', 'locations' => 'location', 'friends' => 'friend', 'links' => 'link', 'urls' => 'url', 'accounts' => 'account', 'servers' => 'server', 'fruits' => 'fruit', 'maps' => 'map', 'incomes' => 'income', 'pings' => 'ping', 'events' => 'event', 'proofs' => 'proof', 'typos' => 'typo', 'attachments' => 'attachment', 'downloads' => 'download', 'assets' => 'asset', 'jobs' => 'job', 'cities' => 'city', 'packages' => 'package', 'commits' => 'commit', 'versions' => 'version', 'documents' => 'document', 'editions' => 'edition', 'movies' => 'movie', 'songs' => 'song', 'invoices' => 'invoice', 'products' => 'product', 'books' => 'book', 'tickets' => 'ticket', 'games' => 'game', 'tournaments' => 'tournament', 'prizes' => 'prize', 'prices' => 'price', 'installations' => 'installation', 'dates' => 'date', 'schedules' => 'schedule', 'arenas' => 'arena', 'spams' => 'spam', 'rice' => 'rice' } # Missing exceptions or missing rules? PENDING = { 'cacti' => 'cactus', 'cactuses' => 'cactus', 'thesauri' => 'thesaurus', 'geese' => 'goose', 'phenomena' => 'phenomenon', 'Swiss' => 'Swiss', 'drives' => 'drive', 'pluses' => 'plus', 'thieves' => 'thief', 'criteria' => 'criterion', 'postgres' => 'postgres' } PENDING.each do |plural, singular| pending "missing rule or exception for #{plural} => #{singular}" end PLURAL_TO_SINGULAR.each do |plural, singular| it "should signularize #{plural} => #{singular}" do Inflecto.singularize(plural).should eql(singular) end end end inflecto-0.0.2/spec/unit/inflector/class_methods/humanize_spec.rb0000644000175000017500000000055712310435424024234 0ustar jonasjonasrequire '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 inflecto-0.0.2/spec/unit/inflector/class_methods/tabelize_spec.rb0000644000175000017500000000205412310435424024205 0ustar jonasjonasrequire 'spec_helper' describe Inflecto, '.tableize' do it 'pluralizes last word in snake_case strings: fancy_category => fancy_categories' do Inflecto.tableize('fancy_category').should == 'fancy_categories' end it 'underscores CamelCase strings before pluralization: enlarged_testis => enlarged_testes' do Inflecto.tableize('enlarged_testis').should == 'enlarged_testes' end it 'underscores CamelCase strings before pluralization: FancyCategory => fancy_categories' do Inflecto.tableize('FancyCategory').should == 'fancy_categories' end it 'underscores CamelCase strings before pluralization: EnlargedTestis => enlarged_testes' do Inflecto.tableize('EnlargedTestis').should == 'enlarged_testes' end it 'replaces :: with underscores: Fancy::Category => fancy_categories' do Inflecto.tableize('Fancy::Category').should == 'fancy_categories' end it 'underscores CamelCase strings before pluralization: Enlarged::Testis => enlarged_testes' do Inflecto.tableize('Enlarged::Testis').should == 'enlarged_testes' end end inflecto-0.0.2/spec/unit/inflector/class_methods/pluralize_spec.rb0000644000175000017500000001352612310435424024423 0ustar jonasjonasrequire 'spec_helper' describe Inflecto, '.pluralize' do SINGULAR_TO_PLURAL = { 'equipment' => 'equipment', 'information' => 'information', 'money' => 'money', 'species' => 'species', 'series' => 'series', 'fish' => 'fish', 'sheep' => 'sheep', 'news' => 'news', 'matrix' => 'matrices', 'life' => 'lives', 'wife' => 'wives', 'alias' => 'aliases', 'status' => 'statuses', 'axis' => 'axes', 'crisis' => 'crises', 'testis' => 'testes', 'child' => 'children', 'person' => 'people', 'tomato' => 'tomatoes', 'buffalo' => 'buffaloes', 'quiz' => 'quizzes', 'vertex' => 'vertices', 'index' => 'indices', 'ox' => 'oxen', 'mouse' => 'mice', 'louse' => 'lice', 'thesis' => 'theses', 'analysis' => 'analyses', 'octopus' => 'octopi', 'grass' => 'grass', 'drive' => 'drives', # ==== bugs, typos and reported issues # ==== rules and most common cases 'forum' => 'forums', 'hive' => 'hives', 'athlete' => 'athletes', 'dwarf' => 'dwarves', 'man' => 'men', 'woman' => 'women', 'sportsman' => 'sportsmen', 'branch' => 'branches', 'crunch' => 'crunches', 'trash' => 'trashes', 'mash' => 'mashes', 'cross' => 'crosses', 'erratum' => 'errata', # FIXME: add -ia => -ium cases # FIXME: add -ra => -rum cases 'ray' => 'rays', 'spray' => 'sprays', # Merriam-Webster dictionary says # preys is correct, too. 'prey' => 'preys', 'toy' => 'toys', 'joy' => 'joys', 'buy' => 'buys', 'guy' => 'guys', 'cry' => 'cries', 'fly' => 'flies', 'fox' => 'foxes', 'elf' => 'elves', 'shelf' => 'shelves', 'cat' => 'cats', 'rat' => 'rats', 'rose' => 'roses', 'project' => 'projects', 'post' => 'posts', 'article' => 'articles', 'location' => 'locations', 'friend' => 'friends', 'link' => 'links', 'url' => 'urls', 'account' => 'accounts', 'server' => 'servers', 'fruit' => 'fruits', 'map' => 'maps', 'income' => 'incomes', 'ping' => 'pings', 'event' => 'events', 'proof' => 'proofs', 'typo' => 'typos', 'attachment' => 'attachments', 'download' => 'downloads', 'asset' => 'assets', 'job' => 'jobs', 'city' => 'cities', 'package' => 'packages', 'commit' => 'commits', 'version' => 'versions', 'document' => 'documents', 'edition' => 'editions', 'movie' => 'movies', 'song' => 'songs', 'invoice' => 'invoices', 'product' => 'products', 'book' => 'books', 'ticket' => 'tickets', 'game' => 'games', 'tournament' => 'tournaments', 'prize' => 'prizes', 'price' => 'prices', 'installation' => 'installations', 'date' => 'dates', 'schedule' => 'schedules', 'arena' => 'arenas', 'spam' => 'spams', 'bus' => 'buses', 'rice' => 'rice', # Some specs from Rails 'search' => 'searches', 'switch' => 'switches', 'fix' => 'fixes', 'box' => 'boxes', 'process' => 'processes', 'address' => 'addresses', 'case' => 'cases', 'stack' => 'stacks', 'wish' => 'wishes', 'category' => 'categories', 'query' => 'queries', 'ability' => 'abilities', 'agency' => 'agencies', 'archive' => 'archives', 'safe' => 'saves', 'half' => 'halves', 'move' => 'moves', 'salesperson' => 'salespeople', 'spokesman' => 'spokesmen', 'basis' => 'bases', 'diagnosis' => 'diagnoses', 'diagnosis_a' => 'diagnosis_as', 'datum' => 'data', 'medium' => 'media', 'node_child' => 'node_children', 'experience' => 'experiences', 'day' => 'days', 'comment' => 'comments', 'foobar' => 'foobars', 'newsletter' => 'newsletters', 'old_news' => 'old_news', 'perspective' => 'perspectives', 'photo' => 'photos', 'status_code' => 'status_codes', 'house' => 'houses', 'portfolio' => 'portfolios', 'matrix_fu' => 'matrix_fus', 'axis' => 'axes', 'shoe' => 'shoes', 'horse' => 'horses', 'edge' => 'edges', } # Missing rule or exception? PENDING = { 'cow' => 'cows', # 'kine' is archaic and nobody uses it 'virus' => 'viruses', 'torpedo' => 'torpedoes', 'Swiss' => 'Swiss', 'goose' => 'geese', 'milk' => 'milk', 'plus' => 'plusses', 'thesaurus' => 'thesauri', 'thief' => 'thieves', 'hovercraft' => 'hovercraft', 'zero' => 'zeroes', 'rain' => 'rain', 'cactus' => 'cacti', 'moose' => 'moose', 'criterion' => 'criteria', 'potato' => 'potatoes', 'phenomenon' => 'phenomena', 'hero' => 'heroes', } PENDING.each do |singular, plural| pending "missing exception or rule for #{singular} => #{plural}" end SINGULAR_TO_PLURAL.each do |singular, plural| it "pluralizes #{singular} => #{plural}" do Inflecto.pluralize(singular).should eql(plural) end end end inflecto-0.0.2/spec/unit/inflector/class_methods/underscore_spec.rb0000644000175000017500000000117512310435424024562 0ustar jonasjonasrequire '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 inflecto-0.0.2/spec/unit/inflector/class_methods/foreign_key_spec.rb0000644000175000017500000000053412310435424024710 0ustar jonasjonasrequire '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 inflecto-0.0.2/spec/unit/inflector/class_methods/demodulize_spec.rb0000644000175000017500000000054112310435424024546 0ustar jonasjonasrequire '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 inflecto-0.0.2/spec/unit/inflector/class_methods/camelize_spec.rb0000644000175000017500000000123312310435424024175 0ustar jonasjonasrequire '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 inflecto-0.0.2/spec/unit/inflector/class_methods/classify_spec.rb0000644000175000017500000000071512310435424024225 0ustar jonasjonasrequire '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 inflecto-0.0.2/spec/rcov.opts0000644000175000017500000000015712310435424015135 0ustar jonasjonas--exclude-only "spec/,^/" --sort coverage --callsites --xrefs --profile --text-summary --failure-threshold 100 inflecto-0.0.2/spec/spec_helper.rb0000644000175000017500000000034012310435424016065 0ustar jonasjonas# encoding: utf-8 require 'rspec' require 'inflecto' # require spec support files and shared behavior Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require(f) } RSpec.configure do |config| end inflecto-0.0.2/LICENSE0000644000175000017500000000206012310435424013323 0ustar jonasjonasCopyright (c) The rails, merb & datamapper team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. inflecto-0.0.2/Guardfile0000644000175000017500000000117112310435424014145 0ustar jonasjonas# encoding: utf-8 guard :bundler do watch('Gemfile') end guard :rspec do # run all specs if the spec_helper or supporting files files are modified watch('spec/spec_helper.rb') { 'spec' } watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec' } # run unit specs if associated lib code is modified watch(%r{\Alib/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}"] } watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' } # run a spec if it is modified watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z}) end inflecto-0.0.2/TODO0000644000175000017500000000004712310435424013011 0ustar jonasjonas* Find the guys to mention in credits. inflecto-0.0.2/.gitignore0000644000175000017500000000001612310435424014305 0ustar jonasjonas/Gemfile.lock inflecto-0.0.2/lib/0000755000175000017500000000000012310435424013066 5ustar jonasjonasinflecto-0.0.2/lib/inflecto/0000755000175000017500000000000012310435424014671 5ustar jonasjonasinflecto-0.0.2/lib/inflecto/defaults.rb0000644000175000017500000000452612310435424017034 0ustar jonasjonasInflecto.inflections do |inflect| inflect.plural(/\z/, 's') inflect.plural(/s\z/i, 's') inflect.plural(/(ax|test)is\z/i, '\1es') inflect.plural(/(octop|vir)us\z/i, '\1i') inflect.plural(/(octop|vir)i\z/i, '\1i') inflect.plural(/(alias|status)\z/i, '\1es') inflect.plural(/(bu)s\z/i, '\1ses') inflect.plural(/(buffal|tomat)o\z/i, '\1oes') inflect.plural(/([ti])um\z/i, '\1a') inflect.plural(/([ti])a\z/i, '\1a') inflect.plural(/sis\z/i, 'ses') inflect.plural(/(?:([^f])fe|([lr])f)\z/i, '\1\2ves') inflect.plural(/(hive)\z/i, '\1s') inflect.plural(/([^aeiouy]|qu)y\z/i, '\1ies') inflect.plural(/(x|ch|ss|sh)\z/i, '\1es') inflect.plural(/(matr|vert|ind)(?:ix|ex)\z/i, '\1ices') inflect.plural(/([m|l])ouse\z/i, '\1ice') inflect.plural(/([m|l])ice\z/i, '\1ice') inflect.plural(/^(ox)\z/i, '\1en') inflect.plural(/^(oxen)\z/i, '\1') inflect.plural(/(quiz)\z/i, '\1zes') inflect.singular(/s\z/i, '') inflect.singular(/(n)ews\z/i, '\1ews') inflect.singular(/([ti])a\z/i, '\1um') inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses\z/i, '\1\2sis') inflect.singular(/(^analy)ses\z/i, '\1sis') inflect.singular(/([^f])ves\z/i, '\1fe') inflect.singular(/(hive)s\z/i, '\1') inflect.singular(/(tive)s\z/i, '\1') inflect.singular(/([lr])ves\z/i, '\1f') inflect.singular(/([^aeiouy]|qu)ies\z/i, '\1y') inflect.singular(/(s)eries\z/i, '\1eries') inflect.singular(/(m)ovies\z/i, '\1ovie') inflect.singular(/(x|ch|ss|sh)es\z/i, '\1') inflect.singular(/([m|l])ice\z/i, '\1ouse') inflect.singular(/(bus)es\z/i, '\1') inflect.singular(/(o)es\z/i, '\1') inflect.singular(/(shoe)s\z/i, '\1') inflect.singular(/(cris|ax|test)es\z/i, '\1is') inflect.singular(/(octop|vir)i\z/i, '\1us') inflect.singular(/(alias|status)es\z/i, '\1') inflect.singular(/^(ox)en/i, '\1') inflect.singular(/(vert|ind)ices\z/i, '\1ex') inflect.singular(/(matr)ices\z/i, '\1ix') inflect.singular(/(quiz)zes\z/i, '\1') inflect.singular(/(database)s\z/i, '\1') inflect.irregular('person', 'people') inflect.irregular('man', 'men') inflect.irregular('child', 'children') inflect.irregular('sex', 'sexes') inflect.irregular('move', 'moves') inflect.irregular('cow', 'kine') inflect.uncountable(%w(hovercraft moose milk rain Swiss grass equipment information rice money species series fish sheep jeans)) end inflecto-0.0.2/lib/inflecto/inflections.rb0000644000175000017500000001316612310435424017542 0ustar jonasjonasmodule Inflecto # A singleton instance of this class is yielded by Inflecto.inflections, which can then be used to specify additional # inflection rules. Examples: # # Inflecto.inflections do |inflect| # inflect.plural /^(ox)$/i, '\1\2en' # inflect.singular /^(ox)en/i, '\1' # # inflect.irregular 'octopus', 'octopi' # # inflect.uncountable "equipment" # end # # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may # already have been loaded. # class Inflections # Return instance # # @return [Inflections] # # @api private # def self.instance @__instance__ ||= new end # Return plurals # # @return [Array] # # @api private # attr_reader :plurals # Return singulars # # @return [Array] # # @api private # attr_reader :singulars # Return uncountables # # @return [Array] # # @api private # attr_reader :uncountables # Return humans # # @return [Array] # # @api private # # attr_reader :humans # Initialize object # # @return [undefined] # # @api private # def initialize @plurals, @singulars, @uncountables, @humans = [], [], [], [] end # Add a new plural role # # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. # The replacement should always be a string that may include references to the matched data from the rule. # # @param [String, Regexp] rule # @param [String, Regexp] replacement # # @return [self] # # @api private # def plural(rule, replacement) @uncountables.delete(rule) if rule.is_a?(String) @uncountables.delete(replacement) @plurals.insert(0, [rule, replacement]) self end # Add a new singular rule # # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. # The replacement should always be a string that may include references to the matched data from the rule. # # @param [String, Regexp] rule # @param [String, Regexp] replacement # # @return [self] # # @api private # def singular(rule, replacement) @uncountables.delete(rule) if rule.is_a?(String) @uncountables.delete(replacement) @singulars.insert(0, [rule, replacement]) self end # 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 # for strings, not regular expressions. You simply pass the irregular in singular and plural form. # # @example # # Inflecto.irregular('octopus', 'octopi') # Inflecto.irregular('person', 'people') # # @param [String] singular # @param [String] plural # # @return [self] # # @api private # def irregular(singular, plural) @uncountables.delete(singular) @uncountables.delete(plural) if singular[0,1].upcase == plural[0,1].upcase plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1]) singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) else plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1]) plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1]) singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1]) singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1]) end self end # Add uncountable words # # Uncountable will not be inflected # # @example # # Inflecto.uncountable "money" # Inflecto.uncountable "money", "information" # Inflecto.uncountable %w( money information rice ) # # @param [Enumerable] words # # @return [self] # # @api private # def uncountable(words) @uncountables.concat(words) self end # Add humanize rule # # Specifies a humanized form of a string by a regular expression rule or by a string mapping. # When using a regular expression based replacement, the normal humanize formatting is called after the replacement. # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name') # # @example # Inflecto.human(/_cnt$/i, '\1_count') # Inflecto.human("legacy_col_person_name", "Name") # # @param [String, Regexp] rule # @param [String, Regexp] replacement # # @api private # # @return [self] # def human(rule, replacement) @humans.insert(0, [rule, replacement]) self end # Clear all inflection rules # # @example # # Inflecto.clear # # @return [self] # # @api private # def clear initialize self end end end inflecto-0.0.2/lib/inflecto.rb0000644000175000017500000001711112310435424015217 0ustar jonasjonas# The Inflecto transforms words from singular to plural, class names to table names, modularized class names to ones without, # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept # in inflections.rb. # # The Rails core team has stated patches for the inflections library will not be accepted # in order to avoid breaking legacy applications which may be relying on errant inflections. # If you discover an incorrect inflection and require it for your application, you'll need # to correct it yourself (explained below). module Inflecto # Convert input to UpperCamelCase # # Will also convert '/' to '::' which is useful for converting paths to namespaces. # # @param [String] input # # @example # Inflecto.camelize("data_mapper") # => "DataMapper" # Inflecto.camelize("data_mapper/errors") # => "DataMApper::Errors" # # @return [String] # # @api public # def self.camelize(input) input.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } end # Convert input to underscored, lowercase string # # Changes '::' to '/' to convert namespaces to paths. # # @param [String] input # # @example # Inflecto.underscore("DataMapper") # => "data_mapper" # Inflecto.underscore("DataMapper::Errors") # => "data_mapper/errors" # # @return [String] # # @api public # def self.underscore(input) word = input.to_s.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.downcase! word end # Convert input underscores to dashes # # @param [String] input # # @example # Inflecto.dasherize("foo_bar") # => "foo-bar" # # @return [String] # # @api public # def self.dasherize(input) input.gsub(/_/, '-') end # Return unscoped constant name # # @param [String] input # # @example # # Inflecto.demodulize("DataMapper::Error") # => "Error" # Inflecto.demodulize("DataMapper") # => "DataMapper" # # @return [String] # # @api public # def self.demodulize(input) input.to_s.gsub(/^.*::/, '') end # Creates a foreign key name # # @param [String] input # # @example # # Inflecto.foreign_key("Message) => "message_id" # # @return [String] # # @api private # def self.foreign_key(input) "#{underscore(demodulize(input))}_id" end # Find a constant with the name specified in the argument string # # The name is assumed to be the one of a top-level constant, constant scope of caller is igored # # @param [String] input # # @example # # Inflecto.constantize("Module") # => Module # Inflecto.constantize("DataMapper::Error") # => Test::Unit # # @return [Class, Module] # # @api private # def self.constantize(input) names = input.split('::') names.shift if names.empty? || names.first.empty? constant = Object names.each do |name| # Ruby 1.9 introduces an inherit argument for Module#const_get and # #const_defined? and changes their default behavior. if Module.method(:const_get).arity == 1 constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name) else constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name) end end constant end # Convert a number into an ordinal string # # @param [Fixnum] number # # @example # # ordinalize(1) # => "1st" # ordinalize(2) # => "2nd" # ordinalize(1002) # => "1002nd" # ordinalize(1003) # => "1003rd" # # @return [String] # # @api private # def self.ordinalize(number) if (11..13).include?(number.to_i % 100) "#{number}th" else case number.to_i % 10 when 1; "#{number}st" when 2; "#{number}nd" when 3; "#{number}rd" else "#{number}th" end end end # Yields a singleton instance of Inflecto::Inflections # # @example # # Inflecto.inflections do |inflect| # inflect.uncountable "rails" # end # # @return [Inflecto::Inflections] # # @api public # def self.inflections if block_given? yield Inflections.instance else Inflections.instance end end # Convert input word string to plural # # @param [String] word # # @example # # Inflecto.pluralize("post") # => "posts" # Inflecto.pluralize("octopus") # => "octopi" # Inflecto.pluralize("sheep") # => "sheep" # Inflecto.pluralize("words") # => "words" # Inflecto.pluralize("CamelOctopus") # => "CamelOctopi" # # @return [String] # # @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 end # Convert word to singular # # @param [String] word # # @example # # Inflecto.singularize("posts") # => "post" # Inflecto.singularize("octopi") # => "octopus" # Inflecto.singularize("sheep") # => "sheep" # Inflecto.singularize("word") # => "word" # Inflecto.singularize("CamelOctopi") # => "CamelOctopus" # # @return [String] # # @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 end # Humanize string # # @param [String] input # # capitalizes the first word and turns underscores into spaces and strips a # trailing "_id", if any. # Like +titleize+, this is meant for creating pretty output. # # @example # # Inflecto.humanize("employee_salary") # => "Employee salary" # Inflecto.humanize("author_id") # => "Author" # # @return [String] # # @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 end # Tabelize input string # # @param [String] input # # Create the name of a table like Rails does for models to table names. # This method # uses the +pluralize+ method on the last word in the string. # # @example # # Inflecto.tabelize("RawScaledScorer") # => "raw_scaled_scorers" # Inflecto.tabelize("egg_and_ham") # => "egg_and_hams" # Inflecto.tabelize("fancyCategory") # => "fancy_categories" # # @return [String] # # @api private # def self.tableize(input) pluralize(underscore(input).gsub('/','_')) end # Classify input # # Create a class name from a plural table name like Rails does for table names to models. # Note that this returns a string and not a Class. # # To convert to an actual class # follow +classify+ with +constantize+. # # @examples: # # Inflecto.classify("egg_and_hams") # => "EggAndHam" # Inflecto.classify("posts") # => "Post" # # # Singular names are not handled correctly: # Inflecto.classify("business") # => "Busines" # # @return [String] # # @api private # def self.classify(table_name) # strip out any leading schema name camelize(singularize(table_name.to_s.sub(/.*\./, ''))) end end require 'inflecto/inflections' require 'inflecto/defaults' inflecto-0.0.2/Rakefile0000644000175000017500000000006512310435424013766 0ustar jonasjonas# encoding: utf-8 require 'devtools' Devtools.init inflecto-0.0.2/Gemfile0000644000175000017500000000024112310435424013610 0ustar jonasjonassource :rubygems gemspec gem 'inflecto', :path => '.' gem 'devtools', :git => 'https://github.com/datamapper/devtools.git' eval File.read('Gemfile.devtools') inflecto-0.0.2/config/0000755000175000017500000000000012310435424013565 5ustar jonasjonasinflecto-0.0.2/config/flog.yml0000644000175000017500000000002512310435424015234 0ustar jonasjonas--- threshold: 143.4 inflecto-0.0.2/config/flay.yml0000644000175000017500000000004312310435424015240 0ustar jonasjonas--- threshold: 34 total_score: 164 inflecto-0.0.2/config/roodi.yml0000644000175000017500000000161312310435424015425 0ustar jonasjonas--- AbcMetricMethodCheck: { score: 70 } AssignmentInConditionalCheck: { } CaseMissingElseCheck: { } ClassLineCountCheck: { line_count: 325 } ClassNameCheck: pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ ClassVariableCheck: { } CyclomaticComplexityBlockCheck: { complexity: 4 } CyclomaticComplexityMethodCheck: { complexity: 4 } EmptyRescueBodyCheck: { } ForLoopCheck: { } MethodLineCountCheck: { line_count: 16 } MethodNameCheck: pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|<<|[+*&|-])\z/ ModuleLineCountCheck: { line_count: 331 } ModuleNameCheck: pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/ # TODO: decrease parameter_count to 2 or less ParameterNumberCheck: { parameter_count: 3 } inflecto-0.0.2/config/site.reek0000644000175000017500000000321512310435424015402 0ustar jonasjonas--- UncommunicativeParameterName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^.$/ - !ruby/regexp /[0-9]$/ - !ruby/regexp /[A-Z]/ LargeClass: max_methods: 14 exclude: [] enabled: true max_instance_variables: 8 UncommunicativeMethodName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^[a-z]$/ - !ruby/regexp /[0-9]$/ - !ruby/regexp /[A-Z]/ LongParameterList: max_params: 3 exclude: [] enabled: true overrides: {} FeatureEnvy: exclude: - Inflecto::Inflections#irregular enabled: true ClassVariable: exclude: [] enabled: true BooleanParameter: exclude: [] enabled: true IrresponsibleModule: exclude: [] enabled: true UncommunicativeModuleName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^.$/ - !ruby/regexp /[0-9]$/ NestedIterators: ignore_iterators: [] exclude: [] enabled: true max_allowed_nesting: 2 LongMethod: max_statements: 8 exclude: - Inflecto::Inflections#irregular enabled: true Duplication: allow_calls: [] exclude: - Inflecto::Inflections#irregular enabled: true max_calls: 2 UtilityFunction: max_helper_calls: 1 exclude: [] enabled: true Attribute: exclude: [] enabled: false UncommunicativeVariableName: accept: [] exclude: [] enabled: true reject: - !ruby/regexp /^.$/ - !ruby/regexp /[0-9]$/ - !ruby/regexp /[A-Z]/ SimulatedPolymorphism: exclude: [] enabled: true max_ifs: 2 DataClump: exclude: - [replacement, rule] enabled: true max_copies: 2 min_clump_size: 2 ControlCouple: exclude: [] enabled: true LongYieldList: max_params: 1 exclude: [] enabled: true inflecto-0.0.2/config/yardstick.yml0000644000175000017500000000002512310435424016302 0ustar jonasjonas--- threshold: 100.0 inflecto-0.0.2/config/mutant.yml0000644000175000017500000000004712310435424015621 0ustar jonasjonas--- name: inflecto namespace: Inflecto inflecto-0.0.2/.rspec0000644000175000017500000000001012310435424013424 0ustar jonasjonas--color inflecto-0.0.2/Gemfile.devtools0000644000175000017500000000315312310435424015453 0ustar jonasjonas# encoding: utf-8 group :development do gem 'rake', '~> 10.0.3' gem 'rspec', '~> 2.12.0' gem 'yard', '~> 0.8.3' end group :yard do gem 'redcarpet', '~> 2.2.2', :platforms => [ :mri, :rbx ] end group :guard do gem 'guard', '~> 1.6.1' gem 'guard-bundler', '~> 1.0.0' gem 'guard-rspec', '~> 2.3.3' # file system change event handling gem 'rb-fchange', '~> 0.0.6', :require => false gem 'rb-fsevent', '~> 0.9.3', :require => false gem 'rb-inotify', '~> 0.9.0', :require => false # Remove this one https://github.com/guard/listen/pull/78 is released gem 'listen', '~> 0.7.2', :git => 'https://github.com/guard/listen' # notification handling gem 'libnotify', '~> 0.8.0', :require => false gem 'rb-notifu', '~> 0.0.4', :require => false gem 'terminal-notifier-guard', '~> 1.5.3', :require => false end group :metrics do gem 'backports', '~> 2.7.0' gem 'flay', '~> 1.4.3' gem 'flog', '~> 2.5.3' gem 'reek', '~> 1.2.13', :git => 'https://github.com/troessner/reek.git', :ref => 'ef77fcecaa21c9ebcbe4d9a79d41b0e70196bf18' gem 'roodi', '~> 2.1.0' gem 'yardstick', '~> 0.9.0' platforms :ruby_18, :ruby_19 do # this indirectly depends on ffi which does not build on ruby-head gem 'yard-spellcheck', '~> 0.1.5' end platforms :mri_18 do gem 'rcov', '~> 1.0.0' end platforms :mri_19 do gem 'simplecov', '~> 0.7.1' end platforms :rbx do gem 'pelusa', '~> 0.2.2' end end group :benchmarks do gem 'rbench', '~> 0.2.3' end platform :jruby do group :jruby do gem 'jruby-openssl', '~> 0.8.2' end end inflecto-0.0.2/metadata.yml0000644000175000017500000000516412310435424014631 0ustar jonasjonas--- !ruby/object:Gem::Specification name: inflecto version: !ruby/object:Gem::Version version: 0.0.2 prerelease: platform: ruby authors: - The rails, merb & datamapper team - Markus Schirp autorequire: bindir: bin cert_chain: [] date: 2013-01-22 00:00:00.000000000 Z dependencies: [] description: Inflector for strings email: - mbj@seonic.net executables: [] extensions: [] extra_rdoc_files: - LICENSE - README.md - TODO files: - .gitignore - .rspec - .travis.yml - Changelog.md - Gemfile - Gemfile.devtools - Guardfile - LICENSE - README.md - Rakefile - TODO - config/flay.yml - config/flog.yml - config/mutant.yml - config/roodi.yml - config/site.reek - config/yardstick.yml - inflecto.gemspec - lib/inflecto.rb - lib/inflecto/defaults.rb - lib/inflecto/inflections.rb - spec/integration/inflector_spec.rb - spec/rcov.opts - spec/shared/command_method_behavior.rb - spec/shared/each_method_behaviour.rb - spec/shared/hash_method_behavior.rb - spec/shared/idempotent_method_behavior.rb - spec/shared/invertible_method_behaviour.rb - spec/shared/mutator_behavior.rb - spec/spec_helper.rb - spec/unit/inflector/class_methods/camelize_spec.rb - spec/unit/inflector/class_methods/classify_spec.rb - spec/unit/inflector/class_methods/demodulize_spec.rb - spec/unit/inflector/class_methods/foreign_key_spec.rb - spec/unit/inflector/class_methods/humanize_spec.rb - spec/unit/inflector/class_methods/pluralize_spec.rb - spec/unit/inflector/class_methods/singularize_spec.rb - spec/unit/inflector/class_methods/tabelize_spec.rb - spec/unit/inflector/class_methods/underscore_spec.rb homepage: https://github.com/mbj/inflecto licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 1.8.23 signing_key: specification_version: 3 summary: Inflector for strings test_files: - spec/integration/inflector_spec.rb - spec/unit/inflector/class_methods/camelize_spec.rb - spec/unit/inflector/class_methods/classify_spec.rb - spec/unit/inflector/class_methods/demodulize_spec.rb - spec/unit/inflector/class_methods/foreign_key_spec.rb - spec/unit/inflector/class_methods/humanize_spec.rb - spec/unit/inflector/class_methods/pluralize_spec.rb - spec/unit/inflector/class_methods/singularize_spec.rb - spec/unit/inflector/class_methods/tabelize_spec.rb - spec/unit/inflector/class_methods/underscore_spec.rb has_rdoc: inflecto-0.0.2/inflecto.gemspec0000644000175000017500000000110512310435424015465 0ustar jonasjonas# -*- encoding: utf-8 -*- Gem::Specification.new do |gem| gem.name = 'inflecto' gem.version = '0.0.2' gem.authors = ['The rails, merb & datamapper team', 'Markus Schirp'] gem.email = ['mbj@seonic.net'] gem.description = 'Inflector for strings' gem.summary = gem.description gem.homepage = 'https://github.com/mbj/inflecto' gem.require_paths = %w[lib] gem.files = `git ls-files`.split($/) gem.test_files = `git ls-files spec/{unit,integration}`.split($/) gem.extra_rdoc_files = %w[LICENSE README.md TODO] end inflecto-0.0.2/README.md0000644000175000017500000000356412310435424013607 0ustar jonasjonasinflecto ======== [![Build Status](https://secure.travis-ci.org/mbj/inflecto.png)](http://travis-ci.org/mbj/inflecto) [![Dependency Status](https://gemnasium.com/mbj/inflecto.png)](https://gemnasium.com/mbj/inflecto) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/mbj/inflecto) This is a standalone inflecto ripped out from [dm-core](https://github.com/datamapper/dm-core) The dm-core inflecto originated from [extlib](https://github.com/datamapper/extlib) The extlib inflecto originated from [active_support](https://github.com/rails/rails) Installation ------------ Install the gem ```inflecto``` via your preferred method. Examples -------- Soon. Credits ------- The rails, merb & datamapper team The current maintainer is Markus Schirp ([mbj](https://github.com/mbj)) Contributing ------------- * If you want your code merged into the mainline, please discuss the proposed changes with me before doing any work on it. This library is still in early development, and the direction it is going may not always be clear. Some features may not be appropriate yet, may need to be deferred until later when the foundation for them is laid, or may be more applicable in a plugin. * Fork the project. * Make your feature addition or bug fix. * Follow this [style guide](https://github.com/dkubb/styleguide). * Add specs for it. This is important so I don't break it in a future version unintentionally. Tests must cover all branches within the code, and code must be fully covered. * Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) * Run "rake ci". This must pass and not show any regressions in the metrics for the code to be merged. * Send me a pull request. Bonus points for topic branches. License ------- See LICENSE for details