unpatched 0.0.1

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.
data/License ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Konstantin Haase
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,62 @@
1
+ Convenience library, like ActiveSupport or extlib, but without a single
2
+ monkey-patch. It is also an API experiment.
3
+
4
+ # Usage
5
+
6
+ Stand alone:
7
+
8
+ ``` ruby
9
+ require 'unpatched'
10
+ inlcude Unpatched
11
+
12
+ like("FooBar").but.underscore!
13
+ about(1).month.and(4).days.ago!
14
+ ```
15
+
16
+ Is that too much sugar? Try this:
17
+
18
+ ``` ruby
19
+ require 'unpatched'
20
+ include Unpatched::Unfancy
21
+ _('FooBar').underscore!
22
+ ```
23
+
24
+ Still too much?
25
+
26
+ ``` ruby
27
+ require 'unpatched'
28
+ Unpatched['FooBar'].underscore!
29
+ ```
30
+
31
+ With Sinatra:
32
+
33
+ ``` ruby
34
+ require 'sinatra'
35
+ require 'unpatched'
36
+ helpers Unpatched
37
+
38
+ get '/' do
39
+ expires exactly(1.5).minutes.from_now!
40
+ "Hey, ho, let's go!"
41
+ end
42
+ ```
43
+
44
+ # When to use an exclamation mark
45
+
46
+ Short: You don't have to. But methods without one will always return magically
47
+ enhanced objects. Since you never want to pass those on (otherwise, what's the
48
+ point?), you can get vanilla objects by using an exclamation mark.
49
+
50
+ Rule of thumb: Use it at the end of your method chain.
51
+
52
+ # Installation
53
+
54
+ gem install unpatched
55
+
56
+ # TODO
57
+
58
+ * Write code and documentation
59
+ * Fix project description in gemspec
60
+ * Change testing framework if necessary (see Rakefile, currently RSpec)
61
+ * Adjust unpatched.gemspec if your github name is not rkh
62
+ * Adjust License if your real name is not Konstantin Haase
@@ -0,0 +1,37 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ begin
4
+ require 'bundler'
5
+ Bundler::GemHelper.install_tasks
6
+ rescue LoadError => e
7
+ $stderr.puts e
8
+ end
9
+
10
+ desc "run specs"
11
+ task(:spec) { ruby '-S rspec spec' }
12
+
13
+ desc "generate gemspec"
14
+ task 'unpatched.gemspec' do
15
+ require 'unpatched/version'
16
+ content = File.read 'unpatched.gemspec'
17
+
18
+ fields = {
19
+ :authors => `git shortlog -sn`.scan(/[^\d\s].*/),
20
+ :email => `git shortlog -sne`.scan(/[^<]+@[^>]+/),
21
+ :files => `git ls-files`.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ }
22
+ }
23
+
24
+ fields.each do |field, values|
25
+ updated = " s.#{field} = ["
26
+ updated << values.map { |v| "\n %p" % v }.join(',')
27
+ updated << "\n ]"
28
+ content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated)
29
+ end
30
+
31
+ content.sub! /(s\.version.*=\s+).*/, "\\1\"#{Unpatched::VERSION}\""
32
+ File.open('unpatched.gemspec', 'w') { |f| f << content }
33
+ end
34
+
35
+ task :gemspec => 'unpatched.gemspec'
36
+ task :default => :spec
37
+ task :test => :spec
@@ -0,0 +1,168 @@
1
+ require 'unpatched/version'
2
+
3
+ module Unpatched
4
+ MINUTE = 60
5
+ HOUR = 60 * MINUTE
6
+ DAY = 24 * HOUR
7
+ MONTH = 30 * DAY
8
+ YEAR = 365 * DAY
9
+
10
+ module Utils
11
+ extend self
12
+
13
+ def wrapped(value)
14
+ NormalWrapper.new(value)
15
+ end
16
+
17
+ def unwrapped(value)
18
+ value = value.__instance_eval__ { @value } while Wrapper === value
19
+ value
20
+ end
21
+
22
+ def numeric(value)
23
+ case value
24
+ when Numeric then value
25
+ when Wrapper then numeric unwrapped(value)
26
+ else
27
+ begin
28
+ Integer value
29
+ rescue ArgumentError
30
+ Float value
31
+ end
32
+ end
33
+ end
34
+
35
+ alias num numeric
36
+ end
37
+
38
+ class Wrapper < defined?(BasicObject) ? BasicObject : Object
39
+ def self.const_missing(const) ::Unpatched.const_get(const) end
40
+ alias __instance_eval__ instance_eval
41
+
42
+ if superclass == Object
43
+ instance_methods.each do |m|
44
+ undef_method(m) if m.to_s !~ /(?:^__|^send$|^object_id$)/
45
+ end
46
+ else
47
+ undef ==
48
+ undef equal?
49
+ undef instance_eval
50
+ end
51
+
52
+ def initialize(value)
53
+ @value = Utils.unwrapped(value)
54
+ end
55
+
56
+ def inspect
57
+ @value.inspect
58
+ end
59
+
60
+ def and(value = (undefined = true))
61
+ return self if undefined
62
+ if Wrapper === value
63
+ Utils.wrapped @value + unwrapped(value)
64
+ else
65
+ MultiWrapper.new self, value
66
+ end
67
+ end
68
+
69
+ alias_method :but, :and
70
+ end
71
+
72
+ class MultiWrapper < Wrapper
73
+ def initialize(base, value)
74
+ @base, @value = base, Utils.wrapped(value)
75
+ end
76
+
77
+ private
78
+ def method_missing(*a, &b)
79
+ @base + @value.__send__(*a, &b)
80
+ end
81
+ end
82
+
83
+ class NormalWrapper < Wrapper
84
+ def second
85
+ value = Utils.unwrapped @value
86
+ if value.respond_to? :second
87
+ value.second
88
+ else
89
+ Utils.wrapped Utils.num(value)
90
+ end
91
+ rescue TypeError, ArgumentError => err
92
+ raise err unless value.respond_to? :[]
93
+ value[1]
94
+ end
95
+
96
+ def underscore
97
+ to_s.
98
+ gsub(/::/, '/').
99
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
100
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
101
+ tr("-", "_").
102
+ downcase
103
+ end
104
+
105
+ def seconds; Utils.wrapped Utils.num(@value) end
106
+ def minute; Utils.wrapped Utils.num(@value) * MINUTE end
107
+ def hour; Utils.wrapped Utils.num(@value) * HOUR end
108
+ def day; Utils.wrapped Utils.num(@value) * DAY end
109
+ def month; Utils.wrapped Utils.num(@value) * MONTH end
110
+ def year; Utils.wrapped Utils.num(@value) * YEAR end
111
+
112
+ def before(other)
113
+ Utils.wrapped Utils.unwrapped(other) - @value
114
+ end
115
+
116
+ def after(other)
117
+ Utils.wrapped Utils.unwrapped(other) + @value
118
+ end
119
+
120
+ def ago
121
+ before Time.now
122
+ end
123
+
124
+
125
+ def from_now
126
+ after Time.now
127
+ end
128
+
129
+ alias minutes minute
130
+ alias hours hour
131
+ alias days day
132
+ alias months month
133
+ alias years year
134
+
135
+ private
136
+
137
+ def method_missing(m, *a, &b)
138
+ a.map! { |e| Utils.unwrapped e }
139
+ if m[-1] == ?! and NormalWrapper.method_defined?(method = m[0..-2])
140
+ result = __send__(method, *a, &b)
141
+ Utils.unwrapped result
142
+ else
143
+ Utils.wrapped @value.__send__(m, *a, &b)
144
+ end
145
+ end
146
+ end
147
+
148
+ module Unfancy
149
+ private
150
+ def _(value)
151
+ Utils.wrapped(value)
152
+ end
153
+ end
154
+
155
+ module Fancy
156
+ include Unfancy
157
+ %w[about exactly like is some].each do |meth|
158
+ alias_method meth, :_
159
+ private meth
160
+ end
161
+ end
162
+
163
+ def self.[](value)
164
+ Utils.wrapped(value)
165
+ end
166
+
167
+ include Fancy
168
+ end
@@ -0,0 +1,42 @@
1
+ module Unpatched
2
+ def self.version
3
+ VERSION
4
+ end
5
+
6
+ module VERSION
7
+ extend Comparable
8
+
9
+ MAJOR = 0
10
+ MINOR = 0
11
+ TINY = 1
12
+ SIGNATURE = [MAJOR, MINOR, TINY]
13
+ STRING = SIGNATURE.join '.'
14
+
15
+ def self.major; MAJOR end
16
+ def self.minor; MINOR end
17
+ def self.tiny; TINY end
18
+ def self.to_s; STRING end
19
+
20
+ def self.hash
21
+ STRING.hash
22
+ end
23
+
24
+ def self.<=>(other)
25
+ other = other.split('.').map { |i| i.to_i } if other.respond_to? :split
26
+ SIGNATURE <=> Array(other)
27
+ end
28
+
29
+ def self.inspect
30
+ STRING.inspect
31
+ end
32
+
33
+ def self.respond_to?(meth, *)
34
+ meth.to_s !~ /^__|^to_str$/ and STRING.respond_to? meth unless super
35
+ end
36
+
37
+ def self.method_missing(meth, *args, &block)
38
+ return super unless STRING.respond_to?(meth)
39
+ STRING.send(meth, *args, &block)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ require 'unpatched'
2
+
3
+ describe Unpatched do
4
+ before { extend Unpatched }
5
+ it 'should not fail me' do
6
+ exactly(2).seconds.should == 2
7
+ exactly(2).minutes.should == 120
8
+ about(10).minutes.and(1).second.should == 601
9
+ _('FooBar').underscore.should == 'foo_bar'
10
+ about(10).minutes.ago!.should be_a(Time)
11
+ about(10).minutes.from_now!.should be_a(Time)
12
+ exactly(10).before(12).should == 2
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ # Run `rake unpatched.gemspec` to update the gemspec.
2
+ Gem::Specification.new do |s|
3
+ # general infos
4
+ s.name = "unpatched"
5
+ s.version = "0.0.1"
6
+ s.description = "Convenience library without a single monkey-patch."
7
+ s.homepage = "http://github.com/rkh/unpatched"
8
+ s.summary = s.description
9
+
10
+ # generated from git shortlog -sn
11
+ s.authors = [
12
+ "Konstantin Haase"
13
+ ]
14
+
15
+ # generated from git shortlog -sne
16
+ s.email = [
17
+ "konstantin.mailinglists@googlemail.com"
18
+ ]
19
+
20
+ # generated from git ls-files
21
+ s.files = [
22
+ "License",
23
+ "README.md",
24
+ "Rakefile",
25
+ "lib/unpatched.rb",
26
+ "lib/unpatched/version.rb",
27
+ "spec/unpatched_spec.rb",
28
+ "unpatched.gemspec"
29
+ ]
30
+
31
+ # dependencies
32
+ s.add_development_dependency "rspec", "~> 2.0"
33
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unpatched
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Konstantin Haase
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-05-31 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: &2153180300 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *2153180300
26
+ description: Convenience library without a single monkey-patch.
27
+ email:
28
+ - konstantin.mailinglists@googlemail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - License
34
+ - README.md
35
+ - Rakefile
36
+ - lib/unpatched.rb
37
+ - lib/unpatched/version.rb
38
+ - spec/unpatched_spec.rb
39
+ - unpatched.gemspec
40
+ has_rdoc: true
41
+ homepage: http://github.com/rkh/unpatched
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 1.6.2
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Convenience library without a single monkey-patch.
65
+ test_files: []