gcnovus-quacks_like 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +37 -0
- data/Rakefile +99 -0
- data/lib/quacks_like.rb +92 -0
- data/test/quacks_like_test.rb +71 -0
- metadata +58 -0
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## QuacksLike
|
2
|
+
|
3
|
+
QuacksLike is a tiny gem intended to push people towards using duck typing instead of static typing.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
def some_method(an_argument)
|
8
|
+
case an_argument
|
9
|
+
when quacks_like?(:to_i) # responds_to?(:to_i)
|
10
|
+
do_something_with an_argument.to_i
|
11
|
+
when quacks_like?(:foo, :bar) # responds_to?(:foo) && responds_to?(:bar)
|
12
|
+
an_argument.foo + an_argument.bar
|
13
|
+
else
|
14
|
+
raise "#{an_argument} can't quack properly; is it duck-like?"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
## Getting it
|
19
|
+
|
20
|
+
First, of course, install the gem:
|
21
|
+
|
22
|
+
sudo gem install gcnovus-quacks_like
|
23
|
+
|
24
|
+
Then add it to either the global namespace:
|
25
|
+
|
26
|
+
require 'rubygems'
|
27
|
+
require 'gcnovus-quacks_like'
|
28
|
+
QuacksLike.install_everywhere!
|
29
|
+
|
30
|
+
or just use it in one class:
|
31
|
+
|
32
|
+
require 'rubygems'
|
33
|
+
require 'gcnovus-quacks_like'
|
34
|
+
|
35
|
+
class MyClass
|
36
|
+
include QuacksLike
|
37
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift("lib")
|
6
|
+
require 'quacks_like'
|
7
|
+
|
8
|
+
task :default => ['test']
|
9
|
+
|
10
|
+
PROJECT_ROOT = File.expand_path(File.dirname(__FILE__))
|
11
|
+
|
12
|
+
LIB_DIRECTORIES = FileList.new do |fl|
|
13
|
+
fl.include "#{PROJECT_ROOT}/lib"
|
14
|
+
end
|
15
|
+
|
16
|
+
TEST_FILES = FileList.new do |fl|
|
17
|
+
fl.include "#{PROJECT_ROOT}/test/**/*_test.rb"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Run all tests'
|
21
|
+
Rake::TestTask.new(:test) do |t|
|
22
|
+
t.libs = LIB_DIRECTORIES
|
23
|
+
t.test_files = TEST_FILES
|
24
|
+
t.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "Build a code coverage report"
|
28
|
+
task :coverage do
|
29
|
+
files = TEST_FILES.join(" ")
|
30
|
+
sh "rcov -o coverage #{files} --exclude ^/Library/Ruby/,^init.rb --include lib/ --include-file ^lib/.*\\.rb"
|
31
|
+
end
|
32
|
+
|
33
|
+
namespace :coverage do
|
34
|
+
task :clean do
|
35
|
+
rm_r 'coverage' if File.directory?('coverage')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Rake::RDocTask.new(:rdoc) do |rd|
|
40
|
+
rd.rdoc_dir = 'doc'
|
41
|
+
rd.main = 'lib/quacks_like.rb'
|
42
|
+
rd.rdoc_files.include("lib/**/*.rb")
|
43
|
+
rd.options << "--all"
|
44
|
+
rd.title = 'QuacksLike Documentation'
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
#Hey, thanks, mislave-will_paginate!
|
49
|
+
desc %{Update ".manifest" with the latest list of project filenames. Respect\
|
50
|
+
.gitignore by excluding everything that git ignores. Update `files` and\
|
51
|
+
`test_files` arrays in "*.gemspec" file if it's present.}
|
52
|
+
task :manifest do
|
53
|
+
list = `git ls-files --full-name --exclude=*.gemspec --exclude=.*`.chomp.split("\n")
|
54
|
+
|
55
|
+
if spec_file = Dir['*.gemspec'].first
|
56
|
+
spec = File.read spec_file
|
57
|
+
spec.gsub! /^(\s* s.(test_)?files \s* = \s* )( \[ [^\]]* \] | %w\( [^)]* \) )/mx do
|
58
|
+
assignment = $1
|
59
|
+
bunch = $2 ? list.grep(/^test\//) : list
|
60
|
+
'%s%%w(%s)' % [assignment, bunch.join(' ')]
|
61
|
+
end
|
62
|
+
|
63
|
+
File.open(spec_file, 'w') { |f| f << spec }
|
64
|
+
end
|
65
|
+
File.open('.manifest', 'w') { |f| f << list.join("\n") }
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
# Hey, thanks, thoughtbot-shoulda
|
70
|
+
spec = Gem::Specification.new do |s|
|
71
|
+
s.name = "quacks_like"
|
72
|
+
s.version = QuacksLike::VERSION
|
73
|
+
s.summary = "Type like a duck."
|
74
|
+
s.description = 'QuacksLike is a tiny gem intended to push people towards using duck typing instead of static typing.'
|
75
|
+
s.homepage = "http://github.com/gcnovus/quacks_like"
|
76
|
+
|
77
|
+
s.files = FileList["[A-Z]*", "{lib,test}/**/*"]
|
78
|
+
|
79
|
+
s.has_rdoc = true
|
80
|
+
s.rdoc_options = ["--line-numbers", "--main", "lib/quacks_like.rb"]
|
81
|
+
|
82
|
+
s.authors = ["James Rosen"]
|
83
|
+
s.email = "james.a.rosen@gmail.com"
|
84
|
+
end
|
85
|
+
|
86
|
+
Rake::GemPackageTask.new spec do |pkg|
|
87
|
+
pkg.need_tar = true
|
88
|
+
pkg.need_zip = true
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "Clean files generated by rake tasks"
|
92
|
+
task :clobber => [:clobber_rdoc, :clobber_package]
|
93
|
+
|
94
|
+
desc "Generate a gemspec file for GitHub"
|
95
|
+
task :gemspec do
|
96
|
+
File.open("#{spec.name}.gemspec", 'w') do |f|
|
97
|
+
f.write spec.to_ruby
|
98
|
+
end
|
99
|
+
end
|
data/lib/quacks_like.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# == QuacksLike
|
2
|
+
#
|
3
|
+
# QuacksLike is a tiny gem intended to push people towards using
|
4
|
+
# duck typing instead of static typing.
|
5
|
+
#
|
6
|
+
# == Usage
|
7
|
+
#
|
8
|
+
# def some_method(an_argument)
|
9
|
+
# case an_argument
|
10
|
+
# when quacks_like?(:to_i) # responds_to?(:to_i)
|
11
|
+
# do_something_with an_argument.to_i
|
12
|
+
# when quacks_like?(:foo, :bar) # responds_to?(:foo) && responds_to?(:bar)
|
13
|
+
# an_argument.foo + an_argument.bar
|
14
|
+
# else
|
15
|
+
# raise "#{an_argument} can't quack properly; is it duck-like?"
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# == Installation
|
20
|
+
#
|
21
|
+
# === Riding the Rails
|
22
|
+
#
|
23
|
+
# Add the following to your <tt>environment.rb</tt>:
|
24
|
+
#
|
25
|
+
# config.gem 'gcnovus-quacks_like', :version => '~> 1.0.0', :lib => 'quacks_like',
|
26
|
+
# :source => 'http://gems.github.com'
|
27
|
+
#
|
28
|
+
# === Anywhere else
|
29
|
+
#
|
30
|
+
# From your command prompt:
|
31
|
+
#
|
32
|
+
# sudo gem install gcnovus-quacks_like
|
33
|
+
#
|
34
|
+
# == Setting it up
|
35
|
+
#
|
36
|
+
# === Globally
|
37
|
+
#
|
38
|
+
# If you don't mind mucking with Kernel and want the easiest thing
|
39
|
+
# that could possibly work, do this:
|
40
|
+
#
|
41
|
+
# require 'rubygems'
|
42
|
+
# require 'gcnovus-quacks_like'
|
43
|
+
# QuacksLike.install_everywhere!
|
44
|
+
#
|
45
|
+
# === Or just for one class
|
46
|
+
#
|
47
|
+
# require 'rubygems'
|
48
|
+
# require 'gcnovus-quacks_like'
|
49
|
+
#
|
50
|
+
# class MyClass
|
51
|
+
# include QuacksLike # for instance methods
|
52
|
+
# extend QuacksLike # for class methods
|
53
|
+
# end
|
54
|
+
module QuacksLike
|
55
|
+
|
56
|
+
VERSION = '1.0.1'
|
57
|
+
|
58
|
+
def self.install_everywhere!
|
59
|
+
Kernel.class_eval do
|
60
|
+
include ::QuacksLike
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Create a new matcher that matches all of the methods given.
|
65
|
+
#
|
66
|
+
# Raises a <tt>NoMethodError</tt> if any method does not respond
|
67
|
+
# to <tt>:to_sym</tt>.
|
68
|
+
#
|
69
|
+
# Raises a <tt>ArgumentError</tt> if any method responds to
|
70
|
+
# <tt>:to_sym</tt> but the result is not a <tt>Symbol</tt>.
|
71
|
+
def quacks_like?(*methods)
|
72
|
+
::QuacksLike::Matcher.new(*methods)
|
73
|
+
end
|
74
|
+
|
75
|
+
class Matcher
|
76
|
+
|
77
|
+
def initialize(*methods)
|
78
|
+
@methods = methods.map do |m|
|
79
|
+
sym = m.to_sym
|
80
|
+
raise ArgumentError.new("#{m} could not be converted to a symbol") unless sym
|
81
|
+
sym
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns +true+ iff +object+ responds to all of <tt>self</tt>'s methods.
|
86
|
+
def ===(object)
|
87
|
+
@methods.all? { |m| object.respond_to?(m) }
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'shoulda'
|
6
|
+
require 'mocha'
|
7
|
+
require 'quacks_like'
|
8
|
+
|
9
|
+
class Duck
|
10
|
+
def eat(bread)
|
11
|
+
"yum"
|
12
|
+
end
|
13
|
+
def quack!
|
14
|
+
"quack!!"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class QuacksLikeTest < Test::Unit::TestCase
|
19
|
+
|
20
|
+
context 'the QuacksLike class' do
|
21
|
+
setup { Kernel.expects(:include).with(QuacksLike) }
|
22
|
+
should 'be able to install itself everywhere' do
|
23
|
+
QuacksLike.install_everywhere!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context ':quacks_like?' do
|
28
|
+
|
29
|
+
setup do
|
30
|
+
extend QuacksLike
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'given an argument that cannot be converted to a Symbol' do
|
34
|
+
should 'raise an NoMethodError' do
|
35
|
+
assert_raises(NoMethodError) { quacks_like?(Object.new) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'given an argument that knows how to convert to a Symbol, but can\'t' do
|
40
|
+
should 'raise an ArgumentException' do
|
41
|
+
assert_raises(ArgumentError) { quacks_like?(8) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'given a single valid argument' do
|
46
|
+
|
47
|
+
should 'return a Object that acts as a matcher' do
|
48
|
+
matcher = quacks_like?(:foo)
|
49
|
+
assert !matcher.nil?
|
50
|
+
assert matcher.respond_to?(:===)
|
51
|
+
end
|
52
|
+
|
53
|
+
should 'create a matcher that checks that arguments respond to the given method' do
|
54
|
+
assert quacks_like?(:eat) === Duck.new
|
55
|
+
assert !(quacks_like?(:juggle) === Duck.new)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'given several valid arguments' do
|
61
|
+
|
62
|
+
should 'create a matcher that checks that arguments respond to ALL of the given methods' do
|
63
|
+
assert quacks_like?(:eat, :quack!, :to_s) === Duck.new
|
64
|
+
assert !(quacks_like?(:eat, :juggle, :to_s) === Duck.new)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gcnovus-quacks_like
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Rosen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-20 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: QuacksLike is a tiny gem intended to push people towards using duck typing instead of static typing.
|
17
|
+
email: james.a.rosen@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/quacks_like.rb
|
28
|
+
- test/quacks_like_test.rb
|
29
|
+
has_rdoc: false
|
30
|
+
homepage: http://github.com/gcnovus/quacks_like
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options:
|
33
|
+
- --line-numbers
|
34
|
+
- --main
|
35
|
+
- lib/quacks_like.rb
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: "0"
|
43
|
+
version:
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.2.0
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: Type like a duck.
|
57
|
+
test_files: []
|
58
|
+
|