xapit 0.1.0 → 0.2.0
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.
- data/CHANGELOG +27 -0
- data/Manifest +16 -1
- data/README.rdoc +29 -15
- data/Rakefile +1 -1
- data/features/facets.feature +40 -1
- data/features/finding.feature +15 -59
- data/features/sorting.feature +29 -0
- data/features/step_definitions/xapit_steps.rb +11 -3
- data/features/suggestions.feature +17 -0
- data/features/support/xapit_helpers.rb +1 -1
- data/install.rb +7 -8
- data/lib/xapit.rb +34 -2
- data/lib/xapit/adapters/abstract_adapter.rb +46 -0
- data/lib/xapit/adapters/active_record_adapter.rb +20 -0
- data/lib/xapit/adapters/data_mapper_adapter.rb +10 -0
- data/lib/xapit/collection.rb +17 -5
- data/lib/xapit/config.rb +1 -9
- data/lib/xapit/facet.rb +11 -8
- data/lib/xapit/index_blueprint.rb +9 -3
- data/lib/xapit/indexers/abstract_indexer.rb +13 -2
- data/lib/xapit/indexers/classic_indexer.rb +5 -3
- data/lib/xapit/indexers/simple_indexer.rb +15 -8
- data/lib/xapit/membership.rb +19 -1
- data/lib/xapit/query.rb +40 -15
- data/lib/xapit/query_parsers/abstract_query_parser.rb +46 -24
- data/lib/xapit/rake_tasks.rb +13 -0
- data/rails_generators/xapit/USAGE +13 -0
- data/rails_generators/xapit/templates/setup_xapit.rb +1 -0
- data/rails_generators/xapit/templates/xapit.rake +4 -0
- data/rails_generators/xapit/xapit_generator.rb +20 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/xapit/adapters/active_record_adapter_spec.rb +31 -0
- data/spec/xapit/adapters/data_mapper_adapter_spec.rb +10 -0
- data/spec/xapit/facet_option_spec.rb +2 -2
- data/spec/xapit/index_blueprint_spec.rb +11 -3
- data/spec/xapit/indexers/abstract_indexer_spec.rb +37 -0
- data/spec/xapit/indexers/classic_indexer_spec.rb +9 -0
- data/spec/xapit/indexers/simple_indexer_spec.rb +22 -6
- data/spec/xapit/membership_spec.rb +16 -0
- data/spec/xapit/query_parsers/abstract_query_parser_spec.rb +21 -3
- data/spec/xapit/query_spec.rb +21 -0
- data/spec/xapit_member.rb +13 -2
- data/tasks/xapit.rake +1 -9
- data/tmp/xapiandatabase/postlist.DB +0 -0
- data/tmp/xapiandatabase/postlist.baseB +0 -0
- data/tmp/xapiandatabase/record.DB +0 -0
- data/tmp/xapiandatabase/record.baseB +0 -0
- data/tmp/xapiandatabase/spelling.DB +0 -0
- data/tmp/xapiandatabase/spelling.baseB +0 -0
- data/tmp/xapiandatabase/termlist.DB +0 -0
- data/tmp/xapiandatabase/termlist.baseB +0 -0
- data/tmp/xapiandatabase/value.DB +0 -0
- data/tmp/xapiandatabase/value.baseA +0 -0
- data/tmp/xapiandb/spelling.DB +0 -0
- data/tmp/xapiandb/spelling.baseB +0 -0
- data/xapit.gemspec +4 -4
- metadata +23 -3
@@ -0,0 +1,13 @@
|
|
1
|
+
# TODO investigate why this is needed to ensure it doesn't load twice
|
2
|
+
unless @xapit_rake_loaded
|
3
|
+
@xapit_rake_loaded = true
|
4
|
+
namespace :xapit do
|
5
|
+
desc "Index all xapit models."
|
6
|
+
task :index => :environment do
|
7
|
+
Xapit.remove_database
|
8
|
+
Xapit.index_all do |member_class|
|
9
|
+
puts "Indexing #{member_class.name}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Description:
|
2
|
+
Generates files necessary to setup Xapit. This includes an initializer
|
3
|
+
to specify the configuration (setup_xapit.rb) and a rake file to load
|
4
|
+
the rake tasks (xapit.rake).
|
5
|
+
|
6
|
+
IMPORTANT: Only use this generator if you are using the gem version of
|
7
|
+
Xapit, it is not needed if you are installing via Rails plugin.
|
8
|
+
|
9
|
+
Examples:
|
10
|
+
script/generate xapit
|
11
|
+
|
12
|
+
Initializer: config/initializers/setup_xapit.rb
|
13
|
+
Rake Tasks: lib/tasks/xapit.rake
|
@@ -0,0 +1 @@
|
|
1
|
+
Xapit.setup(:database_path => "#{Rails.root}/db/xapiandb")
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class XapitGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
m.directory "config/initializers"
|
5
|
+
m.file "setup_xapit.rb", "config/initializers/setup_xapit.rb"
|
6
|
+
|
7
|
+
m.directory "lib/tasks"
|
8
|
+
m.file "xapit.rake", "lib/tasks/xapit.rake"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
def banner
|
14
|
+
<<-EOS
|
15
|
+
Generates files necessary to setup Xapit.
|
16
|
+
|
17
|
+
USAGE: #{$0} #{spec.name}
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,8 +8,8 @@ require File.dirname(__FILE__) + '/xapit_member'
|
|
8
8
|
Spec::Runner.configure do |config|
|
9
9
|
config.mock_with :rr
|
10
10
|
config.before(:each) do
|
11
|
-
Xapit
|
12
|
-
Xapit
|
11
|
+
Xapit.setup(:database_path => File.dirname(__FILE__) + '/tmp/xapiandb')
|
12
|
+
Xapit.remove_database
|
13
13
|
XapitMember.delete_all
|
14
14
|
end
|
15
15
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::ActiveRecordAdapter do
|
4
|
+
it "should be used for ActiveRecord::Base subclasses" do
|
5
|
+
Xapit::ActiveRecordAdapter.should_not be_for_class(Object)
|
6
|
+
klass = Object.new
|
7
|
+
stub(klass).ancestors { ["ActiveRecord::Base"] }
|
8
|
+
Xapit::ActiveRecordAdapter.should be_for_class(klass)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should pass find_single to find method to target" do
|
12
|
+
target = Object.new
|
13
|
+
mock(target).find(1) { :record }
|
14
|
+
adapter = Xapit::ActiveRecordAdapter.new(target)
|
15
|
+
adapter.find_single(1).should == :record
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should pass find_multiple to find method to target" do
|
19
|
+
target = Object.new
|
20
|
+
mock(target).find([1, 2]) { :record }
|
21
|
+
adapter = Xapit::ActiveRecordAdapter.new(target)
|
22
|
+
adapter.find_multiple([1, 2]).should == :record
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should pass find_each to target" do
|
26
|
+
target = Object.new
|
27
|
+
mock(target).find_each(:args) { 5 }
|
28
|
+
adapter = Xapit::ActiveRecordAdapter.new(target)
|
29
|
+
adapter.find_each(:args).should == 5
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
+
|
3
|
+
describe Xapit::DataMapperAdapter do
|
4
|
+
it "should be used for DataMapper::Resource model" do
|
5
|
+
Xapit::DataMapperAdapter.should_not be_for_class(Object)
|
6
|
+
klass = Object.new
|
7
|
+
stub(klass).ancestors { ["DataMapper::Resource"] }
|
8
|
+
Xapit::DataMapperAdapter.should be_for_class(klass)
|
9
|
+
end
|
10
|
+
end
|
@@ -9,7 +9,7 @@ describe Xapit::FacetOption do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should remove current identifier from previous identifiers if it exists" do
|
12
|
-
Xapit
|
12
|
+
Xapit.setup(:breadcrumb_facets => false)
|
13
13
|
option = Xapit::FacetOption.new(nil, nil, nil)
|
14
14
|
option.existing_facet_identifiers = ["abc", "123", "foo"]
|
15
15
|
stub(option).identifier { "foo" }
|
@@ -17,7 +17,7 @@ describe Xapit::FacetOption do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should support breadcrumb style facets" do
|
20
|
-
Xapit
|
20
|
+
Xapit.setup(:breadcrumb_facets => true)
|
21
21
|
option = Xapit::FacetOption.new(nil, nil, nil)
|
22
22
|
option.existing_facet_identifiers = ["abc", "123", "foo"]
|
23
23
|
stub(option).identifier { "123" }
|
@@ -2,6 +2,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
|
2
2
|
|
3
3
|
describe Xapit::IndexBlueprint do
|
4
4
|
before(:each) do
|
5
|
+
XapitMember.xapit { } # call so methods are generated
|
5
6
|
@index = Xapit::IndexBlueprint.new(XapitMember)
|
6
7
|
end
|
7
8
|
|
@@ -36,7 +37,14 @@ describe Xapit::IndexBlueprint do
|
|
36
37
|
@index.facet(:foo)
|
37
38
|
@index.facet(:test)
|
38
39
|
@index.sortable(:bar, :blah)
|
39
|
-
@index.
|
40
|
+
@index.position_of_sortable(:blah).should == 3
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should have a field position offset by facets + sortable" do
|
44
|
+
@index.facet(:foo)
|
45
|
+
@index.sortable(:bar, :blah)
|
46
|
+
@index.field(:bar, :blah)
|
47
|
+
@index.position_of_field(:blah).should == 4
|
40
48
|
end
|
41
49
|
|
42
50
|
it "should index member document into database" do
|
@@ -53,8 +61,8 @@ describe Xapit::IndexBlueprint do
|
|
53
61
|
end
|
54
62
|
|
55
63
|
it "should pass in extra arguments to each method" do
|
56
|
-
index = Xapit::IndexBlueprint.new(
|
57
|
-
mock(
|
64
|
+
index = Xapit::IndexBlueprint.new(XapitMember, :foo, :bar => :blah)
|
65
|
+
mock(XapitMember).find_each(:foo, :bar => :blah)
|
58
66
|
index.index_all
|
59
67
|
end
|
60
68
|
end
|
@@ -71,4 +71,41 @@ describe Xapit::AbstractIndexer do
|
|
71
71
|
@index.field(:created_on)
|
72
72
|
@indexer.field_terms(member).should == ["Xcreated_on-#{member.created_on.to_time.to_i}"]
|
73
73
|
end
|
74
|
+
|
75
|
+
it "should use sortable_serialze for numeric sortable" do
|
76
|
+
member = Object.new
|
77
|
+
stub(member).age { 7.89 }
|
78
|
+
@index.sortable(:age)
|
79
|
+
@indexer.values(member).should == [Xapian.sortable_serialise(7.89)]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should only use first value if sortable attribute is an array" do
|
83
|
+
member = Object.new
|
84
|
+
stub(member).age { [1, 2] }
|
85
|
+
@index.sortable(:age)
|
86
|
+
@indexer.values(member).should == [Xapian.sortable_serialise(1)]
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should add sortable_serialze value for numeric field" do
|
90
|
+
member = Object.new
|
91
|
+
stub(member).age { [1, 2] }
|
92
|
+
@index.field(:age)
|
93
|
+
@indexer.values(member).should == [Xapian.sortable_serialise(1)]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should use sortable_serialze for date field" do
|
97
|
+
date = Date.today
|
98
|
+
member = Object.new
|
99
|
+
stub(member).age { date }
|
100
|
+
@index.field(:age)
|
101
|
+
@indexer.values(member).should == [Xapian.sortable_serialise(date.to_time.to_i)]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should use sortable_serialze for time field" do
|
105
|
+
time = Time.now
|
106
|
+
member = Object.new
|
107
|
+
stub(member).age { time }
|
108
|
+
@index.field(:age)
|
109
|
+
@indexer.values(member).should == [Xapian.sortable_serialise(time.to_i)]
|
110
|
+
end
|
74
111
|
end
|
@@ -23,4 +23,13 @@ describe Xapit::ClassicIndexer do
|
|
23
23
|
@indexer.index_text_attributes(member, document)
|
24
24
|
document.terms.map(&:term).sort.should == %w[6].sort
|
25
25
|
end
|
26
|
+
|
27
|
+
it "should return terms separated by array" do
|
28
|
+
member = Object.new
|
29
|
+
stub(member).description { ["foo bar", 6, "", nil] }
|
30
|
+
@index.text(:description)
|
31
|
+
document = Xapian::Document.new
|
32
|
+
@indexer.index_text_attributes(member, document)
|
33
|
+
document.terms.map(&:term).sort.should == ["foo bar", "6"].sort
|
34
|
+
end
|
26
35
|
end
|
@@ -10,21 +10,21 @@ describe Xapit::SimpleIndexer do
|
|
10
10
|
member = Object.new
|
11
11
|
stub(member).description { "This is a test" }
|
12
12
|
@index.text(:description)
|
13
|
-
@indexer.
|
13
|
+
@indexer.terms_for_attribute(member, :description, {}).should == %w[this is a test]
|
14
14
|
end
|
15
15
|
|
16
|
-
it "should return text
|
16
|
+
it "should return text terms with stemming added" do
|
17
17
|
member = Object.new
|
18
18
|
stub(member).description { "jumping high" }
|
19
19
|
@index.text(:description)
|
20
|
-
@indexer.
|
20
|
+
@indexer.stemmed_terms_for_attribute(member, :description, {}).should == %w[Zjump Zhigh]
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should convert attribute to string when converting text to terms" do
|
24
24
|
member = Object.new
|
25
25
|
stub(member).num { 123 }
|
26
26
|
@index.text(:num)
|
27
|
-
@indexer.
|
27
|
+
@indexer.terms_for_attribute(member, :num, {}).should == %w[123]
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should add text terms to document when indexing attributes" do
|
@@ -32,14 +32,14 @@ describe Xapit::SimpleIndexer do
|
|
32
32
|
stub(@indexer).terms_for_attribute { %w[term list] }
|
33
33
|
document = Xapian::Document.new
|
34
34
|
@indexer.index_text_attributes(nil, document)
|
35
|
-
document.terms.map(&:term).sort.should == %w[
|
35
|
+
document.terms.map(&:term).sort.should == %w[Zlist Zterm list term].sort
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should use given block to generate text terms" do
|
39
39
|
member = Object.new
|
40
40
|
stub(member).name { "foobar" }
|
41
41
|
proc = lambda { |t| [t.length] }
|
42
|
-
@indexer.
|
42
|
+
@indexer.terms_for_attribute(member, :name, { :proc => proc }).should == ["6"]
|
43
43
|
end
|
44
44
|
|
45
45
|
it "should increment term frequency by weight option" do
|
@@ -50,4 +50,20 @@ describe Xapit::SimpleIndexer do
|
|
50
50
|
@indexer.index_text_attributes(member, document)
|
51
51
|
document.terms.first.wdf.should == 10
|
52
52
|
end
|
53
|
+
|
54
|
+
it "should increment term frequency by weight option" do
|
55
|
+
member = Object.new
|
56
|
+
stub(member).description { "This is a test" }
|
57
|
+
@index.text(:description, :weight => 10)
|
58
|
+
document = Xapian::Document.new
|
59
|
+
@indexer.index_text_attributes(member, document)
|
60
|
+
document.terms.first.wdf.should == 10
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return terms separated by array" do
|
64
|
+
member = Object.new
|
65
|
+
stub(member).description { ["foo bar", 6, "", nil] }
|
66
|
+
@index.text(:description)
|
67
|
+
@indexer.terms_for_attribute(member, :description, {}).should == ["foo bar", "6"]
|
68
|
+
end
|
53
69
|
end
|
@@ -21,11 +21,13 @@ describe XapitMember do
|
|
21
21
|
XapitMember.xapit do |index|
|
22
22
|
index.text :description
|
23
23
|
end
|
24
|
+
XapitMember.instance_variable_set("@xapit_adapter", nil)
|
24
25
|
end
|
25
26
|
|
26
27
|
it "should have xapit index blueprint" do
|
27
28
|
XapitMember.xapit_index_blueprint.should be_kind_of(Xapit::IndexBlueprint)
|
28
29
|
end
|
30
|
+
|
29
31
|
it "should return collection from search" do
|
30
32
|
XapitMember.search("foo").class.should == Xapit::Collection
|
31
33
|
end
|
@@ -35,5 +37,19 @@ describe XapitMember do
|
|
35
37
|
member.xapit_relevance = 123
|
36
38
|
member.xapit_relevance.should == 123
|
37
39
|
end
|
40
|
+
|
41
|
+
it "should have an adapter" do
|
42
|
+
XapitMember.xapit_adapter.class.should == Xapit::ActiveRecordAdapter
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should use DataMapper adapter if that is ancestor" do
|
46
|
+
stub(XapitMember).ancestors { ["DataMapper::Resource"] }
|
47
|
+
XapitMember.xapit_adapter.class.should == Xapit::DataMapperAdapter
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should raise an exception when no adapter is found" do
|
51
|
+
stub(XapitMember).ancestors { [] }
|
52
|
+
lambda { XapitMember.xapit_adapter }.should raise_error
|
53
|
+
end
|
38
54
|
end
|
39
55
|
end
|
@@ -4,20 +4,38 @@ describe Xapit::AbstractQueryParser do
|
|
4
4
|
before(:each) do
|
5
5
|
end
|
6
6
|
|
7
|
-
it "parse conditions hash into terms" do
|
7
|
+
it "should parse conditions hash into terms" do
|
8
8
|
parser = Xapit::AbstractQueryParser.new(:conditions => { :foo => 'bar', 'hello' => :world })
|
9
9
|
parser.condition_terms.sort.should == ["Xfoo-bar", "Xhello-world"].sort
|
10
10
|
end
|
11
11
|
|
12
|
-
it "convert time into integer before placing in condition term" do
|
12
|
+
it "should convert time into integer before placing in condition term" do
|
13
13
|
time = Time.now
|
14
14
|
parser = Xapit::AbstractQueryParser.new(:conditions => { :time => time })
|
15
15
|
parser.condition_terms.should == ["Xtime-#{time.to_i}"]
|
16
16
|
end
|
17
17
|
|
18
|
-
it "convert date into time then integer before placing in condition term" do
|
18
|
+
it "should convert date into time then integer before placing in condition term" do
|
19
19
|
date = Date.today
|
20
20
|
parser = Xapit::AbstractQueryParser.new(:conditions => { :date => date })
|
21
21
|
parser.condition_terms.should == ["Xdate-#{date.to_time.to_i}"]
|
22
22
|
end
|
23
|
+
|
24
|
+
it "should give spelling suggestion on full term" do
|
25
|
+
Xapit::Config.writable_database.add_spelling("foo bar")
|
26
|
+
parser = Xapit::AbstractQueryParser.new(nil, "foo barr")
|
27
|
+
parser.spelling_suggestion.should == "foo bar"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should allow an array of conditions to be specified and use OR xapian query." do
|
31
|
+
parser = Xapit::AbstractQueryParser.new(:not_conditions => { :foo => %w[hello world]})
|
32
|
+
parser.not_condition_terms.first.xapian_query.description.should == Xapit::Query.new(%w[Xfoo-hello Xfoo-world], :or).xapian_query.description
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow range condition to be specified and use VALUE_RANGE xapian query." do
|
36
|
+
XapitMember.xapit { |i| i.field :foo }
|
37
|
+
expected = Xapian::Query.new(Xapian::Query::OP_VALUE_RANGE, 0, Xapian.sortable_serialise(2), Xapian.sortable_serialise(5))
|
38
|
+
parser = Xapit::AbstractQueryParser.new(XapitMember, :conditions => { :foo => 2..5 })
|
39
|
+
parser.condition_terms.first.description.should == expected.description
|
40
|
+
end
|
23
41
|
end
|
data/spec/xapit/query_spec.rb
CHANGED
@@ -19,6 +19,12 @@ describe Xapit::Query do
|
|
19
19
|
query.xapian_query.description.should == expected.description
|
20
20
|
end
|
21
21
|
|
22
|
+
it "should build a query from an array of strings with :or operator" do
|
23
|
+
expected = Xapian::Query.new(Xapian::Query::OP_OR, %w[foo bar])
|
24
|
+
query = Xapit::Query.new(%w[foo bar], :or)
|
25
|
+
query.xapian_query.description.should == expected.description
|
26
|
+
end
|
27
|
+
|
22
28
|
it "should AND two queries together" do
|
23
29
|
expected = Xapian::Query.new(Xapian::Query::OP_AND,
|
24
30
|
Xapian::Query.new(Xapian::Query::OP_AND, ["foo"]),
|
@@ -38,4 +44,19 @@ describe Xapit::Query do
|
|
38
44
|
query.or_query("bar")
|
39
45
|
query.xapian_query.description.should == expected.description
|
40
46
|
end
|
47
|
+
|
48
|
+
it "should build a query from an array of mixed strings and queries" do
|
49
|
+
expected = Xapian::Query.new(Xapian::Query::OP_AND,
|
50
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["foo"]),
|
51
|
+
Xapian::Query.new(Xapian::Query::OP_AND, ["bar"])
|
52
|
+
)
|
53
|
+
query = Xapit::Query.new([Xapit::Query.new("foo"), Xapian::Query.new(Xapian::Query::OP_AND, ["bar"])])
|
54
|
+
query.xapian_query.description.should == expected.description
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should use xapit query passed in" do
|
58
|
+
expected = Xapian::Query.new(Xapian::Query::OP_AND, ["foo bar"])
|
59
|
+
query = Xapit::Query.new(Xapit::Query.new("foo bar"))
|
60
|
+
query.xapian_query.description.should == expected.description
|
61
|
+
end
|
41
62
|
end
|
data/spec/xapit_member.rb
CHANGED
@@ -3,6 +3,12 @@ class XapitMember
|
|
3
3
|
|
4
4
|
attr_reader :id
|
5
5
|
|
6
|
+
# Make it look like this inherits from ActiveRecord::Base
|
7
|
+
# so it will use the ActiveRecord adapter.
|
8
|
+
def self.ancestors
|
9
|
+
["ActiveRecord::Base"]
|
10
|
+
end
|
11
|
+
|
6
12
|
def self.find_each(&block)
|
7
13
|
@@records.each(&block) if @@records
|
8
14
|
end
|
@@ -11,8 +17,13 @@ class XapitMember
|
|
11
17
|
@@records = []
|
12
18
|
end
|
13
19
|
|
14
|
-
def self.find(
|
15
|
-
|
20
|
+
def self.find(ids)
|
21
|
+
if ids.kind_of? Array
|
22
|
+
# change the order to mimic database where we can't predict the order
|
23
|
+
ids.sort.map { |id| @@records.detect { |r| r.id == id.to_i } }
|
24
|
+
else
|
25
|
+
@@records.detect { |r| r.id == ids.to_i }
|
26
|
+
end
|
16
27
|
end
|
17
28
|
|
18
29
|
def initialize(attributes = {})
|
data/tasks/xapit.rake
CHANGED
@@ -1,9 +1 @@
|
|
1
|
-
|
2
|
-
desc "Index all xapit models."
|
3
|
-
task :index => :environment do
|
4
|
-
Xapit::Config.remove_database
|
5
|
-
Xapit.index_all do |member_class|
|
6
|
-
puts "Indexing #{member_class.name}"
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
1
|
+
require File.join(File.dirname(__FILE__), '/../lib/xapit/rake_tasks')
|