lore 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/LICENSE +19 -0
  2. data/README +74 -0
  3. data/aspect.rb +80 -0
  4. data/behaviours/lockable.rb +41 -0
  5. data/behaviours/movable.rb +54 -0
  6. data/behaviours/versioned.rb +24 -0
  7. data/benchmark.rb +193 -0
  8. data/bits.rb +52 -0
  9. data/cache/abstract_entity_cache.rb +82 -0
  10. data/cache/bits.rb +22 -0
  11. data/cache/cacheable.rb +202 -0
  12. data/cache/cached_entities.rb +116 -0
  13. data/cache/file_index.rb +35 -0
  14. data/cache/mmap_entity_cache.rb +67 -0
  15. data/clause.rb +528 -0
  16. data/connection.rb +155 -0
  17. data/custom_functions.sql +14 -0
  18. data/exception/ambiguous_attribute.rb +14 -0
  19. data/exception/cache_exception.rb +30 -0
  20. data/exception/invalid_klass_parameters.rb +63 -0
  21. data/exception/invalid_parameter.rb +42 -0
  22. data/exception/unknown_typecode.rb +19 -0
  23. data/file_index.sql +56 -0
  24. data/gui/erb_template.rb +79 -0
  25. data/gui/erb_template_helpers.rhtml +19 -0
  26. data/gui/form.rb +314 -0
  27. data/gui/form_element.rb +676 -0
  28. data/gui/form_generator.rb +151 -0
  29. data/gui/templates/button.rhtml +2 -0
  30. data/gui/templates/checkbox.rhtml +3 -0
  31. data/gui/templates/checkbox_row.rhtml +1 -0
  32. data/gui/templates/file.rhtml +2 -0
  33. data/gui/templates/file_readonly.rhtml +3 -0
  34. data/gui/templates/form_element.rhtml +5 -0
  35. data/gui/templates/form_element_horizontal.rhtml +3 -0
  36. data/gui/templates/form_element_listed.rhtml +8 -0
  37. data/gui/templates/form_table.rhtml +3 -0
  38. data/gui/templates/form_table_blank.rhtml +3 -0
  39. data/gui/templates/form_table_horizontal.rhtml +8 -0
  40. data/gui/templates/password.rhtml +2 -0
  41. data/gui/templates/password_readonly.rhtml +3 -0
  42. data/gui/templates/radio.rhtml +1 -0
  43. data/gui/templates/radio_row.rhtml +1 -0
  44. data/gui/templates/select.rhtml +23 -0
  45. data/gui/templates/text.rhtml +2 -0
  46. data/gui/templates/text_readonly.rhtml +3 -0
  47. data/gui/templates/textarea.rhtml +3 -0
  48. data/gui/templates/textarea_readonly.rhtml +4 -0
  49. data/lore.gemspec +40 -0
  50. data/lore.rb +94 -0
  51. data/migration.rb +48 -0
  52. data/model.rb +139 -0
  53. data/model_factory.rb +202 -0
  54. data/model_shortcuts.rb +16 -0
  55. data/query_shortcuts.rb +367 -0
  56. data/reserved_methods.txt +3 -0
  57. data/result.rb +100 -0
  58. data/symbol.rb +58 -0
  59. data/table_accessor.rb +1926 -0
  60. data/table_deleter.rb +115 -0
  61. data/table_inserter.rb +168 -0
  62. data/table_instance.rb +384 -0
  63. data/table_selector.rb +314 -0
  64. data/table_updater.rb +155 -0
  65. data/test/README +31 -0
  66. data/test/env.rb +5 -0
  67. data/test/lore_test.log +8218 -0
  68. data/test/model.rb +142 -0
  69. data/test/prepare.rb +37 -0
  70. data/test/tc_aspect.rb +58 -0
  71. data/test/tc_cache.rb +80 -0
  72. data/test/tc_clause.rb +104 -0
  73. data/test/tc_deep_inheritance.rb +49 -0
  74. data/test/tc_factory.rb +57 -0
  75. data/test/tc_filter.rb +37 -0
  76. data/test/tc_form.rb +32 -0
  77. data/test/tc_model.rb +86 -0
  78. data/test/tc_prepare.rb +45 -0
  79. data/test/tc_refined_query.rb +88 -0
  80. data/test/tc_table_accessor.rb +265 -0
  81. data/test/test.log +181 -0
  82. data/test/test_db.sql +400 -0
  83. data/test/ts_lore.rb +49 -0
  84. data/types.rb +55 -0
  85. data/validation/message.rb +60 -0
  86. data/validation/parameter_validator.rb +104 -0
  87. data/validation/reason.rb +54 -0
  88. data/validation/type_validator.rb +91 -0
  89. data/validation.rb +65 -0
  90. metadata +170 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+
