ruby_ext 0.5.9 → 0.5.10

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