ruby_ext 0.5.9 → 0.5.10

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.
Files changed (40) hide show
  1. data/Rakefile +2 -3
  2. data/lib/rake_ext/project.rb +1 -2
  3. data/lib/rspec_ext.rb +37 -35
  4. data/lib/rspec_ext/nokogiri.rb +26 -0
  5. data/lib/ruby_ext/core.rb +3 -5
  6. data/lib/ruby_ext/core/array.rb +1 -1
  7. data/lib/ruby_ext/core/basic_object.rb +1 -1
  8. data/lib/ruby_ext/core/deep_clone.rb +3 -10
  9. data/lib/ruby_ext/core/enumerable.rb +3 -3
  10. data/lib/ruby_ext/core/false_class.rb +1 -1
  11. data/lib/ruby_ext/core/hash.rb +23 -7
  12. data/lib/ruby_ext/core/module.rb +37 -57
  13. data/lib/ruby_ext/core/multiple_inheritance.rb +3 -3
  14. data/lib/ruby_ext/core/must.rb +0 -16
  15. data/lib/ruby_ext/core/nil_class.rb +5 -0
  16. data/lib/ruby_ext/core/object.rb +7 -7
  17. data/lib/ruby_ext/core/open_object.rb +7 -25
  18. data/lib/ruby_ext/core/string.rb +1 -6
  19. data/lib/ruby_ext/more.rb +2 -0
  20. data/lib/ruby_ext/more/callbacks.rb +37 -0
  21. data/lib/ruby_ext/more/declarative_cache.rb +45 -56
  22. data/lib/yaml_fix.rb +9 -0
  23. data/spec/core/array_spec.rb +1 -1
  24. data/spec/core/deep_clone_spec.rb +4 -2
  25. data/spec/core/enumerable.rb +1 -1
  26. data/spec/core/module_spec.rb +65 -107
  27. data/spec/core/multiple_inheritance_spec.rb +4 -4
  28. data/spec/core/must_spec.rb +1 -1
  29. data/spec/core/object_spec.rb +6 -6
  30. data/spec/core/open_object_spec.rb +1 -1
  31. data/spec/more/callbacks_spec.rb +90 -20
  32. data/spec/more/declarative_cache_spec.rb +96 -75
  33. data/spec/more/observable_spec.rb +10 -34
  34. data/spec/more/open_constructor_spec.rb +14 -11
  35. data/spec/spec_helper.rb +2 -0
  36. metadata +5 -6
  37. data/lib/rspec_ext/xhtml.rb +0 -48
  38. data/lib/ruby_ext/fixes.rb +0 -6
  39. data/spec/core/spec_helper.rb +0 -2
  40. data/spec/more/spec_helper.rb +0 -2
data/Rakefile CHANGED
@@ -3,11 +3,10 @@ $LOAD_PATH << lib_dir unless $LOAD_PATH.include? lib_dir
3
3
 
4
4
  require 'rake_ext'
5
5
 
6
- project(
6
+ project \
7
7
  name: "ruby_ext",
8
8
  gem: true,
9
9
  summary: "Ruby Extensions",
10
10
 
11
11
  author: "Alexey Petrushin",
12
- homepage: "http://github.com/alexeypetrushin/ruby_ext"
13
- )
12
+ homepage: "http://github.com/alexeypetrushin/ruby_ext"
@@ -7,7 +7,7 @@ YAML::ENGINE.yamler = 'syck'
7
7
  #
8
8
  # Helper for releasing gem, add following code to Your Rakefile:
9
9
  #
10
- # project(
10
+ # project \
11
11
  # name: "fake_gem",
12
12
  # gem: true,
13
13
  # summary: "Makes any directory looks like Ruby Gem",
@@ -18,7 +18,6 @@ YAML::ENGINE.yamler = 'syck'
18
18
  #
19
19
  # author: "Alexey Petrushin",
20
20
  # homepage: "http://github.com/alexeypetrushin/fake_gem"
21
- # )
22
21
  #
23
22
  # use "rake gem" to release gem
24
23
  #
data/lib/rspec_ext.rb CHANGED
@@ -12,10 +12,6 @@
12
12
  #
13
13
  # CLASS_LOADER_GENERATE_TMP_FILES = true
14
14
 
15
-
16
- #
17
- # RSpec
18
- #
19
15
  require 'rspec'
20
16
  require 'fileutils'
21
17
 
@@ -40,9 +36,17 @@ rspec do
40
36
  end
41
37
 
42
38
  rspec do
