rmtools 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -27,6 +27,18 @@ It's still randomly documented since it's just my working tool.
27
27
 
28
28
  ### CHANGES
29
29
 
30
+ ##### Version 2.1.0
31
+
32
+ * Array
33
+ * For ruby >= 1.9.3 #uniq_by[!] is alias of #uniq[!] itself, since it’s native implementation appears to be ~1.4x faster
34
+ * A bit better english singularizer for iterators
35
+ * Added #partition_by iterator
36
+ * Enumerable
37
+ * Generalized faster set operations for Array and Set (see rmtools/enumerable/set_ops)
38
+ * Boosted &-operator
39
+ * ActiveRecord::Base
40
+ * Added #update_attributes?
41
+
30
42
  ##### Version 2.0.0
31
43
 
32
44
  * Array Meta-iterators
data/ext/rmtools.cpp CHANGED
@@ -199,6 +199,9 @@ static VALUE rb_str_conjunction(VALUE self, VALUE str)
199
199
  */
200
200
  static VALUE rb_ary_uniq_by_bang(VALUE ary)
201
201
  {
202
+ long len = RARRAY_LEN(ary);
203
+ if (len < 2)
204
+ return Qnil;
202
205
  if (!rb_block_given_p())
203
206
  return rb_ary_new4(RARRAY_LEN(ary), RARRAY_PTR(ary));
204
207
  VALUE hash, res_hash, res, el;
@@ -206,7 +209,7 @@ static VALUE rb_ary_uniq_by_bang(VALUE ary)
206
209
 
207
210
  hash = rb_hash_new();
208
211
  res_hash = rb_hash_new();
209
- for (i=j=0; i<RARRAY_LEN(ary); i++) {
212
+ for (i=j=0; i<len; i++) {
210
213
  // We store an element itself and so we won't calculate function of it
211
214
  // other time we'll find it in source. Ruby store function is very fast,
212
215
  // so we can neglect its runtime even if source array is allready uniq
@@ -220,7 +223,7 @@ static VALUE rb_ary_uniq_by_bang(VALUE ary)
220
223
  }
221
224
  ARY_SET_LEN(ary, j);
222
225
 
223
- return ary;
226
+ return j == len ? Qnil : ary;
224
227
  }
225
228
 
226
229
  /*
@@ -228,7 +231,9 @@ static VALUE rb_ary_uniq_by_bang(VALUE ary)
228
231
  */
229
232
  static VALUE rb_ary_uniq_by(VALUE ary)
230
233
  {
231
- return rb_ary_uniq_by_bang(rb_ary_dup(ary));
234
+ VALUE ary_dup = rb_ary_dup(ary);
235
+ rb_ary_uniq_by_bang(ary_dup);
236
+ return ary_dup;
232
237
  }
233
238
 
234
239
  /*
@@ -152,7 +152,7 @@ module ActiveRecord
152
152
  id ?
153
153
  delete_with_id :
154
154
  field ?
155
- self.class.delete_all(field => __send__(field)) :
155
+ self.class.delete_all(field => self[field]) :
156
156
  self.class.delete_all(attributes)
157
157
  end
158
158
 
@@ -160,7 +160,7 @@ module ActiveRecord
160
160
  id ?
161
161
  destroy_with_id :
162
162
  field ?
163
- self.class.destroy_all(field => __send__(field)) :
163
+ self.class.destroy_all(field => self[field]) :
164
164
  self.class.destroy_all(attributes)
165
165
  end
166
166
 
@@ -171,6 +171,11 @@ module ActiveRecord
171
171
  def with_same(attr)
172
172
  self.class.where(attr => self[attr])
173
173
  end
174
+
175
+ def update_attributes?(hash)
176
+ hash.each {|k, v| self[k] = v}
177
+ changed? && save
178
+ end
174
179
 
175
180
  end
176
181
 
@@ -1,71 +1,10 @@
1
1
  # encoding: utf-8
2
2
  require 'active_support/core_ext/array'
3
3
  RMTools::require 'functional/fold'
4
+ RMTools::require 'enumerable/set_ops'
4
5
 
5
6
  class Array
6
- # builtin methods overwrite
7
- # why should we do zillions of cycles just for ensure A | [] = A - [] = A or A & [] = []
8
- # though - and & should be improved within C-extension to break loop when no items have lost in self
9
- alias union |
10
- alias coallition +
11
- alias subtraction -
12
- alias intersection &
13
- private :union, :coallition, :subtraction, :intersection
14
-
15
- def |(ary)
16
- if empty?
17
- ary.uniq
18
- elsif ary.respond_to? :empty? and ary.empty?
19
- dup
20
- else union(ary)
21
- end
22
- end
23
-
24
- def +(ary)
25
- if empty?
26
- if ary.respond_to? :empty? and ary.empty?
27
- []
28
- else ary.dup
29
- end
30
- elsif ary.respond_to? :empty? and ary.empty?
31
- dup
32
- else coallition(ary)
33
- end
34
- end
35
-
36
- def -(ary)
37
- if empty?
38
- []
39
- elsif ary.respond_to? :empty? and ary.empty?
40
- dup
41
- else subtraction(ary)
42
- end
43
- end
44
-
45
- def &(ary)
46
- if empty? or (ary.respond_to? :empty? and ary.empty?)
47
- []
48
- else intersection(ary)
49
- end
50
- end
51
-
52
- def ^(ary)
53
- if empty? or (ary.respond_to? :empty? and ary.empty?)
54
- [dup, ary.dup]
55
- elsif self == ary
56
- [[], []]
57
- else
58
- common = intersection ary
59
- [self - common, ary - common]
60
- end
61
- end
62
-
63
- alias diff ^
64
-
65
- def intersects?(ary)
66
- (self & ary).any?
67
- end
68
- alias :x? :intersects?
7
+ include RMTools::SmarterSetOps
69
8
 
70
9
  # arithmetics
71
10
  def avg
@@ -184,6 +123,14 @@ class Array
184
123
  reject {|e| e.__send__(key) == value}
185
124
  end
186
125
 
126
+ def partition_by(key, value)
127
+ partition {|e| e.__send__(key) == value}
128
+ end
129
+
130
+ if RUBY_VERSION >= '1.9.3'
131
+ alias :uniq_by :uniq
132
+ alias :uniq_by! :uniq!
133
+ end
187
134
 
188
135
  # uniqs
189
136
  def uniq?
@@ -15,6 +15,14 @@ class Array
15
15
  mattr_reader :iterators_names, :iterators_pattern
16
16
  @@iterators_names = []
17
17
 
18
+ private
19
+ def simple_inplace_singularize!(noun)
20
+ noun.sub!(/(ss|[sc]h|[xo])es([=!?]?)$/, '\1\2') or
21
+ noun.sub!(/ies([=!?]?)$/, 'y\1') or
22
+ noun.sub!(/ves([=!?]?)$/, 'f\1') or
23
+ noun.sub!(/s([=!?]?)$/, '\1')
24
+ end
25
+
18
26
  class << self
19
27
 
20
28
  def add_iterator_name(name_or_list)
@@ -65,7 +73,7 @@ class Array
65
73
 
66
74
  return case iterator
67
75
  when :sum, :sort_along_by; __send__(iterator, args.shift) {|i| i.__send__ meth, *args, &block}
68
- when :find_by, :select_by, :reject_by; __send__(iterator, meth, *args)
76
+ when :find_by, :select_by, :reject_by, :partition_by; __send__(iterator, meth, *args)
69
77
  else __send__(iterator) {|i| i.__send__ meth, *args, &block}
70
78
  end
71
79
  rescue NoMethodError => e
@@ -73,7 +81,7 @@ class Array
73
81
  raise e
74
82
  end
75
83
 
76
- elsif meth.sub!(/sses([=!?]?)$/, 'ss\1') or meth.sub!(/ies([=!?]?)$/, 'y\1') or meth.sub!(/s([=!?]?)$/, '\1')
84
+ elsif simple_inplace_singularize!(meth)
77
85
  assignment = meth =~ /=$/
78
86
  meth = meth.to_sym
79
87
 
@@ -100,7 +108,7 @@ class Array
100
108
 
101
109
  end # << self
102
110
 
103
- add_iterator_name(instance_methods.grep(/_by$/)+%w{every no select reject partition find_all find sum foldr foldl fold count rand_by})
111
+ add_iterator_name(instance_methods.grep(/_by$/)+%w{every no which select reject partition find_all find sum foldr foldl fold count rand_by})
104
112
 
105
113
  # Benchmark 2:
106
114
  #
@@ -161,7 +169,7 @@ class Array
161
169
  end
162
170
  end
163
171
 
164
- elsif meth.sub!(/sses([=!?]?)$/, 'ss\1') or meth.sub!(/ies([=!?]?)$/, 'y\1') or meth.sub!(/s([=!?]?)$/, '\1')
172
+ elsif simple_inplace_singularize!(meth)
165
173
  assignment = meth =~ /=$/
166
174
  meth = meth.to_sym
167
175
 
@@ -236,7 +244,7 @@ class Array
236
244
  err.message << " (`#{method}' interpreted as decorator-function `#{meth}')"
237
245
  raise err
238
246
  end}
239
- when :find_by, :rfind_by,:select_by, :reject_by
247
+ when :find_by, :rfind_by, :select_by, :reject_by, :partition_by
240
248
  Array.class_eval %{
241
249
  def #{method}(val)
242
250
  # select_by_count(max_count) =>
@@ -258,7 +266,7 @@ class Array
258
266
  end}
259
267
  end
260
268
 
261
- elsif meth.sub!(/sses([=!?]?)$/, 'ss\1') or meth.sub!(/ies([=!?]?)$/, 'y\1') or meth.sub!(/s([=!?]?)$/, '\1')
269
+ elsif simple_inplace_singularize!(meth)
262
270
  assignment = meth =~ /=$/
263
271
  meth = meth.to_sym
264
272
 
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+ require 'set'
3
+ RMTools::require 'enumerable/set_ops'
4
+
5
+ class Set
6
+ alias :uniq :dup
7
+ include RMTools::SmarterSetOps
8
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+ module RMTools
3
+
4
+ # Builtin methods overwrite.
5
+ # Why should we do zillions of cycles just for ensure
6
+ # `A | [] = A - [] = A or A & [] = []`
7
+ # ?
8
+ # Though #- and #& should be improved within C-extension to break loop when no items have had lost in self (Or not? Don't remember what I had on my mind while I've being writing this)
9
+ module SmarterSetOps
10
+
11
+ def self.included(acceptor)
12
+ acceptor.class_eval {
13
+ alias :union :|
14
+ alias :coallition :+
15
+ alias :subtraction :-
16
+ alias :intersection :&
17
+ protected :union, :coallition, :subtraction, :intersection
18
+
19
+ def |(ary)
20
+ return ary.uniq if empty?
21
+ return uniq if ary.respond_to? :empty? and ary.empty?
22
+
23
+ union ary
24
+ end
25
+
26
+ def +(ary)
27
+ if empty?
28
+ return [] if ary.respond_to? :empty? and ary.empty?
29
+ ary.dup
30
+ end
31
+ return dup if ary.respond_to? :empty? and ary.empty?
32
+
33
+ coallition ary
34
+ end
35
+
36
+ def -(ary)
37
+ return [] if empty?
38
+ return dup if ary.respond_to? :empty? and ary.empty?
39
+
40
+ subtraction ary
41
+ end
42
+
43
+ def &(ary)
44
+ return [] if empty? or (ary.respond_to? :empty? and ary.empty?)
45
+ return ary.intersection self if size < ary.size
46
+
47
+ intersection ary
48
+ end
49
+
50
+ def ^(ary)
51
+ return [dup, ary.dup] if empty? or (ary.respond_to? :empty? and ary.empty?)
52
+ return [[], []] if self == ary
53
+
54
+ common = intersection ary
55
+ [self - common, ary - common]
56
+ end
57
+
58
+ alias diff ^
59
+
60
+ def intersects?(ary)
61
+ (self & ary).any?
62
+ end
63
+ alias :x? :intersects?
64
+ }
65
+ super
66
+ end
67
+
68
+ end
69
+ end
@@ -1,3 +1,3 @@
1
1
  module RMTools
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rmtools
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-29 00:00:00.000000000 Z
12
+ date: 2013-06-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -124,6 +124,8 @@ files:
124
124
  - lib/rmtools/enumerable/hash.rb
125
125
  - lib/rmtools/enumerable/object_space.rb
126
126
  - lib/rmtools/enumerable/range.rb
127
+ - lib/rmtools/enumerable/set.rb
128
+ - lib/rmtools/enumerable/set_ops.rb
127
129
  - lib/rmtools/enumerable/traversal.rb
128
130
  - lib/rmtools/fs.rb
129
131
  - lib/rmtools/fs/dir.rb