rubype 0.2.6 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 942f53bc7020fb73e9af0158cd6c5d75fa7476f7
4
- data.tar.gz: e1fe176b85235b86007b967c040d5971a3851093
3
+ metadata.gz: 11e9ed5d164e542b00c10907afbe3267e85782d4
4
+ data.tar.gz: 9fd19b2b530147fb64d00e1f35a10d654c830f9a
5
5
  SHA512:
6
- metadata.gz: 5c60d752bd40eedcb3a85163d3c92d091f2a2e5e0098dd35afd61412a42cbec86416b67bec1cff60fa087b20b8eccabf9f413294e179dff9fed2d1dfe7ab45c0
7
- data.tar.gz: f62bfe664a071c7f5c86490f708b483da6b5e837530cfc843f388c50938b7c0e61bd99f76f7fc2acb1f595acb292158d12ff0277e3a9fe410240a19fce2be064
6
+ metadata.gz: 727672e8759985e9d1a5dabbfe6082c9637bf43897028783d513ce24ca5ce697da54fde51e47c334de55e0b1a7b87390e3c0bdebf3fbc51224bfd9f515d405d8
7
+ data.tar.gz: f0c745f01fc40523eab21e642c0d50368920304564bf14443f09c55ec693e604a5baf26ff553c6bafa32d551e608d38dc2f5925ad5e6a7433a423accff537b45
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ /vendor/
data/.travis.yml CHANGED
@@ -1,9 +1,13 @@
1
1
  language: ruby
2
+ sudo: false
3
+ cache:
4
+ - bundler
5
+
6
+ bundler:
2
7
  rvm:
3
- - 2.2.0
4
- - 2.1.5
5
- - 2.0.0
6
- - rbx-2
8
+ - 2.2
9
+ - 2.1
10
+ - 2.0
7
11
  - ruby-head
8
12
  # - jruby-head
9
13
  notifications:
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## CHANGELOG
2
+
3
+ ### 0.3.0
4
+
5
+ * First release with C ext.
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gem 'pry'
4
+ gem 'benchmark-ips'
4
5
  gemspec
data/README.md CHANGED
@@ -246,25 +246,44 @@ This gem requires Ruby 2.0.0+.
246
246
 
247
247
  ### Contributing
248
248
 
