2019-12-05 17:51:33 +05:30
# =====================================================================================================
# Template for generating a no-frills Rails application with support for Elasticsearch full-text search
# =====================================================================================================
#
# This file creates a basic, fully working Rails application with support for Elasticsearch full-text
# search via the `elasticsearch-rails` gem; https://github.com/elasticsearch/elasticsearch-rails.
#
# Requirements:
# -------------
#
# * Git
# * Ruby >= 1.9.3
2020-03-13 15:44:24 +05:30
# * Rails >= 5
2019-12-05 17:51:33 +05:30
#
# Usage:
# ------
#
# $ rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/01-basic.rb
#
# =====================================================================================================
require 'uri'
require 'net/http'
2020-03-13 15:44:24 +05:30
require 'json'
2019-12-05 17:51:33 +05:30
2020-03-13 15:44:24 +05:30
$elasticsearch_url = ENV . fetch ( 'ELASTICSEARCH_URL' , 'http://localhost:9200' )
# ----- Check for Elasticsearch -------------------------------------------------------------------
required_elasticsearch_version = '6'
docker_command = <<-CMD.gsub(/\s{1,}/, ' ').strip
docker run \
- - name elasticsearch - rails - searchapp \
- - publish 9200 : 9200 \
- - env " discovery.type=single-node " \
- - env " cluster.name=elasticsearch-rails " \
- - env " cluster.routing.allocation.disk.threshold_enabled=false " \
- - rm \
docker . elastic . co / elasticsearch / elasticsearch - oss : 6 . 4 . 0
CMD
begin
cluster_info = Net :: HTTP . get ( URI . parse ( $elasticsearch_url ) )
rescue Errno :: ECONNREFUSED = > e
say_status " ERROR " , " Cannot connect to Elasticsearch on < #{ $elasticsearch_url } > \n \n " , :red
say_status " " , " The application requires an Elasticsearch cluster running, " +
" but no cluster has been found on < #{ $elasticsearch_url } >. "
say_status " " , " The easiest way of launching Elasticsearch is by running it with Docker (https://www.docker.com/get-docker): \n \n "
say_status " " , docker_command + " \n "
exit ( 1 )
rescue StandardError = > e
say_status " ERROR " , " #{ e . class } : #{ e . message } " , :red
exit ( 1 )
end
cluster_info = JSON . parse ( cluster_info )
unless cluster_info [ 'version' ]
say_status " ERROR " , " Cannot determine Elasticsearch version from < #{ $elasticsearch_url } > " , :red
say_status " " , JSON . dump ( cluster_info ) , :red
exit ( 1 )
end
if cluster_info [ 'version' ] [ 'number' ] < required_elasticsearch_version
say_status " ERROR " ,
" The application requires Elasticsearch version #{ required_elasticsearch_version } or higher, found version #{ cluster_info [ 'version' ] [ 'number' ] } . \n \n " , :red
say_status " " , " The easiest way of launching Elasticsearch is by running it with Docker (https://www.docker.com/get-docker): \n \n "
say_status " " , docker_command + " \n "
exit ( 1 )
2019-12-05 17:51:33 +05:30
end
2020-03-13 15:44:24 +05:30
# ----- Application skeleton ----------------------------------------------------------------------
2019-12-05 17:51:33 +05:30
run " touch tmp/.gitignore "
2020-03-13 15:44:24 +05:30
append_to_file " .gitignore " , " vendor/elasticsearch-5.2.1/ \n "
2019-12-05 17:51:33 +05:30
git :init
git add : " . "
git commit : " -m 'Initial commit: Clean application' "
# ----- Add README --------------------------------------------------------------------------------
puts
say_status " README " , " Adding Readme... \n " , :yellow
puts '-' * 80 , '' ; sleep 0 . 25
2020-03-13 15:44:24 +05:30
remove_file 'README.md'
2019-12-05 17:51:33 +05:30
2020-03-13 15:44:24 +05:30
create_file 'README.md' , <<-README
# Ruby on Rails and Elasticsearch: Example application
2019-12-05 17:51:33 +05:30
This application is an example of integrating the { Elasticsearch } [ http : / / www . elasticsearch . org ]
search engine with the { Ruby On Rails } [ http : / / rubyonrails . org ] web framework .
It has been generated by application templates available at
https : / / github . com / elasticsearch / elasticsearch - rails / tree / master / elasticsearch - rails / lib / rails / templates .
2020-03-13 15:44:24 +05:30
## [1] Basic
2019-12-05 17:51:33 +05:30
The ` basic ` version provides a simple integration for a simple Rails model , ` Article ` , showing how
to include the search engine support in your model , automatically index changes to records ,
and use a form to perform simple search require 'requests.'
README
git add : " . "
git commit : " -m '[01] Added README for the application' "
# ----- Use Thin ----------------------------------------------------------------------------------
begin
require 'thin'
puts
say_status " Rubygems " , " Adding Thin into Gemfile... \n " , :yellow
puts '-' * 80 , '' ;
gem 'thin'
rescue LoadError
end
# ----- Auxiliary gems ----------------------------------------------------------------------------
2020-03-13 15:44:24 +05:30
gem 'mocha' , group : 'test'
gem 'rails-controller-testing' , group : 'test'
2019-12-05 17:51:33 +05:30
# ----- Remove CoffeeScript, Sass and "all that jazz" ---------------------------------------------
comment_lines 'Gemfile' , / gem 'coffee /
comment_lines 'Gemfile' , / gem 'sass /
comment_lines 'Gemfile' , / gem 'uglifier /
uncomment_lines 'Gemfile' , / gem 'therubyracer /
# ----- Add gems into Gemfile ---------------------------------------------------------------------
puts
say_status " Rubygems " , " Adding Elasticsearch libraries into Gemfile... \n " , :yellow
puts '-' * 80 , '' ; sleep 0 . 75
2020-03-13 15:44:24 +05:30
gem 'elasticsearch' , git : 'https://github.com/elasticsearch/elasticsearch-ruby.git'
gem 'elasticsearch-model' , git : 'https://github.com/elasticsearch/elasticsearch-rails.git'
gem 'elasticsearch-rails' , git : 'https://github.com/elasticsearch/elasticsearch-rails.git'
2019-12-05 17:51:33 +05:30
git add : " Gemfile* "
git commit : " -m 'Added libraries into Gemfile' "
# ----- Disable asset logging in development ------------------------------------------------------
puts
say_status " Application " , " Disabling asset logging in development... \n " , :yellow
puts '-' * 80 , '' ; sleep 0 . 25
environment 'config.assets.logger = false' , env : 'development'
2020-03-13 15:44:24 +05:30
environment 'config.assets.quiet = true' , env : 'development'
2019-12-05 17:51:33 +05:30
git add : " config/ "
git commit : " -m 'Disabled asset logging in development' "
# ----- Install gems ------------------------------------------------------------------------------
puts
say_status " Rubygems " , " Installing Rubygems... " , :yellow
puts '-' * 80 , ''
run " bundle install "
# ----- Generate Article resource -----------------------------------------------------------------
puts
say_status " Model " , " Generating the Article resource... " , :yellow
puts '-' * 80 , '' ; sleep 0 . 75
generate :scaffold , " Article title:string content:text published_on:date "
route " root to: 'articles # index' "
rake " db:migrate "
git add : " . "
git commit : " -m 'Added the generated Article resource' "
# ----- Add Elasticsearch integration into the model ----------------------------------------------
puts
say_status " Model " , " Adding search support into the Article model... " , :yellow
puts '-' * 80 , '' ; sleep 0 . 25
run " rm -f app/models/article.rb "
file 'app/models/article.rb' , <<-CODE
class Article < ActiveRecord :: Base
include Elasticsearch :: Model
include Elasticsearch :: Model :: Callbacks
#{'attr_accessible :title, :content, :published_on' if Rails::VERSION::STRING < '4'}
end
CODE
git commit : " -a -m 'Added Elasticsearch support into the Article model' "
# ----- Add Elasticsearch integration into the interface ------------------------------------------
puts
say_status " Controller " , " Adding controller action, route, and HTML for searching... " , :yellow
puts '-' * 80 , '' ; sleep 0 . 25
inject_into_file 'app/controllers/articles_controller.rb' , before : %r|^\s*# GET /articles/1$| do
<<-CODE
# GET /articles/search
def search
@articles = Article . search ( params [ :q ] ) . records
render action : " index "
end
CODE
end
2020-03-13 15:44:24 +05:30
inject_into_file 'app/views/articles/index.html.erb' , after : %r{ <h1>.*Articles</h1> }i do
2019-12-05 17:51:33 +05:30
<<-CODE
< hr >
< %= form_tag search_articles_path , method : 'get' do % >
< %= label_tag :query % >
< %= text_field_tag :q , params [ :q ] % >
< %= submit_tag :search % >
< % end % >
< hr >
CODE
end
inject_into_file 'app/views/articles/index.html.erb' , after : %r{ <%= link_to 'New Article', new_article_path %> } do
<<-CODE
< %= link_to 'All Articles' , articles_path if params [ :q ] % >
CODE
end
gsub_file 'config/routes.rb' , %r{ resources :articles$ } , <<-CODE
resources :articles do
collection { get :search }
end
CODE
2020-03-13 15:44:24 +05:30
gsub_file " test/controllers/articles_controller_test.rb " , %r{ setup do.*?end }m , <<-CODE
2019-12-05 17:51:33 +05:30
setup do
@article = articles ( :one )
2020-03-13 15:44:24 +05:30
Article . __elasticsearch__ . import force : true
2019-12-05 17:51:33 +05:30
Article . __elasticsearch__ . refresh_index!
end
CODE
2020-03-13 15:44:24 +05:30
inject_into_file " test/controllers/articles_controller_test.rb " , after : %r{ test "should get index" do.*?end }m do
2019-12-05 17:51:33 +05:30
<<-CODE
test " should get search results " do
2020-03-13 15:44:24 +05:30
#{ Rails::VERSION::STRING > '5' ? 'get search_articles_url(q: "mystring")' : 'get :search, q: "mystring"' }
2019-12-05 17:51:33 +05:30
assert_response :success
assert_not_nil assigns ( :articles )
assert_equal 2 , assigns ( :articles ) . size
end
CODE
end
git commit : " -a -m 'Added search form and controller action' "
# ----- Seed the database -------------------------------------------------------------------------
puts
say_status " Database " , " Seeding the database with data... " , :yellow
puts '-' * 80 , '' ; sleep 0 . 25
remove_file " db/seeds.rb "
create_file 'db/seeds.rb' , %q{
contents = [
'Lorem ipsum dolor sit amet.' ,
'Consectetur adipisicing elit, sed do eiusmod tempor incididunt.' ,
'Labore et dolore magna aliqua.' ,
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.' ,
'Excepteur sint occaecat cupidatat non proident.'
]
puts " Deleting all articles... "
Article . delete_all
unless ENV [ 'COUNT' ]
puts " Creating articles... "
%w[ One Two Three Four Five ] . each_with_index do | title , i |
Article . create title : title , content : contents [ i ] , published_on : i . days . ago . utc
end
else
print " Generating articles... "
( 1 .. ENV [ 'COUNT' ] . to_i ) . each_with_index do | title , i |
Article . create title : " Title #{ title } " , content : 'Lorem ipsum dolor' , published_on : i . days . ago . utc
print '.' if i % ENV [ 'COUNT' ] . to_i / 10 == 0
end
puts " \n "
end
}
run " rails runner 'Article.__elasticsearch__.create_index! force: true' "
rake " db:seed "
git add : " db/seeds.rb "
git commit : " -m 'Added the database seeding script' "
# ----- Print Git log -----------------------------------------------------------------------------
puts
say_status " Git " , " Details about the application: " , :yellow
puts '-' * 80 , ''
git tag : " basic "
git log : " --reverse --oneline "
# ----- Start the application ---------------------------------------------------------------------
unless ENV [ 'RAILS_NO_SERVER_START' ]
require 'net/http'
if ( begin ; Net :: HTTP . get ( URI ( 'http://localhost:3000' ) ) ; rescue Errno :: ECONNREFUSED ; false ; rescue Exception ; true ; end )
puts " \n "
say_status " ERROR " , " Some other application is running on port 3000! \n " , :red
puts '-' * 80
port = ask ( " Please provide free port: " , :bold )
else
port = '3000'
end
puts " " , " = " * 80
say_status " DONE " , " \e [1mStarting the application. \e [0m " , :yellow
puts " = " * 80 , " "
run " rails server --port= #{ port } "
end