-
Notifications
You must be signed in to change notification settings - Fork 533
Integration Testing Rails Models with Tire
This page is a little light on narrative, but hopefully stands as a useful resource for testing Rails models with
class Widget
include Tire::Model::Search
include Tire::Model::Callbacks
#
# Define the name based on the environment
# We wouldn't like to erase dev data during
# test runs!
#
index_name("#{Rails.env}-#{Rails.application.class.to_s.downcase}-widgets")
#
# mapping do; end
#
# No mapping here, because we need custom settings,
# we shouldn't use the mapping DSL here.
#
class << self
def create_search_index
Tire.index(Widget.index_name) do
create(
:settings => {
"analysis" => {
"analyzer" => {
"widget_name_analyzer" => {
"type" => "custom",
"tokenizer" => "lowercase",
"filter" => ["name_ngram"]
}
},
"filter" => {
"name_ngram" => {
"type" => 'edgeNGram',
"min_gram" => 2,
"max_gram" => 7,
"side" => "front"
}
}
}
},
:mappings => {
:show => {
:properties => {
:id => { :type => :integer },
:name => { :type => :string, :analyzer => :widget_name_analyzer }
}
}
}
)
end
end
def delete_search_index
search_index.delete
end
def search_index
Tire.index(Widget.index_name)
end
end
end
The definition here is a little extensive, but effectively creates a simple mapping, where the name
field of our Widget
is analyzed at search time using the newly defined widget_name_analyzer
.
Important to note the following:
- We have class methods for creating, and deleting the index… this allows us to effectively recreate the index at test time.
- The mapping is done inside of the index creation, we cannot use the mappings DSL when creating custom analyzers.
- The index name uses the rails environment, as well as the application class name (only available to Rails)
Typically, in a Rails application then one would have an initializer such as:
Tire.configure do
logger Rails.root + "log/tire_#{Rails.env}.log"
end
Widget.create_search_index unless Widget.search_index.exists?
Note: In production, your search index will be valuable, you don't want an initializer that empties your index, so we guard the creation of the index here with a check for it's existence. One could easily come up with a Rake task, or similar for re-creating an index, when the settings change in your production environment.
And, a simple test case:
require 'test_helper'
class WidgetSearchTest < ActiveSupport::TestCase
setup do
Widget.create_search_index
#
# Setup widgets for testing here
#
Widget.search_index.refresh
end
teardown do
Widget.delete_search_index
end
def test_something_about_widgets
ws = Widget.search("test")
#
# Normal assertions here, remember to refresh
# the search index after creating new
# records. At this point, using the Tire API
# should be exactly like documented
#
end
end