rufus-doric 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.txt CHANGED
@@ -2,6 +2,14 @@
2
2
  = rufus-doric CHANGELOG.txt
3
3
 
4
4
 
5
+ == rufus-doric - 0.1.7 released 2010/04/16
6
+
7
+ - view_by 'tysec', "emit(doc.type + '__' + doc.security_level, null);"
8
+ - model : view_by [ :x, :y ] => view_by_x_and_y
9
+ - neutralize_id(i) now turns dots to underscores as well
10
+ - model : default _id generator (when no _id_field specified)
11
+
12
+
5
13
  == rufus-doric - 0.1.6 released 2010/04/14
6
14
 
7
15
  - property :sold, :default => false was not working. Fixed.
data/TODO.txt CHANGED
@@ -3,12 +3,15 @@
3
3
  [o] model : validation
4
4
  [o] destroy/delete
5
5
  [o] fix Amedeo's infinite loop (model.rb l438)
6
+ [o] all, by : limit and skip (pagination)
7
+ [o] pagination for everybody in Model (DRY)
8
+ [o] eventually : pagination for the text index
6
9
 
7
10
  [x] lsof check (jig / patron)
8
11
 
9
- [ ] all, by : limit and skip (pagination)
10
-
11
12
  [ ] eventually : cache the text index
12
- [ ] eventually : pagination for the text index
13
- [ ] pagination for everybody in Model (DRY)
13
+
14
+ [ ] view_by 'name' do
15
+ %{ emit(doc.nada) }
16
+ end
14
17
 
@@ -103,16 +103,28 @@ module Doric
103
103
  @_id_field
104
104
  end
105
105
 
106
- def self.view_by (key)
106
+ def self.view_by (key, func=nil)
107
107
 
108
- @keys ||= []
109
- @keys << key.to_s
108
+ if func
110
109
 
