ts-datetime-delta 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.textile +50 -0
- data/features/datetime_deltas.feature +66 -0
- data/features/step_definitions/common_steps.rb +61 -0
- data/features/step_definitions/datetime_delta_steps.rb +15 -0
- data/features/support/database.example.yml +3 -0
- data/features/support/database.yml +5 -0
- data/features/support/db/fixtures/thetas.rb +10 -0
- data/features/support/db/migrations/create_thetas.rb +5 -0
- data/features/support/env.rb +17 -0
- data/features/support/models/theta.rb +7 -0
- data/lib/thinking_sphinx/deltas/datetime_delta.rb +124 -0
- data/lib/thinking_sphinx/deltas/datetime_delta/tasks.rb +23 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/thinking_sphinx/deltas/datetime_delta_spec.rb +130 -0
- metadata +99 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Pat Allan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
h1. Datetime Deltas for Thinking Sphinx
|
2
|
+
|
3
|
+
h2. Installation
|
4
|
+
|
5
|
+
You'll need Thinking Sphinx 1.3.0 or later.
|
6
|
+
|
7
|
+
<pre><code>gem install ts-datetime-delta --source http://gemcutter.org</code></pre>
|
8
|
+
|
9
|
+
In your @environment.rb@ file, with the rest of your gem dependencies:
|
10
|
+
|
11
|
+
<pre><code>config.gem 'ts-datetime-delta',
|
12
|
+
:lib => 'thinking_sphinx/deltas/datetime_delta'
|
13
|
+
:version => '>= 1.0.0',
|
14
|
+
:source => 'http://gemcutter.org'</code></pre>
|
15
|
+
|
16
|
+
And add the following line to the bottom of your @Rakefile@:
|
17
|
+
|
18
|
+
<pre><code>require 'thinking_sphinx/deltas/datetime_delta/tasks'</code></pre>
|
19
|
+
|
20
|
+
h2. Usage
|
21
|
+
|
22
|
+
For the indexes you want to use this delta approach, make sure you set that up in their @define_index@ blocks.
|
23
|
+
|
24
|
+
<pre><code>define_index do
|
25
|
+
# ...
|
26
|
+
|
27
|
+
set_property :delta => :datetime
|
28
|
+
end</code></pre>
|
29
|
+
|
30
|
+
If you want to use a column other than @updated_at@, you can specify it using the @:delta_column@ option. The same goes for the threshold, which defaults to one day.
|
31
|
+
|
32
|
+
<pre><code>set_property :delta => :datetime,
|
33
|
+
:threshold => 1.hour,
|
34
|
+
:delta_column => :changed_at</code></pre>
|
35
|
+
|
36
|
+
Then, while your Rails application is running, you'll need to run the delta indexing rake task regularly - as often as your threshold, allowing for some time for the indexing to actually happen.
|
37
|
+
|
38
|
+
For example, if you're going to run the delta indexing task every hour, I would recommend setting your threshold to 70 minutes.
|
39
|
+
|
40
|
+
To ensure this rake task is called regularly, it's best to set it up as a recurring task via cron or similar tools.
|
41
|
+
|
42
|
+
<pre><code>rake thinking_sphinx:index:delta</code></pre>
|
43
|
+
|
44
|
+
The shorthand version is:
|
45
|
+
|
46
|
+
<pre><code>rake ts:in:delta</code></pre>
|
47
|
+
|
48
|
+
h2. Copyright
|
49
|
+
|
50
|
+
Copyright (c) 2009 Pat Allan, and released under an MIT Licence.
|
@@ -0,0 +1,66 @@
|
|
1
|
+
Feature: Datetime Delta Indexing
|
2
|
+
In order to have delta indexing on frequently-updated sites
|
3
|
+
Developers
|
4
|
+
Should be able to use an existing datetime column to track changes
|
5
|
+
|
6
|
+
Scenario: Delta Index should not fire automatically
|
7
|
+
Given Sphinx is running
|
8
|
+
And I am searching on thetas
|
9
|
+
When I search for one
|
10
|
+
Then I should get 1 result
|
11
|
+
|
12
|
+
When I change the name of theta one to eleven
|
13
|
+
And I wait for Sphinx to catch up
|
14
|
+
And I search for one
|
15
|
+
Then I should get 1 result
|
16
|
+
|
17
|
+
When I search for eleven
|
18
|
+
Then I should get 0 results
|
19
|
+
|
20
|
+
Scenario: Delta Index should fire when jobs are run
|
21
|
+
Given Sphinx is running
|
22
|
+
And I am searching on thetas
|
23
|
+
When I search for two
|
24
|
+
Then I should get 1 result
|
25
|
+
|
26
|
+
When I change the name of theta two to twelve
|
27
|
+
And I wait for Sphinx to catch up
|
28
|
+
And I search for twelve
|
29
|
+
Then I should get 0 results
|
30
|
+
|
31
|
+
When I index the theta datetime delta
|
32
|
+
And I wait for Sphinx to catch up
|
33
|
+
And I search for twelve
|
34
|
+
Then I should get 1 result
|
35
|
+
|
36
|
+
When I search for two
|
37
|
+
Then I should get 0 results
|
38
|
+
|
39
|
+
Scenario: New records should be merged into the core index
|
40
|
+
Given Sphinx is running
|
41
|
+
And I am searching on thetas
|
42
|
+
When I search for thirteen
|
43
|
+
Then I should get 0 results
|
44
|
+
|
45
|
+
When I create a new theta named thirteen
|
46
|
+
And I search for thirteen
|
47
|
+
Then I should get 0 results
|
48
|
+
|
49
|
+
When I index the theta datetime delta
|
50
|
+
And I wait for Sphinx to catch up
|
51
|
+
And I search for thirteen
|
52
|
+
Then I should get 1 result
|
53
|
+
|
54
|
+
When I search for the document id of theta thirteen in the theta_core index
|
55
|
+
Then it should exist
|
56
|
+
|
57
|
+
Scenario: Deleting records
|
58
|
+
Given Sphinx is running
|
59
|
+
And I am searching on thetas
|
60
|
+
When I search for three
|
61
|
+
Then I should get 1 result
|
62
|
+
|
63
|
+
When I delete the theta named three
|
64
|
+
And I wait for Sphinx to catch up
|
65
|
+
And I search for three
|
66
|
+
Then I should get 0 results
|
@@ -0,0 +1,61 @@
|
|
1
|
+
Before do
|
2
|
+
$queries_executed = []
|
3
|
+
|
4
|
+
@model = nil
|
5
|
+
@method = :search
|
6
|
+
@query = ""
|
7
|
+
@conditions = {}
|
8
|
+
@with = {}
|
9
|
+
@without = {}
|
10
|
+
@with_all = {}
|
11
|
+
@options = {}
|
12
|
+
@results = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
Given "Sphinx is running" do
|
16
|
+
ThinkingSphinx::Configuration.instance.controller.should be_running
|
17
|
+
end
|
18
|
+
|
19
|
+
Given /^I am searching on (.+)$/ do |model|
|
20
|
+
@model = model.gsub(/\s/, '_').singularize.camelize.constantize
|
21
|
+
end
|
22
|
+
|
23
|
+
When "I wait for Sphinx to catch up" do
|
24
|
+
sleep(0.25)
|
25
|
+
end
|
26
|
+
|
27
|
+
When /^I search for (\w+)$/ do |query|
|
28
|
+
@results = nil
|
29
|
+
@query = query
|
30
|
+
end
|
31
|
+
|
32
|
+
When /^I search for the document id of (\w+) (\w+) in the (\w+) index$/ do |model, name, index|
|
33
|
+
model = model.gsub(/\s/, '_').camelize.constantize
|
34
|
+
@id = model.find_by_name(name).sphinx_document_id
|
35
|
+
@index = index
|
36
|
+
end
|
37
|
+
|
38
|
+
Then /^I should get (\d+) results?$/ do |count|
|
39
|
+
results.length.should == count.to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
Then "it should exist" do
|
43
|
+
ThinkingSphinx::Search.search_for_id(@id, @index).should == true
|
44
|
+
end
|
45
|
+
|
46
|
+
Then "it should not exist" do
|
47
|
+
ThinkingSphinx::Search.search_for_id(@id, @index).should == false
|
48
|
+
end
|
49
|
+
|
50
|
+
def results
|
51
|
+
@results ||= (@model || ThinkingSphinx).send(
|
52
|
+
@method,
|
53
|
+
@query,
|
54
|
+
@options.merge(
|
55
|
+
:conditions => @conditions,
|
56
|
+
:with => @with,
|
57
|
+
:without => @without,
|
58
|
+
:with_all => @with_all
|
59
|
+
)
|
60
|
+
)
|
61
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
When /^I index the theta datetime delta$/ do
|
2
|
+
Theta.sphinx_indexes.first.delta_object.delayed_index(Theta)
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I change the name of theta (\w+) to (\w+)$/ do |current, replacement|
|
6
|
+
Theta.find_by_name(current).update_attributes(:name => replacement)
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I create a new theta named (\w+)$/ do |name|
|
10
|
+
Theta.create(:name => name)
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I delete the theta named (\w+)$/ do |name|
|
14
|
+
Theta.find_by_name(name).destroy
|
15
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Theta.create :name => "one"
|
2
|
+
Theta.create :name => "two"
|
3
|
+
Theta.create :name => "three"
|
4
|
+
Theta.create :name => "four"
|
5
|
+
Theta.create :name => "five"
|
6
|
+
Theta.create :name => "six"
|
7
|
+
Theta.create :name => "seven"
|
8
|
+
Theta.create :name => "eight"
|
9
|
+
Theta.create :name => "nine"
|
10
|
+
Theta.create :name => "ten"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'cucumber'
|
3
|
+
require 'spec/expectations'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'active_record'
|
6
|
+
|
7
|
+
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
8
|
+
|
9
|
+
require 'cucumber/thinking_sphinx/internal_world'
|
10
|
+
|
11
|
+
world = Cucumber::ThinkingSphinx::InternalWorld.new
|
12
|
+
world.configure_database
|
13
|
+
|
14
|
+
require 'thinking_sphinx'
|
15
|
+
require 'thinking_sphinx/deltas/datetime_delta'
|
16
|
+
|
17
|
+
world.setup
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# Datetime Deltas for Thinking Sphinx
|
2
|
+
#
|
3
|
+
# This documentation is aimed at those reading the code. If you're looking for
|
4
|
+
# a guide to Thinking Sphinx and/or deltas, I recommend you start with the
|
5
|
+
# Thinking Sphinx site instead - or the README for this library at the very
|
6
|
+
# least.
|
7
|
+
#
|
8
|
+
# @author Patrick Allan
|
9
|
+
# @see http://ts.freelancing-gods.com Thinking Sphinx
|
10
|
+
#
|
11
|
+
class ThinkingSphinx::Deltas::DatetimeDelta < ThinkingSphinx::Deltas::DefaultDelta
|
12
|
+
attr_accessor :column, :threshold
|
13
|
+
|
14
|
+
# Initialises the Delta object for the given index and settings. All handled
|
15
|
+
# by Thinking Sphinx, so you shouldn't need to call this method yourself in
|
16
|
+
# general day-to-day situations.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# ThinkingSphinx::Deltas::DatetimeDelta.new index,
|
20
|
+
# :delta_column => :updated_at,
|
21
|
+
# :threshold => 1.day
|
22
|
+
#
|
23
|
+
# @param [ThinkingSphinx::Index] index the index using this delta object
|
24
|
+
# @param [Hash] options a hash of options for the index
|
25
|
+
# @option options [Symbol] :delta_column (:updated_at) The column to use for
|
26
|
+
# tracking when a record has changed. Default to :updated_at.
|
27
|
+
# @option options [Integer] :threshold (1.day) The window of time to store
|
28
|
+
# changes for, in seconds. Defaults to one day.
|
29
|
+
#
|
30
|
+
def initialize(index, options = {})
|
31
|
+
@index = index
|
32
|
+
@column = options.delete(:delta_column) || :updated_at
|
33
|
+
@threshold = options.delete(:threshold) || 1.day
|
34
|
+
end
|
35
|
+
|
36
|
+
# Does absolutely nothing, beyond returning true. Thinking Sphinx expects
|
37
|
+
# this method, though, and we don't want to use the inherited behaviour from
|
38
|
+
# DefaultDelta.
|
39
|
+
#
|
40
|
+
# All the real indexing logic is done by the delayed_index method.
|
41
|
+
#
|
42
|
+
# @param [Class] model the ActiveRecord model to index.
|
43
|
+
# @param [ActiveRecord::Base] instance the instance of the given model that
|
44
|
+
# has changed. Optional.
|
45
|
+
# @return [Boolean] true
|
46
|
+
# @see #delayed_index
|
47
|
+
#
|
48
|
+
def index(model, instance = nil)
|
49
|
+
# do nothing
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
# Processes the delta index for the given model, and then merges the relevant
|
54
|
+
# core and delta indexes together. By default, the output of these indexer
|
55
|
+
# commands are printed to stdout. If you'd rather it didn't, set
|
56
|
+
# ThinkingSphinx.suppress_delta_output to true.
|
57
|
+
#
|
58
|
+
# @param [Class] model the ActiveRecord model to index
|
59
|
+
# @return [Boolean] true
|
60
|
+
#
|
61
|
+
def delayed_index(model)
|
62
|
+
config = ThinkingSphinx::Configuration.instance
|
63
|
+
rotate = ThinkingSphinx.sphinx_running? ? " --rotate" : ""
|
64
|
+
|
65
|
+
output = `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file}#{rotate} #{delta_index_name model}`
|
66
|
+
output += `#{config.bin_path}#{config.indexer_binary_name} --config #{config.config_file}#{rotate} --merge #{core_index_name model} #{delta_index_name model} --merge-dst-range sphinx_deleted 0 0`
|
67
|
+
puts output unless ThinkingSphinx.suppress_delta_output?
|
68
|
+
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
# Toggles the given instance to be flagged as part of the next delta indexing.
|
73
|
+
# For datetime deltas, this means do nothing at all.
|
74
|
+
#
|
75
|
+
# @param [ActiveRecord::Base] instance the instance to be toggled
|
76
|
+
#
|
77
|
+
def toggle(instance)
|
78
|
+
# do nothing
|
79
|
+
end
|
80
|
+
|
81
|
+
# Report whether a given instance is considered toggled (part of the next
|
82
|
+
# delta process). For datetime deltas, this is true if the delta column
|
83
|
+
# (updated_at by default) has a value within the threshold. Otherwise, false
|
84
|
+
# is returned.
|
85
|
+
#
|
86
|
+
# @param [ActiveRecord::Base] instance the instance to check
|
87
|
+
# @return [Boolean] True if within the threshold window, otherwise false.
|
88
|
+
#
|
89
|
+
def toggled(instance)
|
90
|
+
instance.send(@column) > @threshold.ago
|
91
|
+
end
|
92
|
+
|
93
|
+
# Returns the SQL query that resets the model data after a normal index. For
|
94
|
+
# datetime deltas, nothing needs to be done, so this method returns nil.
|
95
|
+
#
|
96
|
+
# @param [Class] model The ActiveRecord model that is requesting the query
|
97
|
+
# @return [NilClass] Always nil
|
98
|
+
#
|
99
|
+
def reset_query(model)
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
|
103
|
+
# A SQL condition (as part of the WHERE clause) that limits the result set to
|
104
|
+
# just the delta data, or all data, depending on whether the toggled argument
|
105
|
+
# is true or not. For datetime deltas, the former value is a check on the
|
106
|
+
# delta column being within the threshold. In the latter's case, no condition
|
107
|
+
# is needed, so nil is returned.
|
108
|
+
#
|
109
|
+
# @param [Class] model The ActiveRecord model to generate the SQL condition
|
110
|
+
# for.
|
111
|
+
# @param [Boolean] toggled Whether the query should request delta documents or
|
112
|
+
# all documents.
|
113
|
+
# @return [String, NilClass] The SQL condition if the toggled version is
|
114
|
+
# requested, otherwise nil.
|
115
|
+
#
|
116
|
+
def clause(model, toggled)
|
117
|
+
if toggled
|
118
|
+
"#{model.quoted_table_name}.#{model.connection.quote_column_name(@column.to_s)}" +
|
119
|
+
" > #{adapter.time_difference(@threshold)}"
|
120
|
+
else
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
namespace :thinking_sphinx do
|
2
|
+
namespace :index do
|
3
|
+
desc "Index Thinking Sphinx datetime delta indexes"
|
4
|
+
task :delta => :app_env do
|
5
|
+
ThinkingSphinx.indexed_models.select { |model|
|
6
|
+
model.constantize.sphinx_indexes.any? { |index| index.delta? }
|
7
|
+
}.each do |model|
|
8
|
+
model.constantize.sphinx_indexes.select { |index|
|
9
|
+
index.delta? && index.delta_object.respond_to?(:delayed_index)
|
10
|
+
}.each { |index|
|
11
|
+
index.delta_object.delayed_index(index.model)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
namespace :ts do
|
19
|
+
namespace :in do
|
20
|
+
desc "Index Thinking Sphinx datetime delta indexes"
|
21
|
+
task :delta => "thinking_sphinx:index:delta"
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
|
7
|
+
require 'thinking_sphinx'
|
8
|
+
require 'thinking_sphinx/deltas/delayed_delta'
|
9
|
+
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
#
|
12
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Deltas::DatetimeDelta do
|
4
|
+
before :each do
|
5
|
+
@datetime_delta = ThinkingSphinx::Deltas::DatetimeDelta.new(
|
6
|
+
stub('index'), {}
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#index' do
|
11
|
+
it "should do nothing to the model" do
|
12
|
+
@datetime_delta.index(stub('model'))
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should do nothing to the instance, if provided" do
|
16
|
+
@datetime_delta.index(stub('model'), stub('instance'))
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should make no system calls" do
|
20
|
+
@datetime_delta.stub! :` => true
|
21
|
+
@datetime_delta.stub! :system => true
|
22
|
+
|
23
|
+
@datetime_delta.should_not_receive(:`)
|
24
|
+
@datetime_delta.should_not_receive(:system)
|
25
|
+
|
26
|
+
@datetime_delta.index(stub('model'), stub('instance'))
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return true" do
|
30
|
+
@datetime_delta.index(stub('model')).should be_true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#delayed_index' do
|
35
|
+
before :each do
|
36
|
+
@model = stub('foo')
|
37
|
+
@model.stub!(:name => 'foo')
|
38
|
+
@model.stub!(:source_of_sphinx_index => @model)
|
39
|
+
|
40
|
+
ThinkingSphinx.suppress_delta_output = false
|
41
|
+
|
42
|
+
@datetime_delta.stub! :` => ""
|
43
|
+
@datetime_delta.stub! :puts => nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should process the delta index for the given model" do
|
47
|
+
@datetime_delta.should_receive(:`).
|
48
|
+
with('indexer --config /config/development.sphinx.conf foo_delta')
|
49
|
+
|
50
|
+
@datetime_delta.delayed_index(@model)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should merge the core and delta indexes for the given model" do
|
54
|
+
@datetime_delta.should_receive(:`).with('indexer --config /config/development.sphinx.conf --merge foo_core foo_delta --merge-dst-range sphinx_deleted 0 0')
|
55
|
+
|
56
|
+
@datetime_delta.delayed_index(@model)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should include --rotate if Sphinx is running" do
|
60
|
+
ThinkingSphinx.stub!(:sphinx_running? => true)
|
61
|
+
@datetime_delta.should_receive(:`) do |command|
|
62
|
+
command.should match(/\s--rotate\s/)
|
63
|
+
end
|
64
|
+
|
65
|
+
@datetime_delta.delayed_index(@model)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should output the details by default" do
|
69
|
+
@datetime_delta.should_receive(:puts)
|
70
|
+
|
71
|
+
@datetime_delta.delayed_index(@model)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should hide the details if suppressing delta output" do
|
75
|
+
ThinkingSphinx.suppress_delta_output = true
|
76
|
+
@datetime_delta.should_not_receive(:puts)
|
77
|
+
|
78
|
+
@datetime_delta.delayed_index(@model)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#toggle' do
|
83
|
+
it "should do nothing to the instance" do
|
84
|
+
@datetime_delta.toggle(stub('instance'))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '#toggled' do
|
89
|
+
it "should return true if the column value is more recent than the threshold" do
|
90
|
+
instance = stub('instance', :updated_at => 20.minutes.ago)
|
91
|
+
@datetime_delta.threshold = 30.minutes
|
92
|
+
|
93
|
+
@datetime_delta.toggled(instance).should be_true
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return false if the column value is older than the threshold" do
|
97
|
+
instance = stub('instance', :updated_at => 30.minutes.ago)
|
98
|
+
@datetime_delta.threshold = 20.minutes
|
99
|
+
|
100
|
+
@datetime_delta.toggled(instance).should be_false
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#reset_query' do
|
105
|
+
it "should be nil" do
|
106
|
+
@datetime_delta.reset_query(@model).should be_nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#clause' do
|
111
|
+
before :each do
|
112
|
+
@model = stub('model', :connection => stub('connection'))
|
113
|
+
@model.stub!(:quoted_table_name => '`foo`')
|
114
|
+
@model.connection.stub!(:quote_column_name => '`updated_at`')
|
115
|
+
|
116
|
+
@datetime_delta.stub!(
|
117
|
+
:adapter => stub('adapter', :time_difference => 'time_difference')
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should return nil if not for the toggled results" do
|
122
|
+
@datetime_delta.clause(@model, false).should be_nil
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return only records within the threshold" do
|
126
|
+
@datetime_delta.clause(@model, true).
|
127
|
+
should == '`foo`.`updated_at` > time_difference'
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ts-datetime-delta
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pat Allan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-03 00:00:00 +11:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yard
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: cucumber
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: Manage delta indexes via datetime columns for Thinking Sphinx
|
46
|
+
email: pat@freelancing-gods.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- LICENSE
|
53
|
+
- README.textile
|
54
|
+
files:
|
55
|
+
- LICENSE
|
56
|
+
- README.textile
|
57
|
+
- lib/thinking_sphinx/deltas/datetime_delta.rb
|
58
|
+
- lib/thinking_sphinx/deltas/datetime_delta/tasks.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://github.com/freelancing-god/ts-datetime-delta
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --charset=UTF-8
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: "0"
|
73
|
+
version:
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.3.5
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: Thinking Sphinx - Datetime Deltas
|
87
|
+
test_files:
|
88
|
+
- features/datetime_deltas.feature
|
89
|
+
- features/step_definitions/common_steps.rb
|
90
|
+
- features/step_definitions/datetime_delta_steps.rb
|
91
|
+
- features/support/database.example.yml
|
92
|
+
- features/support/database.yml
|
93
|
+
- features/support/db/fixtures/thetas.rb
|
94
|
+
- features/support/db/migrations/create_thetas.rb
|
95
|
+
- features/support/env.rb
|
96
|
+
- features/support/models/theta.rb
|
97
|
+
- spec/spec.opts
|
98
|
+
- spec/spec_helper.rb
|
99
|
+
- spec/thinking_sphinx/deltas/datetime_delta_spec.rb
|