249
- Fork it ( https://github.com/[my-github-username]/rubype/fork )
249
+ * I really wanna make Rubype elegant source code.
250
250
 
251
- Create your feature branch (`git checkout -b my-new-feature`)
251
+ * Any feature or comments are welcome.
252
+
253
+ #### How to develop
254
+
255
+ Now Rubype is written with 100% Ruby.
256
+ In terms of performance, only core module(https://github.com/gogotanaka/Rubype/blob/develop/lib/rubype.rb#L4-L80) will be translate to C.
257
+
258
+ Only two API will be translate to C, it means you don't need to know what C dose!
259
+
260
+ 1. Fork it ( https://github.com/[my-github-username]/rubype/fork )
261
+
262
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
252
263
 
253
264
  $ bundle install --path vendor/bundle
254
265
 
255
- Commit your changes (`git commit -am 'Add some feature'`)
266
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
267
+
268
+ 4. Run tests
256
269
 
257
270
  $ bundle exec rake test
258
271
 
259
272
  ......
260
273
 
261
- Finished in 0.010961s, 547.3953 runs/s, 5017.7903 assertions/s.
274
+ 5. Run benchmerk(optional)
275
+
276
+ $ bundle exec rake bm
262
277
 
263
- 7 runs, 61 assertions, 0 failures, 0 errors, 0 skips
278
+ ......
264
279
 
265
- Push to the branch (`git push origin my-new-feature`)
280
+ 6. Push to the branch (`git push origin my-new-feature`)
266
281
 
267
- Create a new Pull Request to `develop` branch
282
+ 7. Create a new Pull Request to `develop` branch
268
283
 
269
284
  ## Credits
270
285
  [@chancancode](https://github.com/chancancode) and [This article](http://blog.codeclimate.com/blog/2014/05/06/gradual-type-checking-for-ruby/) first brought this to my attention. I've stolen some idea from them.
286
+
287
+ ## License
288
+
289
+ MIT license (© 2015 Kazuki Tanaka)
data/Rakefile CHANGED
@@ -1,8 +1,57 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require "rake/extensiontask"
3
4
 
5
+ # Test
6
+ #-----------------------------------------------
4
7
  Rake::TestTask.new(:test) do |t|
5
8
  t.libs << "test"
6
9
  end
7
10
 
8
- task default: :test
11
+ # Compile C extension
12
+ #-----------------------------------------------
13
+ Rake::ExtensionTask.new("rubype") do |ext|
14
+ ext.lib_dir = "lib/rubype"
15
+ end
16
+
17
+ task :compile_and_test do
18
+ Rake::Task['compile'].invoke
19
+ Rake::Task['test'].invoke
20
+ end
21
+
22
+ # Benchmark
23
+ #-----------------------------------------------
24
+ desc "Compare with pure ruby"
25
+ task :benchmark do
26
+ require "benchmark/ips"
27
+ require "rubype"
28
+ require "rubype/version"
29
+
30
+ puts "ruby version: #{RUBY_VERSION}"
31
+ class PureClass
32
+ def sum(x, y)
33
+ x + y
34
+ end
35
+ end
36
+ pure_instance = PureClass.new
37
+
38
+ puts "rubype version: #{Rubype::VERSION}"
39
+ class RubypeClass
40
+ def sum(x, y)
41
+ x + y
42
+ end
43
+ typesig :sum, [Numeric, Numeric] => Numeric
44
+ end
45
+ rubype_instance = RubypeClass.new
46
+
47
+ Benchmark.ips do |x|
48
+ x.report('Pure Ruby') { pure_instance.sum(4, 2) }
49
+ x.report('Rubype') { rubype_instance.sum(4, 2) }
50
+
51
+ x.compare!
52
+ end
53
+ end
54
+ task bm: :benchmark
55
+
56
+
57
+ task default: :compile_and_test
data/ext/rubype/rubype.c CHANGED
@@ -1,38 +1,100 @@
1
1
  #include "rubype.h"
2
2
 
3
- VALUE rb_mRubype, rb_cAny, rb_mBoolean, rb_cTypePair;
3
+ VALUE rb_mRubype, rb_cContract, rb_eRubypeArgumentTypeError, rb_eRubypeReturnTypeError, rb_eInvalidTypesigError;
4
+ static ID id_is_a_p, id_to_s, id_meth, id_owner, id_arg_types, id_rtn_type;
4
5
 
5
- #define STR2SYM(x) ID2SYM(rb_intern(x))
6
+ #define error_fmt "\nfor %"PRIsVALUE"\nExpected: %"PRIsVALUE"\nActual: %"PRIsVALUE""
7
+ #define unmatch_type_p(obj, type_info) !(match_type_p(obj, type_info))
8
+
9
+ int match_type_p(VALUE obj, VALUE type_info)
10
+ {
11
+ switch (TYPE(type_info)) {
12
+ case T_SYMBOL: return rb_respond_to(obj, rb_to_id(type_info));
13
+ break;
14
+
15
+ case T_MODULE: return (int)rb_funcall(obj, id_is_a_p, 1, type_info);
16
+ break;
17
+
18
+ case T_CLASS: return (int)rb_funcall(obj, id_is_a_p, 1, type_info);
19
+ break;
20
+
21
+ default: return 0;
22
+ break;
23
+ }
24
+ }
25
+
26
+ VALUE expected_mes(VALUE expected)
27
+ {
28
+ switch (TYPE(expected)) {
29
+ case T_SYMBOL: return rb_sprintf("respond to #%"PRIsVALUE, expected);
30
+ break;
31
+
32
+ case T_MODULE: return rb_funcall(expected, id_to_s, 0);
33
+ break;
34
+
35
+ case T_CLASS: return rb_funcall(expected, id_to_s, 0);
36
+ break;
37
+
38
+ default: return rb_str_new2("");
39
+ break;
40
+ }
41
+ }
6
42
 
7
43
  static VALUE
8
- rb_mod_prepend(int argc, VALUE *argv, VALUE module)
44
+ rb_rubype_assert_type(VALUE self, VALUE args, VALUE rtn)
9
45
  {
10
46
  int i;
11
- ID id_prepend_features, id_prepended;
12
-
13
- CONST_ID(id_prepend_features, "prepend_features");
14
- CONST_ID(id_prepended, "prepended");
15
- for (i = 0; i < argc; i++)
16
- Check_Type(argv[i], T_MODULE);
17
- while (argc--) {
18
- rb_funcall(argv[argc], id_prepend_features, 1, module);
19
- rb_funcall(argv[argc], id_prepended, 1, module);
47
+ VALUE target;
48
+ VALUE meth_caller, meth, arg_types, arg_type, rtn_type, arg;
49
+
50
+ meth_caller = rb_ivar_get(self, id_owner);
51
+ meth = rb_ivar_get(self, id_meth);
52
+ arg_types = rb_ivar_get(self, id_arg_types);
53
+ rtn_type = rb_ivar_get(self, id_rtn_type);
54
+
55
+ for (i=0; i<RARRAY_LEN(args); i++) {
56
+ arg = rb_ary_entry(args, i);
57
+ arg_type = rb_ary_entry(arg_types, i);
58
+
59
+ if (unmatch_type_p(arg, arg_type)){
60
+ target = rb_sprintf("%"PRIsVALUE"#%"PRIsVALUE"'s %d argument", meth_caller, meth, i+1);
61
+ rb_raise(rb_eRubypeArgumentTypeError, error_fmt, target, expected_mes(arg_type), arg);
20
62
  }
63
+ }
64
+
65
+ if (unmatch_type_p(rtn, rtn_type)){
66
+ target = rb_sprintf("%"PRIsVALUE"#%"PRIsVALUE"'s return", meth_caller, meth);
67
+ rb_raise(rb_eRubypeReturnTypeError, error_fmt, target, expected_mes(rtn_type), rtn);
68
+ }
69
+ return rtn;
70
+ }
21
71
 
22
- return module;
72
+ static VALUE
73
+ rb_rubype_initialize(VALUE self, VALUE arg_types, VALUE rtn_type, VALUE owner, VALUE meth) {
74
+ rb_ivar_set(self, id_owner, owner);
75
+ rb_ivar_set(self, id_meth, meth);
76
+ rb_ivar_set(self, id_arg_types, arg_types);
77
+ rb_ivar_set(self, id_rtn_type, rtn_type);
78
+ return Qnil;
23
79
  }
24
80
 
25
81
  void
26
82
  Init_rubype(void)
27
83
  {
28
- // rb_mRubype = rb_define_module("Rubype");
29
- // rb_cAny = rb_define_class("Any", rb_cObject);
30
- // rb_mBoolean = rb_define_module("Boolean");
31
- // rb_include_module(rb_cTrueClass, rb_mBoolean);
32
- // rb_include_module(rb_cFalseClass, rb_mBoolean);
33
- // rb_define_class(
34
- // "TypePair",
35
- // rb_funcall(rb_cStruct, rb_intern("new"), 2, STR2SYM("last_arg_type"), STR2SYM("rtn_type"))
36
- // );
37
- rb_define_method(rb_cModule, "prepend", rb_mod_prepend, -1);
84
+ rb_mRubype = rb_define_module("Rubype");
85
+
86
+ rb_eRubypeArgumentTypeError = rb_define_class_under(rb_mRubype, "ArgumentTypeError", rb_eTypeError);
87
+ rb_eRubypeReturnTypeError = rb_define_class_under(rb_mRubype, "ReturnTypeError", rb_eTypeError);
88
+ rb_eInvalidTypesigError = rb_define_class_under(rb_mRubype, "InvalidTypesigError", rb_eTypeError);
89
+
90
+ rb_cContract = rb_define_class_under(rb_mRubype, "Contract", rb_cObject);
91
+ rb_define_method(rb_cContract, "initialize", rb_rubype_initialize, 4);
92
+ rb_define_method(rb_cContract, "assert_type", rb_rubype_assert_type, 2);
93
+
94
+ id_meth = rb_intern("@meth");
95
+ id_owner = rb_intern("@owner");
96
+ id_arg_types = rb_intern("@arg_types");
97
+ id_rtn_type = rb_intern("@rtn_type");
98
+ id_is_a_p = rb_intern("is_a?");
99
+ id_to_s = rb_intern("to_s");
38
100
  }
data/lib/rubype.rb CHANGED
@@ -1,104 +1,48 @@
1
- require 'rubype/ordinal'
2
- # === Rubype core === #
3
- class Module
4
- private
5
- def __rubype__
6
- prepend (@__rubype__ = Module.new) unless @__rubype__
7
- @__rubype__
8
- end
9
- # typesig :__rubype__, [] => Rubype
10
-
11
- def typesig(meth, type_info_hash)
12
- ::Rubype.define_typed_method(self, meth, type_info_hash, __rubype__)
13
- self
14
- end
15
- # typesig :typesig, [Symbol, Hash] => Module
16
- end
1
+ require_relative 'rubype/version'
2
+ require_relative 'rubype/contract'
17
3
 
18
4
  module Rubype
19
- @@typed_method_info = Hash.new({})
20
- class ArgumentTypeError < ::TypeError; end
21
- class ReturnTypeError < ::TypeError; end
5
+ module TypeInfo; end
6
+ Module.send(:include, TypeInfo)
7
+ Symbol.send(:include, TypeInfo)
8
+ @@typed_methods = Hash.new({})
9
+
22
10
  class << self
23
11
  def define_typed_method(owner, meth, type_info_hash, __rubype__)
12
+ raise InvalidTypesigError unless valid_type_info_hash?(type_info_hash)
24
13
  arg_types, rtn_type = *type_info_hash.first
25
14
 
26
- @@typed_method_info[owner][meth] = { arg_types => rtn_type }
27
-
15
+ contract = Contract.new(arg_types, rtn_type, owner, meth)
16
+ @@typed_methods[owner][meth] = contract
17
+ method_visibility = get_method_visibility(owner, meth)
28
18
  __rubype__.send(:define_method, meth) do |*args, &block|
29
- ::Rubype.assert_arg_type(self, meth, args, arg_types, caller)
30
- super(*args, &block).tap do |rtn|
31
- ::Rubype.assert_rtn_type(self, meth, rtn, rtn_type, caller)
32
- end
19
+ contract.assert_type(args, super(*args, &block))
33
20
  end
34
- end
35
21
 
36
- def assert_arg_type(meth_caller, meth, args, type_infos, caller_trace)
37
- args.zip(type_infos).each.with_index(1) do |(arg, type_info), i|
38
- unless match_type?(arg, type_info)
39
- raise ArgumentTypeError,
40
- error_mes("#{meth_caller.class}##{meth}'s #{i}#{ordinal(i)} argument", type_info, arg, caller_trace)
41
- end
42
- end
22
+ __rubype__.send(method_visibility, meth)
43
23
  end
44
24
 
45
- def assert_rtn_type(meth_caller, meth, rtn, type_info, caller_trace)
46
- unless match_type?(rtn, type_info)
47
- raise ReturnTypeError,
48
- error_mes("#{meth_caller.class}##{meth}'s return", type_info, rtn, caller_trace)
25
+ def get_method_visibility(owner, meth)
26
+ case
27
+ when owner.private_method_defined?(meth)
28
+ :private
29
+ when owner.protected_method_defined?(meth)
30
+ :protected
31
+ else
32
+ :public
49
33
  end
50
34
  end
51
35
 
52
- def typed_method_info
53
- @@typed_method_info
36
+ def typed_methods
37
+ @@typed_methods
54
38
  end
55
39
 
56
40
  private
57
- def match_type?(obj, type_info)
58
- case type_info
59
- when Module; (obj.is_a?(type_info) || type_info == Any)
60
- when Symbol; (obj.respond_to?(type_info))
61
- end
62
- end
63
-
64
- def error_mes(target, expected, actual, caller_trace)
65
- expected_mes = case expected
66
- when Module; expected
67
- when Symbol; "respond to :#{expected}"
68
- end
69
- <<-ERROR_MES
70
- for #{target}
71
- Expected: #{expected_mes},
72
- Actual: #{actual.inspect}
73
-
74
- #{caller_trace.join("\n")}
75
- ERROR_MES
41
+ def valid_type_info_hash?(type_info_hash)
42
+ return false unless type_info_hash.is_a?(Hash)
43
+ type_info_hash.first[0].is_a?(Array)
76
44
  end
77
45
  end
78
46
  end
79
- # === end (only 79 lines :D)=== #
80
-
81
- # Builtin Contracts
82
- class Any; end
83
- module Boolean; end
84
- TrueClass.send(:include, Boolean)
85
- FalseClass.send(:include, Boolean)
86
-
87
- class Method
88
- def type_info
89
- if methods_hash = Rubype.typed_method_info[owner]
90
- methods_hash[name]
91
- end
92
- end
93
- typesig :type_info, [] => Hash
94
47
 
95
- def arg_types
96
- type_info.first.first if type_info
97
- end
98
- typesig :arg_types, [] => Array
99
-
100
- def return_type
101
- type_info.first.last if type_info
102
- end
103
- typesig :arg_types, [] => Any
104
- end
48
+ require_relative 'rubype/core_ext'
@@ -0,0 +1,10 @@
1
+ require_relative 'ordinalize'
2
+ require 'rubype/rubype'
3
+
4
+ class Rubype::Contract
5
+ attr_accessor :arg_types, :rtn_type
6
+
7
+ def info
8
+ { @arg_types => @rtn_type }
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ module Boolean; end
2
+ TrueClass.send(:include, Boolean)
3
+ FalseClass.send(:include, Boolean)
4
+ Any = BasicObject
5
+
6
+ class Module
7
+ private
8
+
9
+ def __rubype__
10
+ prepend (@__rubype__ = Module.new) unless @__rubype__
11
+ @__rubype__
12
+ end
13
+
14
+ def typesig(meth, type_info_hash)
15
+ ::Rubype.define_typed_method(self, meth, type_info_hash, __rubype__)
16
+ self
17
+ end
18
+ end
19
+
20
+ class Method
21
+ def type_info
22
+ Rubype.typed_methods[owner][name].info
23
+ end
24
+ typesig :type_info, [] => Hash
25
+
26
+ def arg_types
27
+ Rubype.typed_methods[owner][name].arg_types
28
+ end
29
+ typesig :arg_types, [] => Array
30
+
31
+ def return_type
32
+ Rubype.typed_methods[owner][name].rtn_type
33
+ end
34
+ typesig :arg_types, [] => Any
35
+ end
@@ -0,0 +1,13 @@
1
+ # Borrowed from ActiveSupport::Inflector
2
+ def ordinalize(number)
3
+ if (11..13).include?(number % 100)
4
+ "#{number}th"
5
+ else
6
+ case number % 10
7
+ when 1 then "#{number}st"
8
+ when 2 then "#{number}nd"
9
+ when 3 then "#{number}rd"
10
+ else "#{number}th"
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Rubype
2
- VERSION = "0.2.6"
2
+ VERSION = "0.3.0"
3
3
  end
data/rubype.gemspec CHANGED
@@ -15,6 +15,7 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.extensions = ["ext/rubype/extconf.rb"]
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
20
  spec.require_paths = ["lib"]
20
21
 
@@ -23,4 +24,5 @@ Gem::Specification.new do |spec|
23
24
  spec.add_development_dependency "bundler", "~> 1.3"
24
25
  spec.add_development_dependency "rake"
25
26
  spec.add_development_dependency "minitest"
27
+ spec.add_development_dependency "rake-compiler"
26
28
  end
data/test/test_rubype.rb CHANGED
@@ -1,10 +1,5 @@
1
1
  require 'minitest_helper'
2
- class TypePair
3
- def to_s
4
- "#{last_arg_type} => #{rtn_type}"
5
- end
6
- end
7
- class TestRubype < MiniTest::Unit::TestCase
2
+ class TestRubype < Minitest::Test
8
3
  def setup
9
4
  @string = 'str'
10
5
  @numeric = 1
@@ -109,6 +104,34 @@ class TestRubype < MiniTest::Unit::TestCase
109
104
  #assert_equal err.message, %|Expected MyClass#test_mth's 2nd argument to be Numeric but got "2" instead|
110
105
  end
111
106
 
107
+ def test_respects_method_visibility
108
+ klass = Class.new.class_eval <<-RUBY_CODE
109
+ private
110
+ def private_mth(n1, n2)
111
+ end
112
+ typesig :private_mth, [Numeric, Numeric] => NilClass
113
+
114
+ protected
115
+ def protected_mth(n1, n2)
116
+ end
117
+ typesig :protected_mth, [Numeric, Numeric] => NilClass
118
+ RUBY_CODE
119
+ instance = klass.new
120
+
121
+ # assert_raises(NoMethodError){ instance.private_mth(1,2) }
122
+ assert_raises(NoMethodError){ instance.protected_mth(1,2) }
123
+ end
124
+
125
+ def test_invalid_typesig
126
+ assert_raises(Rubype::InvalidTypesigError) do
127
+ Class.new.class_eval <<-RUBY_CODE
128
+ def mth(n1, n2)
129
+ end
130
+ typesig :private_mth, Numeric => NilClass
131
+ RUBY_CODE
132
+ end
133
+ end
134
+
112
135
  private
113
136
  def assert_equal_to_s(str, val)
114
137
  assert_equal str, val.to_s
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gogotanaka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-13 00:00:00.000000000 Z
11
+ date: 2015-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,18 +52,33 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: Ruby with type.
56
70
  email:
57
71
  - mail@tanakakazuki.com
58
72
  executables:
59
73
  - rubype
60
- extensions: []
74
+ extensions:
75
+ - ext/rubype/extconf.rb
61
76
  extra_rdoc_files: []
62
77
  files:
63
78
  - ".gitignore"
64
79
  - ".travis.yml"
80
+ - CHANGELOG.md
65
81
  - Gemfile
66
- - LICENSE.txt
67
82
  - README.md
68
83
  - Rakefile
69
84
  - bin/rubype
@@ -71,7 +86,9 @@ files:
71
86
  - ext/rubype/rubype.c
72
87
  - ext/rubype/rubype.h
73
88
  - lib/rubype.rb
74
- - lib/rubype/ordinal.rb
89
+ - lib/rubype/contract.rb
90
+ - lib/rubype/core_ext.rb
91
+ - lib/rubype/ordinalize.rb
75
92
  - lib/rubype/version.rb
76
93
  - rubype.gemspec
77
94
  - test/minitest_helper.rb
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2014 gogotanaka
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,13 +0,0 @@
1
- # Borrowed from ActiveSupport::Inflector
2
- def ordinal(number)
3
- if (11..13).include?(number % 100)
4
- "th"
5
- else
6
- case number % 10
7
- when 1; "st"
8
- when 2; "nd"
9
- when 3; "rd"
10
- else "th"
11
- end
12
- end
13
- end