lore 0.4.2

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 (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