activegroonga 0.0.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/README.ja.rdoc +4 -1
  2. data/README.rdoc +4 -1
  3. data/Rakefile +18 -4
  4. data/lib/active_groonga.rb +25 -52
  5. data/lib/active_groonga/base.rb +164 -1480
  6. data/lib/active_groonga/callbacks.rb +26 -7
  7. data/lib/active_groonga/database.rb +55 -0
  8. data/lib/active_groonga/{dirty.rb → error.rb} +20 -10
  9. data/lib/active_groonga/locale/en.yml +5 -0
  10. data/lib/active_groonga/migration.rb +44 -113
  11. data/lib/active_groonga/migrator.rb +172 -0
  12. data/lib/active_groonga/persistence.rb +172 -0
  13. data/lib/active_groonga/railtie.rb +66 -0
  14. data/lib/active_groonga/railties/configurable.rb +47 -0
  15. data/lib/active_groonga/railties/groonga.rake +167 -0
  16. data/lib/active_groonga/result_set.rb +89 -0
  17. data/lib/active_groonga/schema.rb +54 -188
  18. data/lib/active_groonga/validations.rb +54 -5
  19. data/lib/active_groonga/vector.rb +64 -0
  20. data/lib/active_groonga/version.rb +3 -3
  21. data/lib/{active_groonga/aggregations.rb → rails/generators/active_groonga.rb} +17 -10
  22. data/lib/rails/generators/active_groonga/migration/column.rb +101 -0
  23. data/lib/rails/generators/active_groonga/migration/migration_generator.rb +53 -0
  24. data/lib/rails/generators/active_groonga/migration/templates/migration.rb +29 -0
  25. data/lib/rails/generators/active_groonga/model/model_generator.rb +60 -0
  26. data/lib/rails/generators/active_groonga/model/templates/migration.rb +16 -0
  27. data/lib/rails/generators/active_groonga/model/templates/model.rb +2 -0
  28. data/lib/rails/generators/active_groonga/model/templates/module.rb +5 -0
  29. data/test-unit-notify/COPYING +502 -0
  30. data/test-unit-notify/Rakefile +47 -0
  31. data/test-unit-notify/lib/test/unit/notify.rb +127 -0
  32. data/test-unit/COPYING +56 -0
  33. data/test-unit/GPL +340 -0
  34. data/test-unit/PSFL +271 -0
  35. data/test-unit/Rakefile +18 -5
  36. data/test-unit/html/bar.svg +153 -0
  37. data/test-unit/html/developer.svg +469 -0
  38. data/test-unit/html/favicon.ico +0 -0
  39. data/test-unit/html/favicon.svg +82 -0
  40. data/test-unit/html/heading-mark.svg +393 -0
  41. data/test-unit/html/index.html +235 -13
  42. data/test-unit/html/index.html.ja +258 -15
  43. data/test-unit/html/install.svg +636 -0
  44. data/test-unit/html/logo.svg +483 -0
  45. data/test-unit/html/test-unit.css +339 -0
  46. data/test-unit/html/tutorial.svg +559 -0
  47. data/test-unit/lib/test/unit.rb +29 -43
  48. data/test-unit/lib/test/unit/assertionfailederror.rb +11 -0
  49. data/test-unit/lib/test/unit/assertions.rb +202 -20
  50. data/test-unit/lib/test/unit/autorunner.rb +51 -20
  51. data/test-unit/lib/test/unit/collector.rb +1 -8
  52. data/test-unit/lib/test/unit/collector/dir.rb +1 -1
  53. data/test-unit/lib/test/unit/collector/load.rb +16 -9
  54. data/test-unit/lib/test/unit/color-scheme.rb +19 -3
  55. data/test-unit/lib/test/unit/diff.rb +240 -38
  56. data/test-unit/lib/test/unit/error.rb +4 -0
  57. data/test-unit/lib/test/unit/failure.rb +31 -5
  58. data/test-unit/lib/test/unit/notification.rb +8 -4
  59. data/test-unit/lib/test/unit/omission.rb +51 -3
  60. data/test-unit/lib/test/unit/pending.rb +4 -0
  61. data/test-unit/lib/test/unit/priority.rb +2 -3
  62. data/test-unit/lib/test/unit/testcase.rb +65 -7
  63. data/test-unit/lib/test/unit/testresult.rb +34 -2
  64. data/test-unit/lib/test/unit/ui/console/testrunner.rb +197 -45
  65. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +14 -0
  66. data/test-unit/lib/test/unit/ui/tap/testrunner.rb +2 -12
  67. data/test-unit/lib/test/unit/ui/testrunner.rb +33 -0
  68. data/test-unit/lib/test/unit/util/backtracefilter.rb +1 -0
  69. data/test-unit/lib/test/unit/util/output.rb +31 -0
  70. data/test-unit/lib/test/unit/version.rb +1 -1
  71. data/test-unit/sample/{tc_adder.rb → test_adder.rb} +3 -1
  72. data/test-unit/sample/{tc_subtracter.rb → test_subtracter.rb} +3 -1
  73. data/test-unit/sample/test_user.rb +1 -0
  74. data/test-unit/test/collector/test-descendant.rb +2 -4
  75. data/test-unit/test/collector/test-load.rb +121 -8
  76. data/test-unit/test/collector/test_objectspace.rb +7 -5
  77. data/test-unit/test/run-test.rb +2 -0
  78. data/test-unit/test/test-color-scheme.rb +11 -2
  79. data/test-unit/test/test-diff.rb +48 -7
  80. data/test-unit/test/test-omission.rb +1 -1
  81. data/test-unit/test/test-testcase.rb +57 -20
  82. data/test-unit/test/test_assertions.rb +128 -13
  83. data/test-unit/test/ui/test_tap.rb +33 -0
  84. data/test-unit/test/util/test-output.rb +11 -0
  85. data/test/active-groonga-test-utils.rb +50 -36
  86. data/test/fixtures/site.rb +2 -0
  87. data/test/run-test.rb +36 -9
  88. data/test/test-associations.rb +5 -2
  89. data/test/test-base.rb +39 -31
  90. data/test/test-callbacks.rb +13 -3
  91. data/test/test-persistence.rb +53 -0
  92. data/{lib/active_groonga/observer.rb → test/test-result-set.rb} +14 -12
  93. data/test/test-schema.rb +85 -22
  94. data/{lib/active_groonga/rails_support.rb → test/test-validations.rb} +15 -13
  95. metadata +85 -52
  96. data/lib/active_groonga/associations.rb +0 -93
  97. data/lib/active_groonga/associations/belongs_to_association.rb +0 -25
  98. data/lib/active_groonga/attribute_methods.rb +0 -36
  99. data/lib/active_groonga/column.rb +0 -137
  100. data/lib/active_groonga/dynamic_record_expression_builder.rb +0 -40
  101. data/lib/active_groonga/reflection.rb +0 -30
  102. data/lib/active_groonga/schema_dumper.rb +0 -163
  103. data/lib/active_groonga/tasks.rb +0 -16
  104. data/lib/active_groonga/tasks/groonga.rake +0 -164
  105. data/lib/active_groonga/timestamp.rb +0 -30
  106. data/rails/README +0 -28
  107. data/rails/init.rb +0 -70
  108. data/rails_generators/index_table_groonga/USAGE +0 -23
  109. data/rails_generators/index_table_groonga/index_table_groonga_generator.rb +0 -44
  110. data/rails_generators/index_table_groonga/templates/migration.rb +0 -12
  111. data/rails_generators/migration_groonga/USAGE +0 -29
  112. data/rails_generators/migration_groonga/migration_groonga_generator.rb +0 -19
  113. data/rails_generators/migration_groonga/templates/migration.rb +0 -11
  114. data/rails_generators/model_groonga/USAGE +0 -28
  115. data/rails_generators/model_groonga/model_groonga_generator.rb +0 -45
  116. data/rails_generators/model_groonga/templates/fixtures.yml +0 -17
  117. data/rails_generators/model_groonga/templates/migration.rb +0 -16
  118. data/rails_generators/model_groonga/templates/model.rb +0 -2
  119. data/rails_generators/model_groonga/templates/unit_test.rb +0 -8
  120. data/test-unit/html/classic.html +0 -15
  121. data/test-unit/sample/ts_examples.rb +0 -7
  122. data/test/test-schema-dumper.rb +0 -48
