activegroonga 0.0.1

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 (121) hide show
  1. data/AUTHORS +1 -0
  2. data/NEWS.ja.rdoc +5 -0
  3. data/NEWS.rdoc +5 -0
  4. data/README.ja.rdoc +49 -0
  5. data/README.rdoc +49 -0
  6. data/Rakefile +175 -0
  7. data/lib/active_groonga.rb +75 -0
  8. data/lib/active_groonga/aggregations.rb +30 -0
  9. data/lib/active_groonga/associations.rb +93 -0
  10. data/lib/active_groonga/associations/belongs_to_association.rb +25 -0
  11. data/lib/active_groonga/attribute_methods.rb +36 -0
  12. data/lib/active_groonga/base.rb +1579 -0
  13. data/lib/active_groonga/column.rb +107 -0
  14. data/lib/active_groonga/dirty.rb +30 -0
  15. data/lib/active_groonga/fixtures.rb +92 -0
  16. data/lib/active_groonga/migration.rb +150 -0
  17. data/lib/active_groonga/rails_support.rb +31 -0
  18. data/lib/active_groonga/reflection.rb +30 -0
  19. data/lib/active_groonga/schema.rb +314 -0
  20. data/lib/active_groonga/schema_dumper.rb +147 -0
  21. data/lib/active_groonga/tasks.rb +16 -0
  22. data/lib/active_groonga/tasks/groonga.rake +162 -0
  23. data/lib/active_groonga/test_case.rb +21 -0
  24. data/lib/active_groonga/test_help.rb +21 -0
  25. data/lib/active_groonga/timestamp.rb +30 -0
  26. data/lib/active_groonga/validations.rb +26 -0
  27. data/lib/active_groonga/version.rb +24 -0
  28. data/license/LGPL +504 -0
  29. data/rails/README +28 -0
  30. data/rails/init.rb +70 -0
  31. data/rails_generators/model_groonga/USAGE +28 -0
  32. data/rails_generators/model_groonga/model_groonga_generator.rb +45 -0
  33. data/rails_generators/model_groonga/templates/fixtures.yml +17 -0
  34. data/rails_generators/model_groonga/templates/migration.rb +16 -0
  35. data/rails_generators/model_groonga/templates/model.rb +2 -0
  36. data/rails_generators/model_groonga/templates/unit_test.rb +8 -0
  37. data/test-unit/Rakefile +35 -0
  38. data/test-unit/TODO +5 -0
  39. data/test-unit/bin/testrb +5 -0
  40. data/test-unit/html/classic.html +15 -0
  41. data/test-unit/html/index.html +25 -0
  42. data/test-unit/html/index.html.ja +27 -0
  43. data/test-unit/lib/test/unit.rb +342 -0
  44. data/test-unit/lib/test/unit/assertionfailederror.rb +14 -0
  45. data/test-unit/lib/test/unit/assertions.rb +1149 -0
  46. data/test-unit/lib/test/unit/attribute.rb +125 -0
  47. data/test-unit/lib/test/unit/autorunner.rb +306 -0
  48. data/test-unit/lib/test/unit/collector.rb +43 -0
  49. data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
  50. data/test-unit/lib/test/unit/collector/dir.rb +108 -0
  51. data/test-unit/lib/test/unit/collector/load.rb +135 -0
  52. data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
  53. data/test-unit/lib/test/unit/color-scheme.rb +86 -0
  54. data/test-unit/lib/test/unit/color.rb +96 -0
  55. data/test-unit/lib/test/unit/diff.rb +538 -0
  56. data/test-unit/lib/test/unit/error.rb +124 -0
  57. data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
  58. data/test-unit/lib/test/unit/failure.rb +110 -0
  59. data/test-unit/lib/test/unit/fixture.rb +176 -0
  60. data/test-unit/lib/test/unit/notification.rb +125 -0
  61. data/test-unit/lib/test/unit/omission.rb +143 -0
  62. data/test-unit/lib/test/unit/pending.rb +146 -0
  63. data/test-unit/lib/test/unit/priority.rb +161 -0
  64. data/test-unit/lib/test/unit/runner/console.rb +52 -0
  65. data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
  66. data/test-unit/lib/test/unit/testcase.rb +360 -0
  67. data/test-unit/lib/test/unit/testresult.rb +89 -0
  68. data/test-unit/lib/test/unit/testsuite.rb +110 -0
  69. data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
  70. data/test-unit/lib/test/unit/ui/console/testrunner.rb +220 -0
  71. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +49 -0
  72. data/test-unit/lib/test/unit/ui/testrunner.rb +20 -0
  73. data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
  74. data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
  75. data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
  76. data/test-unit/lib/test/unit/util/method-owner-finder.rb +28 -0
  77. data/test-unit/lib/test/unit/util/observable.rb +90 -0
  78. data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
  79. data/test-unit/lib/test/unit/version.rb +7 -0
  80. data/test-unit/sample/adder.rb +13 -0
  81. data/test-unit/sample/subtracter.rb +12 -0
  82. data/test-unit/sample/tc_adder.rb +18 -0
  83. data/test-unit/sample/tc_subtracter.rb +18 -0
  84. data/test-unit/sample/test_user.rb +22 -0
  85. data/test-unit/sample/ts_examples.rb +7 -0
  86. data/test-unit/test/collector/test-descendant.rb +135 -0
  87. data/test-unit/test/collector/test-load.rb +333 -0
  88. data/test-unit/test/collector/test_dir.rb +406 -0
  89. data/test-unit/test/collector/test_objectspace.rb +98 -0
  90. data/test-unit/test/run-test.rb +13 -0
  91. data/test-unit/test/test-attribute.rb +86 -0
  92. data/test-unit/test/test-color-scheme.rb +56 -0
  93. data/test-unit/test/test-color.rb +47 -0
  94. data/test-unit/test/test-diff.rb +477 -0
  95. data/test-unit/test/test-emacs-runner.rb +60 -0
  96. data/test-unit/test/test-fixture.rb +287 -0
  97. data/test-unit/test/test-notification.rb +33 -0
  98. data/test-unit/test/test-omission.rb +81 -0
  99. data/test-unit/test/test-pending.rb +70 -0
  100. data/test-unit/test/test-priority.rb +119 -0
  101. data/test-unit/test/test_assertions.rb +1082 -0
  102. data/test-unit/test/test_error.rb +26 -0
  103. data/test-unit/test/test_failure.rb +33 -0
  104. data/test-unit/test/test_testcase.rb +478 -0
  105. data/test-unit/test/test_testresult.rb +113 -0
  106. data/test-unit/test/test_testsuite.rb +129 -0
  107. data/test-unit/test/testunit-test-util.rb +14 -0
  108. data/test-unit/test/ui/test_testrunmediator.rb +20 -0
  109. data/test-unit/test/util/test-method-owner-finder.rb +38 -0
  110. data/test-unit/test/util/test_backtracefilter.rb +41 -0
  111. data/test-unit/test/util/test_observable.rb +102 -0
  112. data/test-unit/test/util/test_procwrapper.rb +36 -0
  113. data/test/active-groonga-test-utils.rb +234 -0
  114. data/test/fixtures/bookmark.rb +2 -0
  115. data/test/fixtures/task.rb +2 -0
  116. data/test/fixtures/user.rb +2 -0
  117. data/test/run-test.rb +51 -0
  118. data/test/test-associations.rb +24 -0
  119. data/test/test-base.rb +194 -0
  120. data/test/test-schema.rb +49 -0
  121. metadata +192 -0
