hobo_support 1.3.0.RC
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/CHANGES.txt +5 -0
- data/README.txt +36 -0
- data/Rakefile +16 -0
- data/VERSION +1 -0
- data/hobo_support.gemspec +29 -0
- data/lib/generators/hobo_support/eval_template.rb +14 -0
- data/lib/generators/hobo_support/model.rb +50 -0
- data/lib/generators/hobo_support/thor_shell.rb +40 -0
- data/lib/hobo_support.rb +25 -0
- data/lib/hobo_support/array.rb +40 -0
- data/lib/hobo_support/blankslate.rb +13 -0
- data/lib/hobo_support/command.rb +156 -0
- data/lib/hobo_support/common_tasks.rb +33 -0
- data/lib/hobo_support/enumerable.rb +89 -0
- data/lib/hobo_support/fixes/chronic.rb +21 -0
- data/lib/hobo_support/fixes/module.rb +37 -0
- data/lib/hobo_support/fixes/pp.rb +13 -0
- data/lib/hobo_support/hash.rb +124 -0
- data/lib/hobo_support/implies.rb +15 -0
- data/lib/hobo_support/kernel.rb +16 -0
- data/lib/hobo_support/metaid.rb +28 -0
- data/lib/hobo_support/methodcall.rb +117 -0
- data/lib/hobo_support/methodphitamine.rb +33 -0
- data/lib/hobo_support/module.rb +102 -0
- data/lib/hobo_support/string.rb +34 -0
- data/lib/hobo_support/xss.rb +11 -0
- data/test/hobosupport.rdoctest +75 -0
- data/test/hobosupport/chronic.rdoctest +18 -0
- data/test/hobosupport/enumerable.rdoctest +130 -0
- data/test/hobosupport/hash.rdoctest +123 -0
- data/test/hobosupport/implies.rdoctest +20 -0
- data/test/hobosupport/metaid.rdoctest +59 -0
- data/test/hobosupport/methodphitamine.rdoctest +18 -0
- data/test/hobosupport/module.rdoctest +108 -0
- data/test/hobosupport/xss.rdoctest +44 -0
- metadata +111 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# HoboSupport - implies
|
2
|
+
|
3
|
+
doctest_require: '../../lib/hobo_support'
|
4
|
+
{.hidden}
|
5
|
+
|
6
|
+
The implies operator comes from Eiffel. Often comes in handy in Hobo's model-permission methods.
|
7
|
+
|
8
|
+
## `TrueClass#implies` and `FalseClass#implies`
|
9
|
+
|
10
|
+
>> false.implies true
|
11
|
+
=> true
|
12
|
+
|
13
|
+
>> false.implies false
|
14
|
+
=> true
|
15
|
+
|
16
|
+
>> true.implies true
|
17
|
+
=> true
|
18
|
+
|
19
|
+
>> true.implies false
|
20
|
+
=> false
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# HoboSupport - Metaid
|
2
|
+
|
3
|
+
doctest_require: '../../lib/hobo_support'
|
4
|
+
{.hidden}
|
5
|
+
|
6
|
+
Why the Luck Stiff's essential meta-programming additions to Object. These are probably distributed elsewhere, but they're small enough to throw them in to HoboSupport and remove an external dependency.
|
7
|
+
|
8
|
+
## `Object#metaclass`
|
9
|
+
|
10
|
+
Returns the "metaclass", "eigenclass" or "singleton class" of a given ruby Object
|
11
|
+
|
12
|
+
>> o = Object.new
|
13
|
+
>> def o.foo; ;123; end
|
14
|
+
>> o.foo
|
15
|
+
=> 123
|
16
|
+
>> o.metaclass.method_defined?(:foo)
|
17
|
+
=> true
|
18
|
+
|
19
|
+
## `Object#meta_eval`
|
20
|
+
|
21
|
+
* `object.meta_eval(string)`
|
22
|
+
* `object.meta_eval { block }`
|
23
|
+
|
24
|
+
Evaluates ruby source or a block in the context of the metaclass.
|
25
|
+
|
26
|
+
>> File.meta_eval "alias_method :b, :basename"
|
27
|
+
>> File.b "a/b"
|
28
|
+
=> "b"
|
29
|
+
|
30
|
+
And with a block
|
31
|
+
|
32
|
+
>> File.meta_eval { alias_method :b2, :basename }
|
33
|
+
>> File.b2 "a/b"
|
34
|
+
=> "b"
|
35
|
+
|
36
|
+
## `Object#metaclass_eval`
|
37
|
+
|
38
|
+
* `object.metaclass_eval(string)`
|
39
|
+
* `object.metaclass_eval { block }`
|
40
|
+
|
41
|
+
Like `#meta_eval`, but does a `class_eval` instead of an `instance_eval`
|
42
|
+
|
43
|
+
>> File.metaclass_eval "def b3(path); basename(path); end"
|
44
|
+
>> File.b3 "a/b"
|
45
|
+
=> "b"
|
46
|
+
|
47
|
+
And with a block
|
48
|
+
|
49
|
+
>> File.metaclass_eval { def b4(path); basename(path); end }
|
50
|
+
>> File.b4 "a/b"
|
51
|
+
=> "b"
|
52
|
+
|
53
|
+
|
54
|
+
## `Object#meta_def`
|
55
|
+
|
56
|
+
>> String.meta_def(:backwards_new) { |s| s.reverse }
|
57
|
+
>> String.backwards_new "strange"
|
58
|
+
=> "egnarts"
|
59
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# HoboSupport - Methodphitamine
|
2
|
+
|
3
|
+
doctest_require: '../../lib/hobo_support'
|
4
|
+
{.hidden}
|
5
|
+
|
6
|
+
## `Kernel#it` and `Kernel#its`
|
7
|
+
|
8
|
+
A nice hack from Jay Phillips, christened "Methodphitamine". The low-down is in the [original blog post][1].
|
9
|
+
|
10
|
+
[1]: http://jicksta.com/articles/2007/08/04/the-methodphitamine
|
11
|
+
|
12
|
+
>> (1..10).select &it % 2 == 0
|
13
|
+
=> [2, 4, 6, 8, 10]
|
14
|
+
>> %w(a few short words).map &its.length
|
15
|
+
=> [1, 3, 5, 5]
|
16
|
+
|
17
|
+
Note that `it` and `its` are identical. They just read better in different contexts. Note that methodphitamine is also released directly by Jay (simply `gem install methodphitamine`) but it's small enough that it seemed easier to add it to HoboSupport and avoid an extra dependency. Thanks to Jay.
|
18
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# HoboSupport - Module extensions
|
2
|
+
|
3
|
+
doctest_require: '../../lib/hobo_support'
|
4
|
+
{.hidden}
|
5
|
+
|
6
|
+
## `Module#included_in_class_callbacks`
|
7
|
+
|
8
|
+
Bit involved, this one :-)
|
9
|
+
|
10
|
+
When a module is included in a class, it gets a callback on the `included` method, with the class passed as argument. However, if a module M2 is included in M1, and a class C includes M1, then M2 never gets to know about C. So, for example, M2 could not `alias_method_chain` a class method on C.
|
11
|
+
|
12
|
+
`included_in_class_callbacks` makes it easy to implement a notification from M1 to M2, so that M2 does have full access to the class. All you do is insert a call to `included_in_class_callbacks(base)` as the end of the module's `self.included` method.
|
13
|
+
|
14
|
+
(Note we're using the metaid extensions here too)
|
15
|
+
|
16
|
+
>>
|
17
|
+
module M2
|
18
|
+
def self.included_in_class(klass)
|
19
|
+
klass.metaclass_eval do
|
20
|
+
def name_with_shouting; name_without_shouting.upcase; end
|
21
|
+
alias_method_chain :name, :shouting
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module M1
|
27
|
+
def self.included(base)
|
28
|
+
included_in_class_callbacks(base)
|
29
|
+
end
|
30
|
+
include M2
|
31
|
+
end
|
32
|
+
|
33
|
+
class C
|
34
|
+
def self.name
|
35
|
+
"my name is C"
|
36
|
+
end
|
37
|
+
include M1
|
38
|
+
end
|
39
|
+
|
40
|
+
C.name
|
41
|
+
=> "MY NAME IS C"
|
42
|
+
|
43
|
+
|
44
|
+
## `Module#interiting_cattr_reader`
|
45
|
+
|
46
|
+
Declares a reader for an instance variable on the class. The attribute is looked up on the superclass if not defined on the receiving class. In other words, the superclass defines a default that subclasses can override. The declaration can also give a default, as shown here.
|
47
|
+
|
48
|
+
>>
|
49
|
+
class A
|
50
|
+
inheriting_cattr_reader :nickname => "Andy"
|
51
|
+
end
|
52
|
+
|
53
|
+
class B < A; end
|
54
|
+
|
55
|
+
`B` has the same nickname as its superclass `A`
|
56
|
+
|
57
|
+
>> A.nickname
|
58
|
+
=> "Andy"
|
59
|
+
>> B.nickname
|
60
|
+
=> "Andy"
|
61
|
+
|
62
|
+
Now we change the nickname of `B`. `A` retains it's existing nickname.
|
63
|
+
|
64
|
+
>> class B; @nickname = "Bob"; end
|
65
|
+
>> B.nickname
|
66
|
+
=> "Bob"
|
67
|
+
>> A.nickname
|
68
|
+
=> "Andy"
|
69
|
+
|
70
|
+
|
71
|
+
## `Kernel#classy_module`
|
72
|
+
|
73
|
+
In Ruby we use modules to factor out features that are shared by more than one class. By including the module, a class gets the module's features, just as if they were defined inside the class. This mechanism is very simple if the shared features are all instance methods, but starts to get complicated when we want to share class-level features. For example, to create a module that adds class-methods to the including class, Ruby programmers often use the ClassMethods sub-module idiom:
|
74
|
+
|
75
|
+
>>
|
76
|
+
module M
|
77
|
+
def self.included(base)
|
78
|
+
base.send(:extend, ClassMethods)
|
79
|
+
end
|
80
|
+
|
81
|
+
module ClassMethods
|
82
|
+
def foo; 123; end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class C; include M; end
|
87
|
+
|
88
|
+
>> C.foo
|
89
|
+
=> 123
|
90
|
+
|
91
|
+
It's a shame that such a basic capability isn't more declarative.
|
92
|
+
|
93
|
+
`classy_module` provides a mechanism for creating a module that, when included, will `class_eval` it's entire body (the block passed to `classy_module`). This means we can write shared class features exactly as we would write them if they were inside the class:
|
94
|
+
|
95
|
+
>>
|
96
|
+
MyClassyModule = classy_module do
|
97
|
+
|
98
|
+
def self.foo; 123; end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
>> MyClassyModule.class
|
103
|
+
=> Module
|
104
|
+
>> class C2; include MyClassyModule; end
|
105
|
+
>> C2.foo
|
106
|
+
=> 123
|
107
|
+
|
108
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# HoboSupport - XSS helpers
|
2
|
+
|
3
|
+
>> require 'active_support'
|
4
|
+
>> $:.unshift File.join(File.expand_path(File.dirname(__FILE__)), '../../../hobo_support/lib')
|
5
|
+
>> require 'hobo_support'
|
6
|
+
|
7
|
+
## safe_join
|
8
|
+
|
9
|
+
Version of Array#join that preserves html\_safe:
|
10
|
+
|
11
|
+
>> $,=nil
|
12
|
+
>> ["<a>", "<b>"].safe_join
|
13
|
+
=> "<a><b>"
|
14
|
+
|
15
|
+
>> ["<a>", "<b>"].safe_join.html_safe?
|
16
|
+
=> true
|
17
|
+
|
18
|
+
>> ["<a>".html_safe, "<b>"].safe_join
|
19
|
+
=> "<a><b>"
|
20
|
+
|
21
|
+
>> ["<a>".html_safe, "<b>"].safe_join.html_safe?
|
22
|
+
=> true
|
23
|
+
|
24
|
+
>> ["<a>".html_safe, "<b>".html_safe].safe_join
|
25
|
+
=> "<a><b>"
|
26
|
+
|
27
|
+
>> ["<a>".html_safe, "<b>".html_safe].safe_join.html_safe?
|
28
|
+
=> true
|
29
|
+
|
30
|
+
|
31
|
+
>> ["<a>", "<b>"].safe_join("<br>")
|
32
|
+
=> "<a><br><b>"
|
33
|
+
|
34
|
+
>> ["<a>", "<b>"].safe_join("<br>").html_safe?
|
35
|
+
=> true
|
36
|
+
|
37
|
+
>> ["<a>".html_safe, "<b>".html_safe].safe_join("<br>")
|
38
|
+
=> "<a><br><b>"
|
39
|
+
|
40
|
+
>> ["<a>".html_safe, "<b>".html_safe].safe_join("<br>".html_safe)
|
41
|
+
=> "<a><br><b>"
|
42
|
+
|
43
|
+
|
44
|
+
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hobo_support
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 6
|
5
|
+
version: 1.3.0.RC
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tom Locke
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-10 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rails
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 3.0.0
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubydoctest
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
description: Core Ruby extensions from the Hobo project
|
39
|
+
email: tom@tomlocke.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- CHANGES.txt
|
48
|
+
- README.txt
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- hobo_support.gemspec
|
52
|
+
- lib/generators/hobo_support/eval_template.rb
|
53
|
+
- lib/generators/hobo_support/model.rb
|
54
|
+
- lib/generators/hobo_support/thor_shell.rb
|
55
|
+
- lib/hobo_support.rb
|
56
|
+
- lib/hobo_support/array.rb
|
57
|
+
- lib/hobo_support/blankslate.rb
|
58
|
+
- lib/hobo_support/command.rb
|
59
|
+
- lib/hobo_support/common_tasks.rb
|
60
|
+
- lib/hobo_support/enumerable.rb
|
61
|
+
- lib/hobo_support/fixes/chronic.rb
|
62
|
+
- lib/hobo_support/fixes/module.rb
|
63
|
+
- lib/hobo_support/fixes/pp.rb
|
64
|
+
- lib/hobo_support/hash.rb
|
65
|
+
- lib/hobo_support/implies.rb
|
66
|
+
- lib/hobo_support/kernel.rb
|
67
|
+
- lib/hobo_support/metaid.rb
|
68
|
+
- lib/hobo_support/methodcall.rb
|
69
|
+
- lib/hobo_support/methodphitamine.rb
|
70
|
+
- lib/hobo_support/module.rb
|
71
|
+
- lib/hobo_support/string.rb
|
72
|
+
- lib/hobo_support/xss.rb
|
73
|
+
- test/hobosupport.rdoctest
|
74
|
+
- test/hobosupport/chronic.rdoctest
|
75
|
+
- test/hobosupport/enumerable.rdoctest
|
76
|
+
- test/hobosupport/hash.rdoctest
|
77
|
+
- test/hobosupport/implies.rdoctest
|
78
|
+
- test/hobosupport/metaid.rdoctest
|
79
|
+
- test/hobosupport/methodphitamine.rdoctest
|
80
|
+
- test/hobosupport/module.rdoctest
|
81
|
+
- test/hobosupport/xss.rdoctest
|
82
|
+
has_rdoc: true
|
83
|
+
homepage: http://hobocentral.net
|
84
|
+
licenses: []
|
85
|
+
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options:
|
88
|
+
- --charset=UTF-8
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: "0"
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.3.6
|
103
|
+
requirements: []
|
104
|
+
|
105
|
+
rubyforge_project: hobo
|
106
|
+
rubygems_version: 1.5.0
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: Core Ruby extensions from the Hobo project
|
110
|
+
test_files: []
|
111
|
+
|