@@ -0,0 +1,89 @@
1
+ # Copyright (C) 2010 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 ResultSet
18
+ include Enumerable
19
+
20
+ attr_reader :records, :expression, :n_records
21
+ def initialize(records, klass, options={})
22
+ @records = records
23
+ @klass = klass
24
+ @groups = {}
25
+ @expression = options[:expression]
26
+ if @expression.nil? and @records.respond_to?(:expression)
27
+ @expression = @records.expression
28
+ end
29
+ @n_records = options[:n_records] || @records.size
30
+ compute_n_key_nested
31
+ end
32
+
33
+ def paginate(sort_keys, options={})
34
+ records = @records.paginate(sort_keys, options)
35
+ set = self.class.new(records, @klass,
36
+ :expression => @expression)
37
+ set.extend(PaginationProxy)
38
+ set
39
+ end
40
+
41
+ def sort(keys, options={})
42
+ self.class.new(@records.sort(keys, options), @klass,
43
+ :expression => @expression)
44
+ end
45
+
46
+ def group(key)
47
+ @groups[key] ||= @records.group(key)
48
+ end
49
+
50
+ def each
51
+ @records.each do |record|
52
+ object = instantiate(record)
53
+ next if object.nil?
54
+ yield(object)
55
+ end
56
+ end
57
+
58
+ private
59
+ def instantiate(record)
60
+ @n_key_nested.times do
61
+ return nil if record.nil?
62
+ record = record.key
63
+ end
64
+ return nil if record.nil?
65
+ while record.key.is_a?(Groonga::Record)
66
+ record = record.key
67
+ end
68
+ @klass.instantiate(record)
69
+ end
70
+
71
+ def compute_n_key_nested
72
+ @n_key_nested = 0
73
+ return unless @records.respond_to?(:domain)
74
+ domain = @records.domain
75
+ while domain.is_a?(Groonga::Table)
76
+ @n_key_nested += 1
77
+ domain = domain.domain
78
+ end
79
+ end
80
+
81
+ module PaginationProxy
82
+ Groonga::Pagination.instance_methods.each do |method_name|
83
+ define_method(method_name) do
84
+ @records.send(method_name)
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2009-2010 Kouhei Sutou <kou@clear-code.com>
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -13,209 +13,75 @@
13
13
  # License along with this library; if not, write to the Free Software