111
- instance_eval %{
112
- def by_#{key} (val, opts={})
113
- by('#{key}', val, opts)
114
- end
115
- }
110
+ k = { key => func }
111
+
112
+ instance_eval %{
113
+ def by_#{key} (val, opts={})
114
+ by(#{k.inspect}, val, opts)
115
+ end
116
+ }
117
+
118
+ else
119
+
120
+ skey = key.is_a?(Array) ? key.join('_and_') : key
121
+
122
+ instance_eval %{
123
+ def by_#{skey} (val, opts={})
124
+ by(#{key.inspect}, val, opts)
125
+ end
126
+ }
127
+ end
116
128
  end
117
129
 
118
130
  def self.text_index (*keys)
@@ -164,15 +176,22 @@ module Doric
164
176
 
165
177
  raise ActiveRecord::RecordInvalid.new(self) unless valid?
166
178
 
167
- if @h['_id'].nil? && self.class._id_field
179
+ if @h['_id'].nil?
180
+
181
+ if self.class._id_field
182
+
183
+ @h['_id'] = if self.class._id_field.is_a?(String)
184
+ self.send(self.class._id_field)
185
+ else
186
+ self.instance_eval(&self.class._id_field)
187
+ end
168
188
 
169
- i = if self.class._id_field.is_a?(String)
170
- self.send(self.class._id_field)
171
189
  else
172
- self.instance_eval &self.class._id_field
190
+
191
+ @h['_id'] = generate_id
173
192
  end
174
193
 
175
- @h['_id'] = Rufus::Doric.neutralize_id(i)
194
+ @h['_id'] = Rufus::Doric.neutralize_id(@h['_id'])
176
195
  end
177
196
 
178
197
  raise ActiveRecord::RecordInvalid.new(self) if @h['_id'].nil?
@@ -402,6 +421,27 @@ module Doric
402
421
 
403
422
  protected
404
423
 
424
+ # When there is no _id_field specified, this id generation routine
425
+ # is used.
426
+ #
427
+ def generate_id
428
+
429
+ s = [
430
+ $$, Thread.current.object_id, self.object_id, Time.now.to_f.to_s
431
+ ].join('_')
432
+
433
+ "#{self.class.doric_type}__#{s}"
434
+ end
435
+
436
+ def self.func (body)
437
+ %{
438
+ function (doc) {
439
+ if (doc.doric_type != '#{@doric_type}') return;
440
+ #{body}
441
+ }
442
+ }
443
+ end
444
+
405
445
  def self.put_design_doc (key=nil)
406
446
 
407
447
  # the 'all' view
@@ -423,32 +463,42 @@ module Doric
423
463
  # done on the client side
424
464
 
425
465
  ddoc['views']['text_index'] = {
426
- 'map' => %{
427
- function(doc) {
428
- if (doc.doric_type == '#{@doric_type}') {
429
- var keys = #{Rufus::Json.encode(@text_index)};
430
- for (var key in doc) {
431
- if (keys.indexOf(key) < 0) continue;
432
- if (doc[key] == undefined) continue;
433
- var words = doc[key].split(/[\s,;\.]/);
434
- words.forEach(function (word) {
435
- if (word != '') emit(word, null);
436
- });
437
- }
438
- }
466
+ 'map' => func(%{
467
+ var keys = #{Rufus::Json.encode(@text_index)};
468
+ for (var key in doc) {
469
+ if (keys.indexOf(key) < 0) continue;
470
+ if (doc[key] == undefined) continue;
471
+ var words = doc[key].split(/[\s,;\.]/);
472
+ words.forEach(function (word) {
473
+ if (word != '') emit(word, null);
474
+ });
439
475
  }
440
- }
476
+ })
477
+ }
478
+
479
+ elsif key.is_a?(Hash)
480
+
481
+ ddoc['views']["by_#{key.keys.first}"] = {
482
+ 'map' => func(key.values.first)
483
+ }
484
+
485
+ elsif key.is_a?(Array)
486
+
487
+ skey = key.join('_and_')
488
+ keys = key.collect { |k| "doc['#{k}']" }.join(', ')
489
+
490
+ ddoc['views']["by_#{skey}"] = {
491
+ 'map' => func(%{
492
+ emit([#{keys}], null);
493
+ })
441
494
  }
495
+
442
496
  else
443
497
 
444
498
  ddoc['views']["by_#{key}"] = {
445
- 'map' => %{
446
- function(doc) {
447
- if (doc.doric_type == '#{@doric_type}') {
448
- emit(doc['#{key}'], null);
449
- }
450
- }
451
- }
499
+ 'map' => func(%{
500
+ emit(doc['#{key}'], null);
501
+ })
452
502
  }
453
503
  end
454
504
 
@@ -488,7 +538,7 @@ module Doric
488
538
 
489
539
  qs = [ 'include_docs=true' ]
490
540
 
491
- if val.is_a?(Array)
541
+ if val.is_a?(Array) && ( ! key.is_a?(Array))
492
542
 
493
543
  st, en = val
494
544
  qs << "startkey=#{Rufus::Doric.escape(st)}" if st
@@ -500,7 +550,13 @@ module Doric
500
550
 
501
551
  add_common_options(qs, opts)
502
552
 
503
- path = "#{design_path}/_view/by_#{key}?#{qs.join('&')}"
553
+ skey = case key
554
+ when Array then key.join('_and_')
555
+ when Hash then key.keys.first
556
+ else key
557
+ end
558
+
559
+ path = "#{design_path}/_view/by_#{skey}?#{qs.join('&')}"
504
560
 
505
561
  result = get_result(path, key)
506
562
 
@@ -33,7 +33,7 @@ module Doric
33
33
 
34
34
  def self.neutralize_id (s)
35
35
 
36
- s.to_s.strip.gsub(/[\s\/:;\*\\\+\?]/, '_')
36
+ s.to_s.strip.gsub(/[\.\s\/:;\*\\\+\?]/, '_')
37
37
  end
38
38
 
39
39
  def self.escape (o)
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Rufus
3
3
  module Doric
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.7'
5
5
  end
6
6
  end
7
7
 
data/rufus-doric.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rufus-doric}
8
- s.version = "0.1.6"
8
+ s.version = "0.1.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Mettraux"]
12
- s.date = %q{2010-04-14}
12
+ s.date = %q{2010-04-16}
13
13
  s.description = %q{
14
14
  something at the intersection of Rails3, CouchDB and rufus-jig
15
15
  }
@@ -50,6 +50,9 @@ something at the intersection of Rails3, CouchDB and rufus-jig
50
50
  "test/ut_11_model_view_range.rb",
51
51
  "test/ut_12_model_default.rb",
52
52
  "test/ut_13_one_doc_model_default.rb",
53
+ "test/ut_14_model_default_id.rb",
54
+ "test/ut_15_model_view_by_and.rb",
55
+ "test/ut_16_model_custom_view.rb",
53
56
  "test/ut_1_model.rb",
54
57
  "test/ut_2_model_view.rb",
55
58
  "test/ut_3_model_lint.rb",
@@ -0,0 +1,46 @@
1
+
2
+ #
3
+ # testing rufus-doric
4
+ #
5
+ # Thu Apr 15 15:31:51 JST 2010
6
+ #
7
+
8
+ require File.join(File.dirname(__FILE__), 'base')
9
+
10
+ require 'rufus/doric'
11
+
12
+
13
+ class Unknown < Rufus::Doric::Model
14
+
15
+ db :doric
16
+ doric_type :unknowns
17
+
18
+ #_id_field :serial
19
+
20
+ h_accessor :name
21
+ end
22
+
23
+
24
+ class UtModelDefaultTest < Test::Unit::TestCase
25
+
26
+ def setup
27
+
28
+ Rufus::Doric.db('doric').delete('.')
29
+ Rufus::Doric.db('doric').put('.')
30
+
31
+ Rufus::Doric.db('doric').http.cache.clear
32
+ # CouchDB feeds the same etags for views, even after a db has
33
+ # been deleted and put back, so have to do that 'forgetting'
34
+ end
35
+
36
+ #def teardown
37
+ #end
38
+
39
+ def test_default_id
40
+
41
+ Unknown.new(:name => 'nemo').save!
42
+
43
+ assert_equal 1, Unknown.all.size
44
+ end
45
+ end
46
+
@@ -0,0 +1,64 @@
1
+
2
+ #
3
+ # testing rufus-doric
4
+ #
5
+ # Fri Apr 16 13:46:53 JST 2010
6
+ #
7
+
8
+ require File.join(File.dirname(__FILE__), 'base')
9
+
10
+ require 'rufus/doric'
11
+
12
+
13
+ class Squad < Rufus::Doric::Model
14
+
15
+ db :doric
16
+ doric_type :squads
17
+
18
+ h_accessor :type
19
+ h_accessor :ranking
20
+
21
+ view_by :ranking
22
+ view_by [ :type, :ranking ]
23
+ end
24
+
25
+
26
+ class UtModelViewByAndTest < Test::Unit::TestCase
27
+
28
+ def setup
29
+
30
+ Rufus::Doric.db('doric').delete('.')
31
+ Rufus::Doric.db('doric').put('.')
32
+
33
+ Rufus::Doric.db('doric').http.cache.clear
34
+ # CouchDB feeds the same etags for views, even after a db has
35
+ # been deleted and put back, so have to do that 'forgetting'
36
+ end
37
+
38
+ #def teardown
39
+ #end
40
+
41
+ def test_view_by_and
42
+
43
+ Squad.new(
44
+ 'type' => 'rifle',
45
+ 'ranking' => 'first'
46
+ ).save!
47
+ Squad.new(
48
+ 'type' => 'rifle',
49
+ 'ranking' => 'first'
50
+ ).save!
51
+ Squad.new(
52
+ 'type' => 'artillery',
53
+ 'ranking' => 'second'
54
+ ).save!
55
+ Squad.new(
56
+ 'type' => 'artillery',
57
+ 'ranking' => 'first'
58
+ ).save!
59
+
60
+ assert_equal 2, Squad.by_type_and_ranking([ 'rifle', 'first' ]).size
61
+ assert_equal 3, Squad.by_ranking('first').size
62
+ end
63
+ end
64
+
@@ -0,0 +1,70 @@
1
+
2
+ #
3
+ # testing rufus-doric
4
+ #
5
+ # Fri Apr 16 15:19:46 JST 2010
6
+ #
7
+
8
+ require File.join(File.dirname(__FILE__), 'base')
9
+
10
+ require 'rufus/doric'
11
+
12
+
13
+ class Team < Rufus::Doric::Model
14
+
15
+ db :doric
16
+ doric_type :teams
17
+
18
+ h_accessor :type
19
+ h_accessor :security_level
20
+ h_accessor :headcount
21
+
22
+ view_by 'tysec', %{
23
+ emit(doc.type + '__' + doc.security_level, null);
24
+ }
25
+ end
26
+
27
+
28
+ class UtModelCustomViewTest < Test::Unit::TestCase
29
+
30
+ def setup
31
+
32
+ Rufus::Doric.db('doric').delete('.')
33
+ Rufus::Doric.db('doric').put('.')
34
+
35
+ Rufus::Doric.db('doric').http.cache.clear
36
+ # CouchDB feeds the same etags for views, even after a db has
37
+ # been deleted and put back, so have to do that 'forgetting'
38
+ end
39
+
40
+ #def teardown
41
+ #end
42
+
43
+ def test_view_by_and
44
+
45
+ Team.new(
46
+ 'type' => 'rifle',
47
+ 'security_level' => 'a'
48
+ ).save!
49
+ Team.new(
50
+ 'type' => 'rifle',
51
+ 'security_level' => 'a'
52
+ ).save!
53
+ Team.new(
54
+ 'type' => 'rifle',
55
+ 'security_level' => 'b'
56
+ ).save!
57
+ Team.new(
58
+ 'type' => 'artillery',
59
+ 'security_level' => 'a'
60
+ ).save!
61
+ Team.new(
62
+ 'type' => 'artillery',
63
+ 'security_level' => 'c'
64
+ ).save!
65
+
66
+ assert_equal 2, Team.by_tysec('rifle__a').size
67
+ assert_equal 1, Team.by_tysec('rifle__b').size
68
+ end
69
+ end
70
+
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 6
9
- version: 0.1.6
8
+ - 7
9
+ version: 0.1.7
10
10
  platform: ruby
11
11
  authors:
12
12
  - John Mettraux
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-14 00:00:00 +09:00
17
+ date: 2010-04-16 00:00:00 +09:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -137,6 +137,9 @@ files:
137
137
  - test/ut_11_model_view_range.rb
138
138
  - test/ut_12_model_default.rb
139
139
  - test/ut_13_one_doc_model_default.rb
140
+ - test/ut_14_model_default_id.rb
141
+ - test/ut_15_model_view_by_and.rb
142
+ - test/ut_16_model_custom_view.rb
140
143
  - test/ut_1_model.rb
141
144
  - test/ut_2_model_view.rb
142
145
  - test/ut_3_model_lint.rb