39
+ def self.before_all &block
40
+ before :all, &block
41
+ end
42
+
43
+ def self.after_all &block
44
+ after :all, &block
45
+ end
46
+
43
47
  def self.with_load_path *paths
44
- before(:all){paths.each{|path| $LOAD_PATH << path}}
45
- after(:all){paths.each{|path| $LOAD_PATH.delete path}}
48
+ before_all{paths.each{|path| $LOAD_PATH << path}}
49
+ after_all{paths.each{|path| $LOAD_PATH.delete path}}
46
50
  end
47
51
 
48
52
  def with_load_path *paths, &b
@@ -76,16 +80,10 @@ rspec do
76
80
  end
77
81
 
78
82
  def self.with_spec_dir dir
79
- before(:all){@spec_dir = dir}
80
- after(:all){@spec_dir = nil}
83
+ before_all{@spec_dir = dir}
84
+ after_all{@spec_dir = nil}
81
85
  end
82
86
 
83
- # def self.with_spec_dir
84
-
85
- # def self.spec_dir dir = nil
86
- # @spec_dir ||= calculate_spec_dir_for_current_caller
87
- # end
88
-
89
87
  def self.spec_dir
90
88
  self.calculate_default_spec_dir || raise(":spec_dir not defined!")
91
89
  end
@@ -106,35 +104,39 @@ rspec do
106
104
  args = args.first if args.size == 1 and args.first.is_a?(Array)
107
105
  args.each{|c| Object.send :remove_const, c if Object.const_defined? c}
108
106
  end
109
-
110
- # def spec_tmp_dir
111
- # $spec_tmp_dir || raise("you should call :with_tmp_spec_dir to be able to use :spec_tmp_dir!")
112
- # end
113
107
  end
114
108
 
115
109
 
116
- #
117
- # dirname, parent_dirname
118
- #
119
110
  class String
120
111
  unless method_defined? :dirname
121
112
  def dirname
122
113
  File.expand_path(File.dirname(self))
123
114
  end
124
115
  end
125
- end
126
116
 
117
+ def to_xhtml css = nil
118
+ require 'rspec_ext/nokogiri'
119
+
120
+ node = Nokogiri::HTML(self)
121
+ unless css
122
+ node
123
+ else
124
+ nodes = node.css(css)
125
+ raise "Elements for '#{css}' CSS query not found!" if nodes.size < 1
126
+ raise "Found more than one elment for '#{css}' CSS query!" if nodes.size > 1
127
+ nodes.first
128
+ end
129
+ end
130
+ end
127
131
 
128
- #
129
- # instance_stub
130
- #
131
- # class Class
132
- # def instance_stub! &block
133
- # new_method = method(:new)
134
- # stub!(:new).and_return do |*args|
135
- # instance = new_method.call(*args)
136
- # block.call instance
137
- # instance
138
- # end
139
- # end
140
- # end
132
+ # Stubbing every instances of class.
133
+ class Class
134
+ def instance_stub! &block
135
+ new_method = method :new
136
+ stub! :new do |*args|
137
+ instance = new_method.call *args
138
+ block.call instance
139
+ instance
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,26 @@
1
+ # Helpers to express expectation about html nodes.
2
+ require 'nokogiri'
3
+
4
+ class RSpec::FuzzyHash < Hash
5
+ def == o
6
+ return true if super
7
+
8
+ if o.respond_to? :each
9
+ o.each do |k, v|
10
+ return false if (self[k.to_sym] || self[k.to_s]) != v
11
+ end
12
+ return true
13
+ end
14
+
15
+ false
16
+ end
17
+ end
18
+
19
+ ::Nokogiri::XML::Node.class_eval do
20
+ def to_fuzzy_hash
21
+ h = RSpec::FuzzyHash.new
22
+ attributes.each{|n, v| h[n] = v.value}
23
+ h[:content] = content
24
+ h
25
+ end
26
+ end
data/lib/ruby_ext/core.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  raise 'ruby 1.9.2 or higher required!' if RUBY_VERSION < '1.9.2'
2
2
 
3
- require 'ruby_ext/fixes'
4
-
5
- autoload :OpenObject, 'ruby_ext/core/open_object'
6
-
7
3
  %w(
8
4
  basic_object
9
5
  nil_class
@@ -19,4 +15,6 @@ autoload :OpenObject, 'ruby_ext/core/open_object'
19
15
  deep_clone
20
16
  time
21
17
  multiple_inheritance
22
- ).each{|f| require "ruby_ext/core/#{f}"}
18
+ ).each{|f| require "ruby_ext/core/#{f}"}
19
+
20
+ autoload :OpenObject, 'ruby_ext/core/open_object'
@@ -1,4 +1,4 @@
1
- class Array
1
+ Array.class_eval do
2
2
  def sfilter *filters