14
14
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
15
 
16
+ require 'active_groonga/migrator'
17
+
16
18
  module ActiveGroonga
17
- module Schema
19
+ class Schema
18
20
  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
21
+ def define(options={}, &block)
22
+ new(options).define(&block)
26
23
  end
27
24
 
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(v.to_s)
50
- inserted << v
51
- end
52
- end
53
- end
54
-
55
- def initialize_schema_management_tables
56
- initialize_migrations_table
57
- end
58
-
59
- def create_table(name, options={}, &block)
60
- table_file = File.join(Base.tables_directory, "#{name}.groonga")
61
- table_name = Base.groonga_table_name(name)
62
- options = {:path => table_file}.merge(options)
63
- options = default_table_options(options).merge(options)
64
- options = options.merge(:context => Base.context)
65
- Groonga::Schema.create_table(table_name, options) do |table|
66
- block.call(TableDefinitionWrapper.new(table))
25
+ def dump(options={})
26
+ options ||= {}
27
+ if options.is_a?(Hash)
28
+ options = options.dup
29
+ output = options.delete(:output)
30
+ else
31
+ output, options = options, {}
67
32
  end
33
+ new(options).dump(output)
68
34
  end
35
+ end
69
36
 
70
- def remove_table(name, options={})
71
- options = options.merge(:context => Base.context)
72
- Groonga::Schema.remove_table(name, options)
73
- end
74
- alias_method :drop_table, :remove_table
37
+ def initialize(options={})
38
+ @options = (options || {}).dup
39
+ @version = @options.delete(:version)
40
+ context = @options.delete(:context) || Base.context
41
+ @schema = Groonga::Schema.new(:context => context)
42
+ end
75
43
 
76
- def add_column(table_name, column_name, type, options={})
77
- options_with_context = options.merge(:context => Base.context)
78
- Groonga::Schema.change_table(table_name, options_with_context) do |table|
79
- table = TableDefinitionWrapper.new(table)
80
- table.column(column_name, type, options)
81
- end
82
- end
44
+ def define(&block)
45
+ yield(@schema)
46
+ @schema.define
47
+ update_version if @version
48
+ end
83
49
 