2
+ Copyright (c) 2005-2008 Tobias Fuchs (fuchs@wortundform.de)
3
+ Lore has evolved from Cuba::DB, Copyright (c) 2004 Tobias Fuchs (fuchs@wortundform.de)
4
+
5
+ (MIT Licence)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
8
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation
9
+ the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
10
+ to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of
13
+ the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
16
+ THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
18
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,74 @@
1
+
2
+ Q: Are there adapters for other DBMS than PostgreSQL?
3
+ A: PostgreSQL is - to me and everyone using Lore i know of -
4
+ the best (free) choice for sophisticated database-driven
5
+ apps, so frankly said: Implementing adapters is not on my
6
+ top priority list. Adapters also come with some cost in
7
+ performance, by introducing an additional level of
8
+ abstraction.
9
+ So far, Lore supports PostgreSQL (7.4 to 8.3 tested).
10
+ Adapters are planned for oracle mysql and sqlite though.
11
+ Lore is SQL 92 compatible and not using any exotic
12
+ Postgres features, so it *might* work fine on e.g. mysql
13
+ and sqlite with just minor modifications. It is caring
14
+ about cascading dependencies etc, so you don't even need
15
+ foreign keys or table inheritance.
16
+ You will have to change the code establishing DB
17
+ connections (see connection.rb), but as those are
18
+ abstracted, just a couple of lines of code in connection.rb
19
+ had to be changed.
20
+
21
+ Q: How do i establish a DB connection at all?
22
+ A: In /lore.rb, edit the Hash instance @logins. Lore is caring
23
+ about connections itself.
24
+ You have to enter a so-called context (database, that is),
25
+ though:
26
+
27
+ Lore::Context.enter :my_dbname
28
+
29
+ Q: What about connection pooling?
30
+ A: Use PGPool for that, it's way better than any
31
+ implementation of connection pooling in ruby.
32
+ Install PGPool and tell lore to connect to PGPool's port
33
+ instead of PostgreSQL's one.
34
+ Example:
35
+
36
+ Lore.server = 'localhost:9999'
37
+
38
+ That's it!
39
+
40
+ Q: Which solution do you recommend for query result caching?
41
+ A: There are many possibilities: Tempfiles, MMap and Memcached
42
+ are the most widespread solutions known to me.
43
+ Many will agree that MMap is the best solution in matters
44
+ of performance on a single server, and memcached as soon as
45
+ more than one server is involved in your application.
46
+
47
+ Q: There are failing unit tests!!
48
+ A: I know. Those document missing features i'm implementing
49
+ at the very moment :) Be sure to update once in a while!
50
+
51
+ Q: After creating a model via Model_Factory: How do i change
52
+ it?
53
+ A: At the moment, this is not implemented, but tracked as
54
+ 'missing feature'. This will be possible in version 1.0 at
55
+ the latest.
56
+
57
+ Q: There's so much documentation missing, the API isn't really
58
+ helpful. Where can i get more info and examples?
59
+ A: Have a look at the wiki. I'm updating it quite often, and
60
+ new features are explained in the wiki first:
61
+ http://infranode.com/wiki/
62
+
63
+ Q: I found a bug!! What now?
64
+ A: In case you're registered at rubyforge, visit
65
+ http://lore.rubyforge.org and submit a bug report.
66
+ Otherwise, just send me a mail (fuchs@atomnode.net).
67
+ If you're using Lore and are your progress is blocked by a
68
+ bug, i'll fix it almost instantly. I'm checking my mails
69
+ more often than the tickets at rubyforge, though.
70
+
71
+ Q: I want to join the dev team.
72
+ A: Great! Just send a mail to fuchs@wortundform.de, i will add
73
+ you on Rubyforge if you got some code to share.
74
+
data/aspect.rb ADDED
@@ -0,0 +1,80 @@
1
+
2
+
3
+ module Lore
4
+
5
+ # Steps taken in .create are:
6
+ #
7
+ # * .before_create(attribs)
8
+ # * applying input filters
9
+ # * .before_create_after_filters(attribs)
10
+ # * distributing attributes to tables:
11
+ # { :attrib => 'value' } -> { 'public.my_table' => { :attrib => 'value'} }
12
+ # * .before_create_and_validation(table_attribs)
13
+ # * validation
14
+ # * .before_insert(table_attribs)
15
+ # * insert operation
16
+ # * .before_load(attribs)
17
+ # * load new instance from DB (thus getting final table values)
18
+ # * .after_create(created_instance)
19
+
20
+ module Aspect
21
+
22
+ private
23
+
24
+ def before_delete(args)
25
+ end
26
+
27
+ def after_delete(args)
28
+ end
29
+
30
+ # Expects arguments (value hash) passed
31
+ # to Table_Accessor.create
32
+ def before_create(args)
33
+ end
34
+
35
+ # Expects arguments (value hash) passed
36
+ # to Table_Accessor.create
37
+ def after_filters(filtered_args)
38
+ end
39
+
40
+ # Expects arguments (value hash) passed
41
+ # to Table_Accessor.create and distributed
42
+ # to table names
43
+ def before_validation(distributed_args)
44
+ end
45
+
46
+ # Expects arguments (value hash) passed
47
+ # to Table_Accessor.create and distributed
48
+ # to table names
49
+ def before_insert(validated_args)
50
+ end
51
+
52
+ def before_load(completed_args)
53
+ end
54
+
55
+ # Expects object that has been created.
56
+ def after_create(obj)
57
+ end
58
+
59
+ public
60
+
61
+ # Expects model instance to be deleted.
62
+ def before_instance_delete(model_instance)
63
+ end
64
+ # Expects model instance table rows have been
65
+ # deleted of
66
+ def after_instance_delete(model_instance)
67
+ end
68
+
69
+ # Expects arguments (value hash) passed
70
+ # to Table_Accessor.create and object
71
+ # to be updated.
72
+ def before_commit(obj)
73
+ end
74
+ # Expects updated object.
75
+ def after_commit(obj)
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,41 @@
1
+
2
+ module Lore
3
+ module Behaviours
4
+
5
+ module Lockable
6
+
7
+ # Defines which attribute to use for locking.
8
+ # Default is 'lock'.
9
+ # Usage:
10
+ #
11
+ # If a block is given, a lock is only set when it
12
+ # evaluates to true:
13
+ #
14
+ # lock_by(:lock) { |me|
15
+ # me.user_id != $user.user_id
16
+ # }
17
+ #
18
+ def lock_by(attrib, &block)
19
+ @lock_proc = block
20
+ @lock_attr = attrib
21
+ @lock_attr_name = attrib.to_s.split('.')[-1].intern
22
+ end
23
+
24
+ def lock!(inst)
25
+ inst[@lock_attr] = true
26
+ commit
27
+ end # def
28
+
29
+ def release!(inst)
30
+ inst[@lock_attr] = false
31
+ commit
32
+ end # def
33
+
34
+ def locked?(inst)
35
+ (inst[@lock_attr] == true) || (inst[@lock_attr] == 't')
36
+ end # def
37
+
38
+ end # module
39
+
40
+ end # module
41
+ end # module
@@ -0,0 +1,54 @@
1
+
2
+ module Lore
3
+ module Behaviours
4
+
5
+ module Movable
6
+
7
+ def ordered_by(attr)
8
+ @order_attr = attr
9
+ @order_attr_name = attr.to_s.split('.')[-1].intern
10
+ end
11
+
12
+ def move(inst, sortpos, criteria)
13
+
14
+ sortpos = sortpos.to_i
15
+ return if sortpos < 1
16
+
17
+ sortpos_old = inst.attr[@order_attr_name].to_i
18
+
19
+ # move down:
20
+ if sortpos.to_i > sortpos_old then
21
+
22
+ self.update { |na|
23
+ na.set({@order_attr_name => @order_attr-1}).where(
24
+ (criteria) &
25
+ (@order_attr <= sortpos) &
26
+ (@order_attr > sortpos_old)
27
+ )
28
+ }
29
+
30
+ elsif sortpos.to_i < sortpos_old then
31
+
32
+ self.update { |na|
33
+ na.set({@order_attr_name => @order_attr+1}).where(
34
+ (criteria) &
35
+ (@order_attr >= sortpos) &
36
+ (@order_attr < sortpos_old)
37
+ )
38
+ }
39
+
40
+ end
41
+
42
+ if sortpos != sortpos_old then
43
+
44
+ inst.set_attribute_value(@order_attr_name, sortpos)
45
+ inst.commit()
46
+
47
+ end
48
+
49
+ end # def
50
+
51
+ end # module
52
+
53
+ end # module
54
+ end # module
@@ -0,0 +1,24 @@
1
+
2
+ module Lore
3
+ module Behaviours
4
+
5
+ module Versioned
6
+
7
+ # Defines attribute the version number is stored in.
8
+ # Default is 'version'.
9
+ def version_by(attrib)
10
+ @version_attr = attrib
11
+ @version_attr_name = attrib.to_s.split('.')[-1].intern
12
+ end
13
+
14
+ # Overloads commit so it increments the version attribute
15
+ # before saving instance to database.
16
+ def commit()
17
+ set_attribute_value(@version_attr, self.attr[@version_attr].to_i + 1)
18
+ super()
19
+ end
20
+
21
+ end # module
22
+
23
+ end # module
24
+ end # module
data/benchmark.rb ADDED
@@ -0,0 +1,193 @@
1
+
2
+ require('lore/model')
3
+ require('lore/cache/mmap_entity_cache')
4
+
5
+ Lore::Model.use_entity_cache Lore::Cache::MMap_Entity_Cache
6
+ # Aurita.load_project :default
7
+ # Aurita.import_plugin_model :wiki, :article
8
+
9
+ # include Aurita::Plugins::Wiki
10
+
11
+ require('benchmark')
12
+ include Benchmark
13
+ # require('profile')
14
+ Lore.logfile = './benchmark_query.log'
15
+
16
+ require('rubygems')
17
+ require('activerecord')
18
+
19
+ ActiveRecord::Base.establish_connection(
20
+ :adapter => 'postgresql',
21
+ :host => 'localhost',
22
+ :username => 'cuba',
23
+ :password => 'cuba23',
24
+ :database => 'artest'
25
+ )
26
+
27
+ Lore.add_login_data('artest' => ['cuba', 'cuba23'])
28
+ Lore::Context.enter :artest
29
+
30
+ module AR
31
+ class Content < ActiveRecord::Base
32
+ end
33
+
34
+ class Article < Content
35
+ end
36
+ end
37
+
38
+ module Lore
39
+ class Content < Lore::Model
40
+ table :contents, :public
41
+ primary_key :id, :content_id_seq
42
+ end
43
+
44
+ class Article < Content
45
+ table :articles, :public
46
+ primary_key :id, :article_id_seq
47
+ is_a Content, :content_id
48
+ end
49
+ end
50
+
51
+ num_loops = 10000
52
+
53
+ class Result_Parser
54
+ require 'inline'
55
+
56
+ def initialize(result) # expects PGresult
57
+
58
+ @result = result
59
+ @field_types = nil
60
+ @result_rows = Array.new
61
+ @num_fields = @result.num_fields
62
+ @field_name_split = Array.new
63
+ @field_name = String.new
64
+ @table_name = String.new
65
+ @field_counter = 0
66
+
67
+ end # def initialize
68
+
69
+ =begin
70
+ inline { |builder|
71
+ builder.c <<-EOC
72
+ VALUE get_row_c(VALUE result, int row_num) {
73
+ unsigned int field_counter;
74
+ VALUE row_result, field_name, table_name, field_name_split;
75
+ VALUE value_set = rb_hash_new();
76
+ field_name = rb_string_new();
77
+ table_name = rb_string_new();
78
+ row_result = rb_hash_new();
79
+ for(field_counter = 0; field_counter < num_fields; field_counter++) {
80
+ value_set = result->getvalue(row_num, UINT2NUM(field_counter));
81
+ // if(row_result[@table_name].nil?) then
82
+ if(rb_hash_aref(row_result, table_name) == QNil) {
83
+ // row_result[@table_name] = Hash.new()
84
+ rb_hash_aset(row_result, table_name, value_set)
85
+ }
86
+ rb_hash_aset(rb_hash_aref)row_result, table_name), value_set);
87
+ }
88
+ return row_result;
89
+ }
90
+ EOC
91
+ }
92
+ =end
93
+
94
+ def get_row(row_num=0)
95
+
96
+ return if @result.num_tuples == 0
97
+
98
+ row_result = Hash.new
99
+
100
+ @field_name_split = Array.new
101
+ @field_name = String.new
102
+ @table_name = String.new
103
+ @field_counter = 0
104
+ for @field_counter in 0...@num_fields do
105
+ # admin.rd__content.name -> [admin, rd__content, name]
106
+ @field_name = @result.fieldname(@field_counter)
107
+
108
+ row_result[@field_name] = @result.getvalue(row_num,@field_counter)
109
+ end
110
+
111
+ @result_rows[row_num] = row_result
112
+
113
+ end
114
+
115
+ def get_rows()
116
+ if !@result_rows.first then
117
+ for tuple_counter in 0...@result.num_tuples do
118
+ get_row(tuple_counter)
119
+ end
120
+ end
121
+ @result_rows
122
+ end
123
+
124
+ end
125
+
126
+ db_name = 'artest'
127
+ connection = PGconn.connect(Lore.pg_server, Lore.pg_port, '', '', db_name.to_s, Lore.user_for(db_name), Lore.pass_for(db_name.to_s))
128
+
129
+ sql = 'SELECT *
130
+ FROM public.articles
131
+ JOIN public.contents on (public.contents.id = public.articles.content_id)
132
+ WHERE public.articles.id BETWEEN 1100 AND 1200 LIMIT 100 OFFSET 0'
133
+
134
+ bmbm(12) { |test|
135
+ test.report("rows_raw") {
136
+ num_loops.times {
137
+ result = connection.exec(sql)
138
+ for row in 0...result.num_tuples do
139
+ for field_index in 0...result.num_fields do
140
+ result.getvalue(row,field_index)
141
+ end
142
+ end
143
+ }
144
+ }
145
+ test.report("rows_raw_parsed") {
146
+ num_loops.times {
147
+ result = connection.exec(sql)
148
+ p = Result_Parser.new(result)
149
+ # puts p.get_row_c(result, 0)
150
+ p.get_rows
151
+ }
152
+ }
153
+ test.report("rows_lore") {
154
+ num_loops.times {
155
+ result = connection.exec(sql)
156
+ lore_result = Lore::Result.new('',result)
157
+ lore_result.get_rows.each { |row|
158
+ # noop
159
+ }
160
+ }
161
+ }
162
+ test.report("ac_instances") {
163
+ num_loops.times {
164
+ result = connection.exec(sql)
165
+ lore_result = Lore::Result.new('',result)
166
+ model_instances = []
167
+ lore_result.get_rows.each { |row|
168
+ i = Lore::Article.new(Lore::Article,row)
169
+ model_instances.push(i)
170
+ }
171
+ }
172
+ }
173
+ test.report("full_auto") {
174
+ Lore.disable_cache
175
+ num_loops.times {
176
+ Lore::Article.find(100).with(Lore::Article.id.in(1100..1200)).entities
177
+ }
178
+ }
179
+ test.report("ar") {
180
+ num_loops.times {
181
+ AR::Article.find(:all, :conditions => "id > 1100 AND id < 1200").each { |a|
182
+ }
183
+ }
184
+ }
185
+ test.report('using cache') {
186
+ Lore.enable_cache
187
+ num_loops.times {
188
+ Lore::Article.find(100).with(Lore::Article.id.in(1100..1200)).entities
189
+ }
190
+ }
191
+ }
192
+
193
+
data/bits.rb ADDED
@@ -0,0 +1,52 @@
1
+
2
+ module Lore
3
+
4
+ def self.resolve_passed_value(values, table_name, attrib_name)
5
+ return { :value => values[attrib_name].to_s, :field => attrib_name }
6
+ idx = attrib_name.to_s.length
7
+ value = nil
8
+ while value.nil? && idx > 1 do
9
+ name_part = attrib_name.to_s[0..idx]
10
+ value = values[name_part]
11
+ if value == '' then
12
+ name_part = table_name + '.' << name_part
13
+ value = values[name_part]
14
+ end
15
+
16
+ idx -= 1
17
+ end
18
+ { :value => value, :field => name_part }
19
+ end
20
+
21
+ end
22
+
23
+ class Hash
24
+
25
+ def deep_merge!(second)
26
+ merger = proc { |key,v1,v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
27
+ self.merge!(second, &merger)
28
+ end
29
+
30
+ def nested_hash(array)
31
+ node = self
32
+ array.each do |i|
33
+ node[i]=Hash.new if node[i].nil?
34
+ node = node[i]
35
+ end
36
+ self
37
+ end
38
+
39
+ def merge_nested_hash!(nested_hash)
40
+ deep_merge!(nested_hash)
41
+ end
42
+
43
+ def keys_flat(keys_result=[])
44
+ keys.each { |k|
45
+ keys_result << k
46
+ child = self[k]
47
+ child.keys_flat(keys_result) if (child && child.kind_of?(Hash))
48
+ }
49
+ return keys_result
50
+ end
51
+
52
+ end
@@ -0,0 +1,82 @@
1
+
2
+ require('logger')
3
+ require('pstore')
4
+ require('digest/md5')
5
+
6
+ module Lore
7
+ module Cache
8
+
9
+ # When implementing your own entity cache, derive from and implement
10
+ # Abstract_Entity_Cache.
11
+ # Expected class methods are:
12
+ # - flush
13
+ # - read(query_string)
14
+ # - create(model_klass, query_string, result)
15
+ # - include?(query_string)
16
+ # - delete(cache_index)
17
+ # cache_index being an MD5 sum of the query_string that
18
+ # generated the cache entry.
19
+ # In case you want cache indices other than MD5 sums,
20
+ # define class method
21
+ # index_for(query_string)
22
+ #
23
+ # Every model may use a different caching implementation.
24
+ # To enable a specific caching implenentation for a model, use:
25
+ #
26
+ # class Your_Model < Lore::Model
27
+ # ...
28
+ # use_cache_impl The_Cache_Implementation_Klass
29
+ # ...
30
+ # end
31
+ #
32
+ class Abstract_Entity_Cache
33
+
34
+ # Delete all cache entries for this model
35
+ def self.flush
36
+ raise ::Exception.new('Not implemented')
37
+ end
38
+
39
+ # Read cached result for a specific query string.
40
+ # Returns array of model instances.
41
+ def self.read(accessor, query_string)
42
+ raise ::Exception.new('Not implemented')
43
+ end
44
+
45
+ # Create cache entry for a specific query_string on a model.
46
+ # Expects result from given query string as it has to be
47
+ # returned when calling Cache_Implementation.read(query_string)
48
+ def self.create(accessor, query_string, result)
49
+ raise ::Exception.new('Not implemented')
50
+ end
51
+
52
+ # Whether there is a cache entry for a query or not.
53
+ def self.include?(accessor, query_string)
54
+ raise ::Exception.new('Not implemented')
55
+ end
56
+
57
+ # Delete a specific cache entry, parameter index being
58
+ # primary key (e.g. a hash value) in cache generated from
59
+ # a query.
60
+ def self.delete(index)
61
+ raise ::Exception.new('Not implemented')
62
+ end
63
+
64
+ end
65
+
66
+ module Cache_Helpers
67
+ def index_for(query)
68
+ Digest::MD5.hexdigest(query)
69
+ end
70
+
71
+ def storefile_of(model_name, query)
72
+ '/tmp/lore_cache__' << model_name + '_' << Digest::MD5.hexdigest(query)
73
+ end
74
+
75
+ def create_store(storefile_name)
76
+ store = PStore.new(storefile_name) unless storefile_name.nil?
77
+ return store
78
+ end
79
+ end
80
+
81
+ end
82
+ end
data/cache/bits.rb ADDED
@@ -0,0 +1,22 @@
1
+
2
+ module Lore
3
+ module Cache
4
+
5
+ @@ignore_params = [ 'cb__model', 'cb__controller', 'cb__mode' ]
6
+
7
+ def self.store_name(klass_name, controller, mode, keys)
8
+ key_string = ''
9
+ keys.each_pair { |name, value|
10
+ key_string += '@@@'+name+'==' << value.to_s unless @@ignore_params.include? name
11
+ }
12
+ controller = '*' if controller == :all
13
+ mode = '*' if mode == :all
14
+
15
+ store_name = '/tmp/cb__cache__' << klass_name.to_s << '@@@' << controller.to_s << '@@@' << mode.to_s
16
+ store_name += key_string unless key_string == ''
17
+
18
+ return store_name
19
+ end
20
+
21
+ end # module
22
+ end # module