@@ -0,0 +1,314 @@
1
+ # Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ module ActiveGroonga
17
+ module Schema
18
+ class << self
19
+ def define(info={}, &block)
20
+ initialize_schema_management_tables
21
+ instance_eval(&block)
22
+
23
+ unless info[:version].blank?
24
+ assume_migrated_upto_version(info[:version])
25
+ end
26
+ end
27
+
28
+ def assume_migrated_upto_version(version)
29
+ version = version.to_i
30
+ table_name = Migrator.groonga_schema_migrations_table_name
31
+
32
+ migrations_table = Base.context[table_name]
33
+ migrated = migrations_table.records.collect do |record|
34
+ record["version"].to_i
35
+ end
36
+ versions = Dir['db/migrate/[0-9]*_*.rb'].map do |filename|
37
+ filename.split('/').last.split('_').first.to_i
38
+ end
39
+
40
+ unless migrated.include?(version)
41
+ migrations_table.add(version.to_s)
42
+ end
43
+
44
+ inserted = Set.new
45
+ (versions - migrated).each do |v|
46
+ if inserted.include?(v)
47
+ raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict."
48
+ elsif v < version
49
+ migration = migrations_table.add
50
+ migration["version"] = v.to_s
51
+ inserted << v
52
+ end
53
+ end
54
+ end
55
+
56
+ def initialize_schema_management_tables
57
+ initialize_index_management_table
58
+ initialize_index_table
59
+ initialize_migrations_table
60
+ end
61
+
62
+ def create_table(name, options={})
63
+ table_definition = TableDefinition.new(name)
64
+ yield(table_definition)
65
+ table_definition.create
66
+ end
67
+
68
+ def drop_table(name, options={})
69
+ table = Base.context[Base.groonga_table_name(name)]
70
+ table_id = table.id
71
+ table.remove
72
+ index_management_table.open_cursor do |cursor|
73
+ while cursor.next
74
+ cursor.delete if cursor.table_id == table_id
75
+ end
76
+ end
77
+ end
78
+
79
+ def add_column(table_name, column_name, type, options={})
80
+ column = ColumnDefinition.new(table_name, column_name)
81
+ if type.to_s == "references"
82
+ table = options.delete(:to) || column_name.pluralize
83
+ column.type = Base.groonga_table_name(table)
84
+ else
85
+ column.type = type
86
+ end
87
+ column.create(options)
88
+ end
89
+
90
+ def remove_column(table_name, *column_names)
91
+ column_names.each do |column_name|
92
+ ColumnDefinition.new(table_name, column_name).remove
93
+ end
94
+ end
95
+
96
+ def add_index(table_name, column_name, options={})
97
+ groonga_table_name = Base.groonga_table_name(table_name)
98
+ table = Base.context[groonga_table_name]
99
+ column_name = column_name.to_s
100
+ column = table.column(column_name)
101
+
102
+ base_dir = File.join(Base.metadata_directory,
103
+ index_table_name,
104
+ table_name)
105
+ FileUtils.mkdir_p(base_dir)
106
+
107
+ name = "#{table_name}/#{column_name}"
108
+ path = File.join(base_dir, "#{column_name}.groonga")
109
+ index_column = index_table.define_column(name, table,
110
+ :path => path,
111
+ :type => "index",
112
+ :compress => "zlib",
113
+ # :with_section => true,
114
+ # :with_weight => true,
115
+ :with_position => true)
116
+ index_column.source = column
117
+
118
+ record = index_management_table.add
119
+ record["table"] = groonga_table_name
120
+ record["column"] = column_name
121
+ record["index"] = name
122
+ end
123
+
124
+ def index_management_table
125
+ Base.context[groonga_index_management_table_name]
126
+ end
127
+
128
+ def index_table
129
+ Base.context[groonga_index_table_name]
130
+ end
131
+
132
+ def indexes(table_or_table_name)
133
+ if table_or_table_name.is_a?(String)
134
+ table_name = table_or_table_name
135
+ table = Base.context[Base.groonga_table_name(table_name)]
136
+ else
137
+ table = table_or_table_name
138
+ table_name = table.name.gsub(/(?:\A<table:|>\z)/, '')
139
+ end
140
+ indexes = []
141
+ index_management_table.records.each do |record|
142
+ next if record["table"] != table.name
143
+ indexes << IndexDefinition.new(table_name, record["index"],
144
+ false, record["column"])
145
+ end
146
+ indexes
147
+ end
148
+
149
+ private
150
+ def index_management_table_name
151
+ Base.table_name_prefix + 'indexes' + Base.table_name_suffix
152
+ end
153
+
154
+ def groonga_index_management_table_name
155
+ Base.groonga_metadata_table_name(index_management_table_name)
156
+ end
157
+
158
+ def index_table_name
159
+ Base.table_name_prefix + 'index' + Base.table_name_suffix
160
+ end
161
+
162
+ def groonga_index_table_name
163
+ Base.groonga_metadata_table_name(index_table_name)
164
+ end
165
+
166
+ def initialize_index_management_table
167
+ table_name = index_management_table_name
168
+ groonga_table_name = groonga_index_management_table_name
169
+ if Base.context[groonga_table_name].nil?
170
+ table_file = File.join(Base.metadata_directory,
171
+ "#{table_name}.groonga")
172
+ table = Groonga::Array.create(:name => groonga_table_name,
173
+ :path => table_file)
174
+
175
+ base_dir = File.join(Base.metadata_directory, table_name)
176
+ FileUtils.mkdir_p(base_dir)
177
+
178
+ column_file = File.join(base_dir, "table.groonga")
179
+ table.define_column("table", "<shorttext>", :path => column_file)
180
+
181
+ column_file = File.join(base_dir, "column.groonga")
182
+ table.define_column("column", "<shorttext>", :path => column_file)
183
+
184
+ column_file = File.join(base_dir, "index.groonga")
185
+ table.define_column("index", "<shorttext>", :path => column_file)
186
+ end
187
+ end
188
+
189
+ def initialize_index_table
190
+ table_name = index_table_name
191
+ groonga_table_name = groonga_index_table_name
192
+ if Base.context[groonga_table_name].nil?
193
+ table_file = File.join(Base.metadata_directory,
194
+ "#{table_name}.groonga")
195
+ table = Groonga::PatriciaTrie.create(:name => groonga_table_name,
196
+ :key_type => "<shorttext>",
197
+ # :key_with_sis => true,
198
+ # :key_normalize => true,
199
+ :path => table_file)
200
+
201
+ base_dir = File.join(Base.metadata_directory, table_name)
202
+ FileUtils.mkdir_p(base_dir)
203
+ end
204
+ end
205
+
206
+ def initialize_migrations_table
207
+ table_name = Migrator.schema_migrations_table_name
208
+ groonga_table_name = Migrator.groonga_schema_migrations_table_name
209
+ if Base.context[groonga_table_name].nil?
210
+ table_file = File.join(Base.metadata_directory,
211
+ "#{table_name}.groonga")
212
+ Groonga::Hash.create(:name => groonga_table_name,
213
+ :path => table_file,
214
+ :key_type => "<shorttext>")
215
+ end
216
+ end
217
+ end
218
+
219
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
220
+ undef_method :primary_key, :to_sql, :native
221
+
222
+ def initialize(name)
223
+ super(nil)
224
+ @name = name
225
+ @indexes = []
226
+ end
227
+
228
+ def create
229
+ table_file = File.join(Base.tables_directory, "#{@name}.groonga")
230
+ Groonga::Array.create(:name => Base.groonga_table_name(@name),
231
+ :path => table_file)
232
+ @columns.each(&:create)
233
+ @indexes.each do |column_name, options|
234
+ Schema.add_index(@name.to_s, column_name, options)
235
+ end
236
+ end
237
+
238
+ def column(name, type, options={})
239
+ column = self[name] || ColumnDefinition.new(@name, name)
240
+ column.type = type
241
+ @columns << column unless @columns.include?(column)
242
+ self
243
+ end
244
+
245
+ def index(column_name, options={})
246
+ @indexes << [column_name.to_s, options]
247
+ end
248
+
249
+ def references(*args)
250
+ options = args.extract_options!
251
+ args.each do |col|
252
+ groonga_table_name = Base.groonga_table_name(col.to_s.pluralize)
253
+ table = Base.context[groonga_table_name]
254
+ column(col, table, options)
255
+ end
256
+ end
257
+ alias :belongs_to :references
258
+ end
259
+
260
+ class ColumnDefinition
261
+ attr_accessor :name, :type
262
+
263
+ def initialize(table_name, name)
264
+ @table_name = table_name
265
+ @name = name
266
+ @name = @name.to_s if @name.is_a?(Symbol)
267
+ @type = nil
268
+ end
269
+
270
+ def create(options={})
271
+ column_file = File.join(Base.columns_directory(@table_name),
272
+ "#{@name}.groonga")
273
+ options = options.merge(:path => column_file)
274
+ table = Base.context[Base.groonga_table_name(@table_name)]
275
+ table.define_column(@name,
276
+ normalize_type(@type),
277
+ options)
278
+ end
279
+
280
+ def remove
281
+ Base.context[@name].remove
282
+ end
283
+
284
+ def normalize_type(type)
285
+ return type if type.is_a?(Groonga::Object)
286
+ case type.to_s
287
+ when "string"
288
+ "<shorttext>"
289
+ when "text"
290
+ "<text>"
291
+ when "integer"
292
+ "<int>"
293
+ when "float"
294
+ "<float>"
295
+ when "decimal"
296
+ "<int64>"
297
+ when "datetime", "timestamp", "time", "date"
298
+ "<time>"
299
+ when "binary"
300
+ "<longtext>"
301
+ when "boolean"
302
+ "<int>"
303
+ else
304
+ type
305
+ end
306
+ end
307
+ end
308
+
309
+ class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
310
+ alias_method :column, :columns
311
+ alias_method :column=, :columns=
312
+ end
313
+ end
314
+ end
@@ -0,0 +1,147 @@
1
+ # Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This library is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 2.1 as published by the Free Software Foundation.
6
+ #
7
+ # This library is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public
13
+ # License along with this library; if not, write to the Free Software
14
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
+
16
+ module ActiveGroonga
17
+ class SchemaDumper < ActiveRecord::SchemaDumper
18
+ class << self
19
+ def dump(stream=STDOUT)
20
+ new.dump(StreamWrapper.new(stream))
21
+ stream
22
+ end
23
+ end
24
+
25
+ def initialize
26
+ @version = Migrator.current_version
27
+ end
28
+
29
+ def dump(stream)
30
+ @references = []
31
+ header(stream)
32
+ dump_tables(stream)
33
+ dump_references(stream)
34
+ trailer(stream)
35
+ stream
36
+ end
37
+
38
+ private
39
+ def dump_tables(stream)
40
+ tables.sort.each do |name|
41
+ next if ignore_tables.any? {|ignored| ignored === name}
42
+ dump_table(name, stream)
43
+ end
44
+ end
45
+
46
+ def tables
47
+ Dir[File.join(Base.tables_directory, "*.groonga")].collect do |path|
48
+ File.basename(path, ".groonga")
49
+ end
50
+ end
51
+
52
+ def dump_table(name, stream)
53
+ begin
54
+ table_schema = StringIO.new
55
+ table_schema.puts " create_table #{name.inspect}, :force => true do |t|"
56
+ column_specs = []
57
+ columns(name).each do |column|
58
+ if column.reference_type?
59
+ @references << [name, column]
60
+ next
61
+ end
62
+
63
+ spec = {}
64
+ spec[:type] = column.type.to_s
65
+ spec[:name] = column.name.inspect
66
+ column_specs << spec
67
+ end
68
+
69
+ column_specs.each do |spec|
70
+ table_schema.print(" t.#{spec[:type]} #{spec[:name]}")
71
+ table_schema.puts
72
+ end
73
+
74
+ table_schema.puts " end"
75
+ table_schema.puts
76
+
77
+ dump_indexes(name, table_schema)
78
+
79
+ stream.print table_schema.string
80
+ rescue => e
81
+ stream.puts "# Could not dump table #{name.inspect} because of following #{e.class}"
82
+ stream.puts "# #{e.message}"
83
+ e.backtrace.each do |trace|
84
+ stream.puts "# #{trace}"
85
+ end
86
+ stream.puts
87
+ end
88
+
89
+ stream
90
+ end
91
+
92
+ def dump_indexes(table, stream)
93
+ _indexes = indexes(table)
94
+ return if _indexes.empty?
95
+
96
+ add_index_statements = _indexes.collect do |index|
97
+ statement_parts = []
98
+ statement_parts << "add_index #{index.table.inspect}"
99
+ statement_parts << index.columns.inspect
100
+ statement_parts << ":name => #{index.name.inspect}"
101
+ ' ' + statement_parts.join(', ')
102
+ end
103
+
104
+ stream.puts add_index_statements.sort.join("\n")
105
+ stream.puts
106
+ end
107
+
108
+ def dump_references(stream)
109
+ @references.sort_by do |name, column|
110
+ [name, column.name]
111
+ end.each do |name, column|
112
+ statement = " add_column #{name.inspect}, "
113
+ statement << "#{column.name.inspect}, :references, "
114
+ statement << ":to => #{column.reference_object_name.inspect}"
115
+ stream.puts(statement)
116
+ end
117
+ end
118
+
119
+ def columns(table_name)
120
+ table_name = Base.groonga_table_name(table_name)
121
+ Base.context[table_name].columns.collect {|column| Column.new(column)}
122
+ end
123
+
124
+ def indexes(table_name)
125
+ Schema.indexes(table_name)
126
+ end
127
+
128
+ class StreamWrapper
129
+ def initialize(stream)
130
+ @stream = stream
131
+ end
132
+
133
+ def method_missing(name, *args, &block)
134
+ @stream.send(name, *args.collect {|arg| normalize_string(arg)}, &block)
135
+ end
136
+
137
+ private
138
+ def normalize_string(string)
139
+ if string.is_a?(String)
140
+ string.gsub(/Active ?Record/, "ActiveGroonga")
141
+ else
142
+ string
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end