84
- def remove_column(table_name, *column_names)
85
- if column_names.last.is_a?(Hash)
86
- options = columns.pop
50
+ def dump(output=nil)
51
+ dumped_schema = @schema.dump
52
+ return nil if dumped_schema.nil?
53
+
54
+ return_string = false
55
+ if output.nil?
56
+ output = StringIO.new
57
+ return_string = true
58
+ end
59
+ version = @version || management_table.current_version
60
+ output << "ActiveGroonga::Schema.define(:version => #{version}) do |schema|\n"
61
+ output << " schema.instance_eval do\n"
62
+ dumped_schema.each_line do |line|
63
+ if /^\s*$/ =~ line
64
+ output << line
87
65
  else
88
- options = {}
89
- end
90
- options_with_context = options.merge(:context => Base.context)
91
- Groonga::Schema.change_table(table_name, options_with_context) do |table|
92
- column_names.each do |column_name|
93
- table.remove_column(column_name)
94
- end
66
+ output << " #{line}"
95
67
  end
96
68
  end
97
-
98
- def add_index_column(table_name, target_table_name, target_column_name,
99
- options={})
100
- options_for_table = options.reject {|key, value| key == :name}
101
- options_for_table = options_for_table.merge(:context => Base.context)
102
- Groonga::Schema.change_table(table_name, options_for_table) do |table|
103
- table = TableDefinitionWrapper.new(table)
104
- table.index(target_table_name, target_column_name, options)
105
- end
106
- end
107
-
108
- private
109
- def initialize_migrations_table
110
- table_name = Migrator.schema_migrations_table_name
111
- groonga_table_name = Migrator.groonga_schema_migrations_table_name
112
- if Base.context[groonga_table_name].nil?
113
- table_file = File.join(Base.metadata_directory,
114
- "#{table_name}.groonga")
115
- Groonga::Hash.create(:name => groonga_table_name,
116
- :path => table_file,
117
- :key_type => "ShortText")
118
- end
119
- end
120
-
121
- def default_table_options(options)
122
- default_options = {:sub_records => true}
123
- case options[:type]
124
- when :hash, :patricia_trie
125
- default_options[:default_tokenizer] = "TokenBigram"
126
- end
127
- default_options
69
+ output << " end\n"
70
+ output << "end\n"
71
+ if return_string
72
+ output.string
73
+ else
74
+ output
128
75
  end
129
76
  end
130
77
 
131
- class TableDefinitionWrapper
132
- def initialize(definition)
133
- @definition = definition
134
- end
135
-
136
- def column(name, type, options={})
137
- column_file = File.join(Base.columns_directory(@definition.name),
138
- "#{name}.groonga")
139
- options = {:path => column_file}.merge(options)
140
- @definition.column(name, type, options)
141
- end
142
-
143
- def remove_column(name, options={})
144
- @definition.remove_column(name, options)
145
- end
146
- alias_method :remove_index, :remove_column
147
-
148
- def index(target_table_name, target_column_name, options={})
149
- column_name = options.delete(:name)
150
- column_name ||= [target_table_name, target_column_name].join("_")
151
- column_dir = Base.index_columns_directory(@definition.name,
152
- target_table_name.to_s)
153
- column_file = File.join(column_dir, "#{column_name}.groonga")
154
- options = {
155
- :with_position => true,
156
- :path => column_file,
157
- :name => column_name,
158
- }.merge(options)
159
- target_table = @definition.context[target_table_name]
160
- target_column = target_table.column(target_column_name)
161
- @definition.index(target_column, options)
162
- end
163
-
164
- def timestamps(*args)
165
- options = args.extract_options!
166
- column(:created_at, :datetime, options)
167
- column(:updated_at, :datetime, options)
168
- end
169
-
170
- def string(*args)
171
- columns("ShortText", *args)
172
- end
173
-
174
- def text(*args)
175
- columns("Text", *args)
176
- end
177
-
178
- def integer(*args)
179
- columns("Int32", *args)
180
- end
181
-
182
- def float(*args)
183
- columns("Float", *args)
184
- end
185
-
186
- def decimal(*args)
187
- columns("Int64", *args)
188
- end
189
-
190
- def time(*args)
191
- columns("Time", *args)
192
- end
193
- alias_method :datetime, :time
194
- alias_method :timestamp, :time
195
-
196
- def binary(*args)
197
- columns("LongText", *args)
198
- end
199
-
200
- def boolean(*args)
201
- columns("Bool", *args)
202
- end
203
-
204
- def reference(name, table=nil, options={})
205
- table = Base.groonga_table_name(table || name.to_s.pluralize)
206
- column(name, table, options)
207
- end
208
- alias_method :references, :reference
209
- alias_method :belongs_to, :references
78
+ private
79
+ def management_table
80
+ @management_table ||= SchemaManagementTable.new
81
+ end
210
82
 
