rubype 0.2.6 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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