3
3
  filters = filters.first if filters.size == 1 and filters.first.is_a?(Array)
4
4
  filters.collect!{|o| o.is_a?(Regexp) ? o : /#{Regexp.escape o}/}
@@ -1,4 +1,4 @@
1
- class BasicObject
1
+ BasicObject.class_eval do
2
2
  protected :==, :equal?, :!, :!=
3
3
 
4
4
  protected
@@ -1,4 +1,6 @@
1
- class Object
1
+ require 'date'
2
+
3
+ Object.class_eval do
2
4
  def deep_clone
3
5
  clone = self.clone
4
6
  instance_variables.each do |name|
@@ -18,15 +20,6 @@ Hash.class_eval do
18
20
  end
19
21
  end
20
22
 
21
- OpenObject.class_eval do
22
- def deep_clone
23
- clone = super
24
- clone.clear
25
- each{|k, v| clone[k.deep_clone] = v.deep_clone}
26
- clone
27
- end
28
- end
29
-
30
23
  Struct.class_eval do
31
24
  def deep_clone
32
25
  clone = super
@@ -1,5 +1,5 @@
1
- module Enumerable
2
- class EveryProxy < BasicObject
1
+ Enumerable.class_eval do
2
+ class ::Enumerable::EveryProxy < BasicObject
3
3
  def initialize enumerable
4
4
  @enumerable = enumerable
5
5
  end
@@ -12,6 +12,6 @@ module Enumerable
12
12
  end
13
13
 
14
14
  def every
15
- EveryProxy.new(self)
15
+ ::Enumerable::EveryProxy.new self
16
16
  end
17
17
  end
@@ -1,3 +1,3 @@
1
- class FalseClass
1
+ FalseClass.class_eval do
2
2
  def blank?; true end
3
3
  end
@@ -1,4 +1,4 @@
1
- class Hash
1
+ Hash.class_eval do
2
2
  def subset *keys, &block
3
3
  keys = keys.first if keys.first.is_a? Array
4
4
  h = {}
@@ -27,14 +27,30 @@ class Hash
27
27
  merge!( other_hash ){|key,left,right| left }
28
28
  end
29
29
 
30
- # Haml relies on :inspect default format, can't use it.
31
- #
32
- # def inspect
33
- # "{" + collect{|k, v| "#{k}: #{v}"}.join(', ') + "}"
34
- # end
35
- # alias_method :to_s, :inspect
30
+ # Haml relies on :inspect default format and it brokes haml, but I prefer new hash notation,
31
+ # disable it if You use Haml.
32
+ unless $dont_extend_hash_inspect
33
+ def inspect
34
+ "{" + collect{|k, v| "#{k}: #{v}"}.join(', ') + "}"
35
+ end
36
+ alias_method :to_s, :inspect
37
+ end
36
38
 
37
39
  alias_method :blank?, :empty?
38
40
 
39
41
  alias_method :to_h, :to_hash
42
+
43
+ # OpenObject.
44
+
45
+ def to_openobject deep = false
46
+ OpenObject.initialize_from self, deep
47
+ end
48
+ alias_method :to_oo, :to_openobject
49
+
50
+ alias_method :eql_without_oo, :==
51
+ def == other
52
+ true if self.equal? other
53
+ other == self if other.is_a? OpenObject
54
+ eql_without_oo other
55
+ end
40
56
  end
@@ -1,5 +1,3 @@
1
- require 'set'
2
-
3
1
  Module.class_eval do
4
2
  def alias name = nil
5
3
  if name
@@ -16,48 +14,26 @@ Module.class_eval do
16
14
  end
17
15
 
18
16
  def namespace
19
- if @module_namespace_defined
17
+ if @module_namespace_cached
20
18
  @module_namespace
21
19
  else
22
- @module_namespace_defined = true
20
+ @module_namespace_cached = true
23
21
  @module_namespace = Module.namespace_for name
24
22
  end
25
23
  end
26
24
 
27
- def each_namespace &block
28
- current = namespace
29
- while current do
30
- block.call current
31
- current = current.namespace
32
- end
33
- end
34
-
35
- def each_ancestor include_standard = false, &block
36
- if include_standard
37
- ancestors.each{|a| block.call a unless a == self}
38
- else
39
- exclude = [self, Object, Kernel]
40
- ancestors.each do |a|
41
- block.call a unless exclude.include? a
42
- end
43
- end
44
- end
45
-
46
- def self_ancestors_and_namespaces &b
47
- b.call self
48
- each_ancestor &b
49
- each_namespace &b
50
- end
51
-
52
- # TODO cache it?
53
25
  def self.namespace_for class_name
54
- list = class_name.split("::")
55
- if list.size > 1
56
- list.pop
57
- return eval(list.join("::"), TOPLEVEL_BINDING, __FILE__, __LINE__)
58
- else
59
- return nil
26
+ @namespace_for_cache ||= {}
27
+ unless @namespace_for_cache.include? class_name
28
+ list = class_name.split("::")
29
+ @namespace_for_cache[class_name] = if list.size > 1
30
+ list.pop
31
+ eval list.join("::"), TOPLEVEL_BINDING, __FILE__, __LINE__
32
+ else
33
+ nil
34
+ end
60
35
  end
36
+ @namespace_for_cache[class_name]
61
37
  end
62
38
 
63
39
  def inheritable_accessor attribute_name, default_value
@@ -90,42 +66,46 @@ Module.class_eval do
90
66
  end
91
67
  end
92
68
 
93
- raise "Internal error, it shouldn't be loaded twice!" if defined? ESCAPE_METHOD_SYMBOLS # some tricky error when runing spec with rake.
94
- ESCAPE_METHOD_SYMBOLS = [
95
- ['==', 'assign'],
96
- ['>', 'gt'],
97
- ['<', 'lt'],
98
- ['>=', 'gte'],
99
- ['<=', 'lte'],
100
- ['?', 'qst'],
101
- ['!', 'imp'],
102
- ['<=>', 'lorg'],
103
- ['*', 'mp'],
104
- ['+', 'add'],
105
- ['-', 'sub'],
106
- ['=', 'assign'],
107
- ['**', 'pw'],
108
- ['=~', 'sim'],
109
- ['[]', 'sb'],
110
- ]
69
+ METHOD_ESCAPE_SYMBOLS = {
70
+ '==' => 'assign',
71
+ '>' => 'gt',
72
+ '<' => 'lt',
73
+ '>=' => 'gte',
74
+ '<=' => 'lte',
75
+ '?' => 'qst',
76
+ '!' => 'imp',
77
+ '<=>' => 'lorg',
78
+ '*' => 'mp',
79
+ '+' => 'add',
80
+ '-' => 'sub',
81
+ '=' => 'assign',
82
+ '**' => 'pw',
83
+ '=~' => 'sim',
84
+ '[]' => 'sb'
85
+ }
111
86
 
112
87
  def escape_method method
113
88
  m = method.to_s.clone
114
- ESCAPE_METHOD_SYMBOLS.each{|from, to| m.gsub! from, to}
89
+ METHOD_ESCAPE_SYMBOLS.each{|from, to| m.gsub! from, to}
115
90
  raise "Invalid method name '#{method}'!" unless m =~ /^[_a-zA-Z0-9]+$/
116
91
  m.to_sym
117
92
  end
118
93
 
119
94
  def attr_required *attrs
120
95
  attrs.each do |attr|
121
- define_method(attr){instance_variable_get(:"@#{attr}") || raise("attribute :#{attr} not defined on #{self}!")}
96
+ iv_name = :"@#{attr}"
97
+ define_method attr do
98
+ variable = instance_variable_get iv_name
99
+ raise "attribute :#{attr} not defined on #{self}!" if iv_name == nil
100
+ variable
101
+ end
122
102
  end
123
103
  end
124
104
 
125
105
  public :include, :define_method
126
106
 
127
107
  # Copied from rails.
128
- def delegate(*methods)
108
+ def delegate *methods
129
109
  options = methods.pop
130
110
  unless options.is_a?(Hash) && to = options[:to]
131
111
  raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
@@ -16,16 +16,16 @@
16
16
  #
17
17
  class Module
18
18
  def directly_included_by
19
- @directly_included_by ||= Set.new
19
+ @directly_included_by ||= {}
20
20
  end
21
21
 
22
22
  def include2 mod
23
23
  # unless mod.directly_included_by.include? self
24
- mod.directly_included_by.add self
24
+ mod.directly_included_by[self] = true
25
25
  # end
26
26
 
27
27
  include mod
28
- directly_included_by.each do |child|
28
+ directly_included_by.each do |child, v|
29
29
  child.include2 self
30
30
  end
31
31
  end