211
- private
212
- def columns(type, *args)
213
- options = args.extract_options!
214
- column_names = args
215
- column_names.each do |name|
216
- column(name, type, options)
217
- end
218
- end
83
+ def update_version
84
+ management_table.update_version(@version)
219
85
  end
220
86
  end
221
87
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
2
2
  #
3
3
  # This library is free software; you can redistribute it and/or
4
4
  # modify it under the terms of the GNU Lesser General Public
@@ -14,13 +14,62 @@
14
14
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15
15
 
16
16
  module ActiveGroonga
17
+ class RecordInvalid < Error
18
+ attr_reader :record
19
+ def initialize(record)
20
+ @record = record
21
+ errors = @record.errors.full_messages.join(", ")
22
+ super(I18n.t("activegroonga.errors.messages.record_invalid",
23
+ :errors => errors))
24
+ end
25
+ end
26
+
17
27
  module Validations
18
- class << self
19
- def included(base)
20
- base.class_eval do
21
- include ActiveRecord::Validations
28
+ extend ActiveSupport::Concern
29
+ include ActiveModel::Validations
30
+
31
+ included do
32
+ validates_presence_of(:key,
33
+ :on => :create,
34
+ :if => lambda {|record| record.table.support_key?})
35
+ end
36
+
37
+ module ClassMethods
38
+ def create!(attributes=nil, &block)
39
+ if attributes.is_a?(Array)
40
+ attributes.collect do |nested_attributes|
41
+ create!(nested_attributes, &block)
42
+ end
43
+ else
44
+ object = new(attributes)
45
+ yield(object) if block_given?
46
+ object.save!
47
+ object
22
48
  end
23
49
  end
24
50
  end
51
+
52
+ def save(options={})
53
+ validate(options) ? super : false
54
+ end
55
+
56
+ def save!(options={})
57
+ validate(options) ? super : raise(RecordInvalid.new(self))
58
+ end
59
+
60
+ def valid?(context=nil)
61
+ context ||= (new_record? ? :create : :update)
62
+ valid = super(context)
63
+ errors.empty? and valid
64
+ end
65
+
66
+ private
67
+ def validate(options={})
68
+ if options[:validate] == false
69
+ true
70
+ else
71
+ valid?(options[:context])
72
+ end
73
+ end
25
74
  end
26
75
  end
@@ -0,0 +1,64 @@
1
+ # Copyright (C) 2010 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 Vector
18
+ include Enumerable
19
+
20
+ attr_reader :owner, :klass, :values
21
+ def initialize(owner, klass, values=[])
22
+ @owner = owner
23
+ @klass = klass
24
+ @values = values
25
+ @values = [@values] unless @values.is_a?(Array)
26
+ end
27
+
28
+ def build(*args, &block)
29
+ @klass.new(*args, &block)
30
+ end
31
+
32
+ def create(*args, &block)
33
+ @klass.create(*args, &block)
34
+ end
35
+
36
+ def create!(*args, &block)
37
+ @klass.create!(*args, &block)
38
+ end
39
+
40
+ def each
41
+ @values.each do |value|
42
+ yield(instantiate(value))
43
+ end
44
+ end
45
+
46
+ def <<(value)
47
+ value = @klass.create(value) if @owner.persisted?
48
+ @values << value
49
+ end
50
+
51
+ def to_ary
52
+ to_a
53
+ end
54
+
55
+ private
56
+ def instantiate(value)
57
+ if value.is_a?(@klass)
58
+ value
59
+ else
60
+ @klass.instantiate(value)
61
+ end
62
+ end
63
+ end
64
+ end