lib/rails/templates/03-expert.rb in elasticsearch-rails-0.1.0 vs lib/rails/templates/03-expert.rb in elasticsearch-rails-0.1.1
- old
+ new
@@ -1,910 +1,325 @@
# $ rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/03-complex.rb
# (See: 01-basic.rb, 02-pretty.rb)
-# ----- Move the search form into partial ---------------------------------------------------------
+append_to_file 'README.rdoc', <<-README
+== [3] Expert
+
+The `expert` template changes to a complex database schema with model relationships: article belongs
+to a category, has many authors and comments.
+
+* The Elasticsearch integration is refactored into the `Searchable` concern
+* A complex mapping for the index is defined
+* A custom serialization is defined in `Article#as_indexed_json`
+* The `search` method is amended with facets and suggestions
+* A [Sidekiq](http://sidekiq.org) worker for handling index updates in background is added
+* A custom `SearchController` with associated view is added
+* A Rails initializer is added to customize the Elasticsearch client configuration
+* Seed script and example data from New York Times is added
+
+README
+
+git add: "README.rdoc"
+git commit: "-m '[03] Updated the application README'"
+
+# ----- Add gems into Gemfile ---------------------------------------------------------------------
+
puts
-say_status "View", "Moving the search form into partial template...\n", :yellow
-puts '-'*80, ''; sleep 0.5
+say_status "Rubygems", "Adding Rubygems into Gemfile...\n", :yellow
+puts '-'*80, ''; sleep 0.25
-gsub_file 'app/views/articles/index.html.erb', %r{\n<hr>.*<hr>\n}m do |match|
- create_file "app/views/articles/_search_form.html.erb", match
- "\n<%= render partial: 'search_form' %>\n"
-end
+gem "oj"
-git :add => 'app/views/articles/index.html.erb app/views/articles/_search_form.html.erb'
-git :commit => "-m 'Moved the search form into a partial template'"
+git add: "Gemfile*"
+git commit: "-m 'Added Ruby gems'"
-# ----- Move the model integration into a concern -------------------------------------------------
+# ----- Customize the Rails console ---------------------------------------------------------------
puts
-say_status "Model", "Refactoring the model integration...\n", :yellow
-puts '-'*80, ''; sleep 0.5
+say_status "Rails", "Customizing `rails console`...\n", :yellow
+puts '-'*80, ''; sleep 0.25
-create_file 'app/models/concerns/searchable.rb', <<-CODE
-module Searchable
- extend ActiveSupport::Concern
- included do
- include Elasticsearch::Model
- end
+gem "pry", group: 'development'
- module ClassMethods
- def search(query)
- __elasticsearch__.search(
- {
- query: {
- multi_match: {
- query: query,
- fields: ['title^10', 'content']
- }
- },
- highlight: {
- pre_tags: ['<em class="label label-highlight">'],
- post_tags: ['</em>'],
- fields: {
- title: { number_of_fragments: 0 },
- content: { fragment_size: 25 }
- }
- }
- }
- )
- end
+environment nil, env: 'development' do
+ %q{
+ console do
+ config.console = Pry
+ Pry.config.history.file = Rails.root.join('tmp/console_history.rb').to_s
+ Pry.config.prompt = [ proc { |obj, nest_level, _| "(#{obj})> " },
+ proc { |obj, nest_level, _| ' '*obj.to_s.size + ' '*(nest_level+1) + '| ' } ]
end
+ }
end
-CODE
-remove_file 'app/models/article.rb'
-create_file 'app/models/article.rb', <<-CODE
-class Article < ActiveRecord::Base
- include Searchable
-end
-CODE
+git add: "Gemfile*"
+git add: "config/"
+git commit: "-m 'Added Pry as the console for development'"
-git :add => 'app/models/'
-git :commit => "-m 'Refactored the Elasticsearch integration into a concern\n\nSee:\n\n* http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns\n* http://joshsymonds.com/blog/2012/10/25/rails-concerns-v-searchable-with-elasticsearch/'"
+# ----- Disable asset logging in development ------------------------------------------------------
-# ----- Add initializer ---------------------------------------------------------------------------
-
puts
-say_status "Application", "Adding configuration in an initializer...\n", :yellow
-puts '-'*80, ''; sleep 0.5
+say_status "Application", "Disabling asset logging in development...\n", :yellow
+puts '-'*80, ''; sleep 0.25
-create_file 'config/initializers/elasticsearch.rb', <<-CODE
-# Connect to specific Elasticsearch cluster
-ELASTICSEARCH_URL = ENV['ELASTICSEARCH_URL'] || 'http://localhost:9200'
+environment 'config.assets.logger = false', env: 'development'
+gem 'quiet_assets', group: "development"
-# Print Curl-formatted traces in development
-#
-if Rails.env.development?
- tracer = ActiveSupport::Logger.new(STDERR)
- tracer.level = Logger::INFO
-end
+git add: "Gemfile*"
+git add: "config/"
+git commit: "-m 'Disabled asset logging in development'"
-Elasticsearch::Model.client Elasticsearch::Client.new tracer: tracer, host: ELASTICSEARCH_URL
-CODE
+# ----- Run bundle install ------------------------------------------------------------------------
-git :add => 'config/initializers'
-git :commit => "-m 'Added application initializer with Elasticsearch configuration'"
+run "bundle install"
-# ----- Generate and define data model for books --------------------------------------------------
+# ----- Define and generate schema ----------------------------------------------------------------
puts
-say_status "Database", "Adding complex schema and data for books...\n", :yellow
-puts '-'*80, ''; sleep 0.5
+say_status "Models", "Adding complex schema...\n", :yellow
+puts '-'*80, ''
generate :scaffold, "Category title"
-generate :scaffold, "Book title:string content:text downloads:integer category:references"
generate :scaffold, "Author first_name last_name"
-generate :scaffold, "Authorship book:references author:references"
+generate :scaffold, "Authorship article:references author:references"
+generate :model, "Comment body:text user:string user_location:string stars:integer pick:boolean article:references"
+generate :migration, "CreateArticlesCategories article:references category:references"
+
+rake "db:drop"
+rake "db:migrate"
+
insert_into_file "app/models/category.rb", :before => "end" do
<<-CODE
- has_many :books
+ has_and_belongs_to_many :articles
CODE
end
-insert_into_file "app/models/book.rb", :before => "end" do
- <<-CODE
- has_many :authorships
- has_many :authors, through: :authorships
- CODE
-end
-
insert_into_file "app/models/author.rb", :before => "end" do
<<-CODE
has_many :authorships
def full_name
[first_name, last_name].join(' ')
end
CODE
end
-# ----- Migrate the database --------------------------------------------------------------------------
+gsub_file "app/models/authorship.rb", %r{belongs_to :article$}, <<-CODE
+belongs_to :article, touch: true
+CODE
-rake "db:migrate"
+insert_into_file "app/models/article.rb", after: "ActiveRecord::Base" do
+ <<-CODE
-# ----- Create the seed data --------------------------------------------------------------------------
+ has_and_belongs_to_many :categories, after_add: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ],
+ after_remove: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ]
+ has_many :authorships
+ has_many :authors, through: :authorships
+ has_many :comments
+ CODE
+end
-remove_file 'db/seeds.rb'
-create_file 'db/seeds.rb', <<-CODE
-# encoding: UTF-8
+gsub_file "app/models/comment.rb", %r{belongs_to :article$}, <<-CODE
+belongs_to :article, touch: true
+CODE
-require 'yaml'
+git add: "."
+git commit: "-m 'Generated Category, Author and Comment resources'"
-books = YAML.parse <<-DATA
----
-- :title: Dracula
- :authors:
- - :last_name: Stoker
- :first_name: Bram
- :downloads: 12197
- :category: Fiction
- :content: |
- _3 May. Bistritz._--Left Munich at 8:35 P. M., on 1st May, arriving at
- Vienna early next morning; should have arrived at 6:46, but train was an
- hour late. Buda-Pesth seems a wonderful place, from the glimpse which I
- got of it from the train and the little I could walk through the
- streets. I feared to go very far from the station, as we had arrived
- late and would start as near the correct time as possible. The
- impression I had was that we were leaving the West and entering the
- East; the most western of splendid bridges over the Danube, which is
- here of noble width and depth, took us among the traditions of Turkish
- rule.
+# ----- Add the `abstract` column -----------------------------------------------------------------
- We left in pretty good time, and came after nightfall to Klausenburgh.
- Here I stopped for the night at the Hotel Royale. I had for dinner, or
- rather supper, a chicken done up some way with red pepper, which was
- very good but thirsty. (_Mem._, get recipe for Mina.) I asked the
- waiter, and he said it was called "paprika hendl," and that, as it was a
- national dish, I should be able to get it anywhere along the
- Carpathians. I found my smattering of German very useful here; indeed, I
- don't know how I should be able to get on without it.
+puts
+say_status "Model", "Adding the `abstract` column to Article...\n", :yellow
+puts '-'*80, ''
- Having had some time at my disposal when in London, I had visited the
- British Museum, and made search among the books and maps in the library
- regarding Transylvania; it had struck me that some foreknowledge of the
- country could hardly fail to have some importance in dealing with a
- nobleman of that country. I find that the district he named is in the
- extreme east of the country, just on the borders of three states,
- Transylvania, Moldavia and Bukovina, in the midst of the Carpathian
- mountains; one of the wildest and least known portions of Europe. I was
- not able to light on any map or work giving the exact locality of the
- Castle Dracula, as there are no maps of this country as yet to compare
- with our own Ordnance Survey maps; but I found that Bistritz, the post
- town named by Count Dracula, is a fairly well-known place. I shall enter
- here some of my notes, as they may refresh my memory when I talk over my
- travels with Mina.
+generate :migration, "AddColumnsToArticle abstract:text url:string shares:integer"
+rake "db:migrate"
- In the population of Transylvania there are four distinct nationalities:
- Saxons in the South, and mixed with them the Wallachs, who are the
- descendants of the Dacians; Magyars in the West, and Szekelys in the
- East and North. I am going among the latter, who claim to be descended
- from Attila and the Huns. This may be so, for when the Magyars conquered
- the country in the eleventh century they found the Huns settled in it. I
- read that every known superstition in the world is gathered into the
- horseshoe of the Carpathians, as if it were the centre of some sort of
- imaginative whirlpool; if so my stay may be very interesting. (_Mem._, I
- must ask the Count all about them.)
+git add: "db/"
+git commit: "-m 'Added additional columns to Article'"
- I did not sleep well, though my bed was comfortable enough, for I had
- all sorts of queer dreams. There was a dog howling all night under my
- window, which may have had something to do with it; or it may have been
- the paprika, for I had to drink up all the water in my carafe, and was
- still thirsty. Towards morning I slept and was wakened by the continuous
- knocking at my door, so I guess I must have been sleeping soundly then.
- I had for breakfast more paprika, and a sort of porridge of maize flour
- which they said was "mamaliga," and egg-plant stuffed with forcemeat, a
- very excellent dish, which they call "impletata." (_Mem._, get recipe
- for this also.) I had to hurry breakfast, for the train started a little
- before eight, or rather it ought to have done so, for after rushing to
- the station at 7:30 I had to sit in the carriage for more than an hour
- before we began to move. It seems to me that the further east you go the
- more unpunctual are the trains. What ought they to be in China?
+# ----- Move the model integration into a concern -------------------------------------------------
- All day long we seemed to dawdle through a country which was full of
- beauty of every kind. Sometimes we saw little towns or castles on the
- top of steep hills such as we see in old missals; sometimes we ran by
- rivers and streams which seemed from the wide stony margin on each side
- of them to be subject to great floods. It takes a lot of water, and
- running strong, to sweep the outside edge of a river clear. At every
- station there were groups of people, sometimes crowds, and in all sorts
- of attire. Some of them were just like the peasants at home or those I
- saw coming through France and Germany, with short jackets and round hats
- and home-made trousers; but others were very picturesque. The women
- looked pretty, except when you got near them, but they were very clumsy
- about the waist. They had all full white sleeves of some kind or other,
- and most of them had big belts with a lot of strips of something
- fluttering from them like the dresses in a ballet, but of course there
- were petticoats under them. The strangest figures we saw were the
- Slovaks, who were more barbarian than the rest, with their big cow-boy
- hats, great baggy dirty-white trousers, white linen shirts, and enormous
- heavy leather belts, nearly a foot wide, all studded over with brass
- nails. They wore high boots, with their trousers tucked into them, and
- had long black hair and heavy black moustaches. They are very
- picturesque, but do not look prepossessing. On the stage they would be
- set down at once as some old Oriental band of brigands. They are,
- however, I am told, very harmless and rather wanting in natural
- self-assertion.
+puts
+say_status "Model", "Refactoring the model integration...\n", :yellow
+puts '-'*80, ''; sleep 0.25
- It was on the dark side of twilight when we got to Bistritz, which is a
- very interesting old place. Being practically on the frontier--for the
- Borgo Pass leads from it into Bukovina--it has had a very stormy
- existence, and it certainly shows marks of it. Fifty years ago a series
- of great fires took place, which made terrible havoc on five separate
- occasions. At the very beginning of the seventeenth century it underwent
- a siege of three weeks and lost 13,000 people, the casualties of war
- proper being assisted by famine and disease.
+remove_file 'app/models/article.rb'
+create_file 'app/models/article.rb', <<-CODE
+class Article < ActiveRecord::Base
+ include Searchable
+end
+CODE
- Count Dracula had directed me to go to the Golden Krone Hotel, which I
- found, to my great delight, to be thoroughly old-fashioned, for of
- course I wanted to see all I could of the ways of the country. I was
- evidently expected, for when I got near the door I faced a
- cheery-looking elderly woman in the usual peasant dress--white
- undergarment with long double apron, front, and back, of coloured stuff
- fitting almost too tight for modesty. When I came close she bowed and
- said, "The Herr Englishman?" "Yes," I said, "Jonathan Harker." She
- smiled, and gave some message to an elderly man in white shirt-sleeves,
- who had followed her to the door. He went, but immediately returned with
- a letter:--
+# copy_file File.expand_path('../searchable.rb', __FILE__), 'app/models/concerns/searchable.rb'
+get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/searchable.rb',
+ 'app/models/concerns/searchable.rb'
- "My Friend.--Welcome to the Carpathians. I am anxiously expecting
- you. Sleep well to-night. At three to-morrow the diligence will
- start for Bukovina; a place on it is kept for you. At the Borgo
- Pass my carriage will await you and will bring you to me. I trust
- that your journey from London has been a happy one, and that you
- will enjoy your stay in my beautiful land.
+insert_into_file "app/models/article.rb", after: "ActiveRecord::Base" do
+ <<-CODE
- "Your friend,
+ has_and_belongs_to_many :categories, after_add: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ],
+ after_remove: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ]
+ has_many :authorships
+ has_many :authors, through: :authorships
+ has_many :comments
- "DRACULA."
+ CODE
+end
-- :title: Beyond Good and Evil
- :authors:
- - :last_name: Nietzsche
- :first_name: Friedrich Wilhelm
- :downloads: 8222
- :category: Philosophy
- :content: |
- SUPPOSING that Truth is a woman--what then? Is there not ground
- for suspecting that all philosophers, in so far as they have been
- dogmatists, have failed to understand women--that the terrible
- seriousness and clumsy importunity with which they have usually paid
- their addresses to Truth, have been unskilled and unseemly methods for
- winning a woman? Certainly she has never allowed herself to be won; and
- at present every kind of dogma stands with sad and discouraged mien--IF,
- indeed, it stands at all! For there are scoffers who maintain that it
- has fallen, that all dogma lies on the ground--nay more, that it is at
- its last gasp. But to speak seriously, there are good grounds for hoping
- that all dogmatizing in philosophy, whatever solemn, whatever conclusive
- and decided airs it has assumed, may have been only a noble puerilism
- and tyronism; and probably the time is at hand when it will be once
- and again understood WHAT has actually sufficed for the basis of such
- imposing and absolute philosophical edifices as the dogmatists have
- hitherto reared: perhaps some popular superstition of immemorial time
- (such as the soul-superstition, which, in the form of subject- and
- ego-superstition, has not yet ceased doing mischief): perhaps some
- play upon words, a deception on the part of grammar, or an
- audacious generalization of very restricted, very personal, very
- human--all-too-human facts. The philosophy of the dogmatists, it is to
- be hoped, was only a promise for thousands of years afterwards, as was
- astrology in still earlier times, in the service of which probably more
- labour, gold, acuteness, and patience have been spent than on any
- actual science hitherto: we owe to it, and to its "super-terrestrial"
- pretensions in Asia and Egypt, the grand style of architecture. It seems
- that in order to inscribe themselves upon the heart of humanity with
- everlasting claims, all great things have first to wander about the
- earth as enormous and awe-inspiring caricatures: dogmatic philosophy has
- been a caricature of this kind--for instance, the Vedanta doctrine in
- Asia, and Platonism in Europe. Let us not be ungrateful to it, although
- it must certainly be confessed that the worst, the most tiresome,
- and the most dangerous of errors hitherto has been a dogmatist
- error--namely, Plato's invention of Pure Spirit and the Good in Itself.
- But now when it has been surmounted, when Europe, rid of this nightmare,
- can again draw breath freely and at least enjoy a healthier--sleep,
- we, WHOSE DUTY IS WAKEFULNESS ITSELF, are the heirs of all the strength
- which the struggle against this error has fostered. It amounted to
- the very inversion of truth, and the denial of the PERSPECTIVE--the
- fundamental condition--of life, to speak of Spirit and the Good as Plato
- spoke of them; indeed one might ask, as a physician: "How did such a
- malady attack that finest product of antiquity, Plato? Had the wicked
- Socrates really corrupted him? Was Socrates after all a corrupter of
- youths, and deserved his hemlock?" But the struggle against Plato,
- or--to speak plainer, and for the "people"--the struggle against
- the ecclesiastical oppression of millenniums of Christianity (FOR
- CHRISTIANITY IS PLATONISM FOR THE "PEOPLE"), produced in Europe
- a magnificent tension of soul, such as had not existed anywhere
- previously; with such a tensely strained bow one can now aim at the
- furthest goals. As a matter of fact, the European feels this tension as
- a state of distress, and twice attempts have been made in grand style to
- unbend the bow: once by means of Jesuitism, and the second time by means
- of democratic enlightenment--which, with the aid of liberty of the press
- and newspaper-reading, might, in fact, bring it about that the spirit
- would not so easily find itself in "distress"! (The Germans invented
- gunpowder--all credit to them! but they again made things square--they
- invented printing.) But we, who are neither Jesuits, nor democrats,
- nor even sufficiently Germans, we GOOD EUROPEANS, and free, VERY free
- spirits--we have it still, all the distress of spirit and all the
- tension of its bow! And perhaps also the arrow, the duty, and, who
- knows? THE GOAL TO AIM AT....
+git add: "app/models/"
+git commit: "-m 'Refactored the Elasticsearch integration into a concern\n\nSee:\n\n* http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns\n* http://joshsymonds.com/blog/2012/10/25/rails-concerns-v-searchable-with-elasticsearch/'"
- Sils Maria Upper Engadine, JUNE, 1885.
+# ----- Add Sidekiq indexer -----------------------------------------------------------------------
-- :title: Ulysses
- :authors:
- - :last_name: Joyce
- :first_name: James
- :downloads: 14679
- :category: Fiction
- :content: |
- Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of
- lather on which a mirror and a razor lay crossed. A yellow dressinggown,
- ungirdled, was sustained gently behind him on the mild morning air. He
- held the bowl aloft and intoned:
+puts
+say_status "Application", "Adding Sidekiq worker for updating the index...\n", :yellow
+puts '-'*80, ''; sleep 0.25
- --_Introibo ad altare Dei_.
+gem "sidekiq"
- Halted, he peered down the dark winding stairs and called out coarsely:
+run "bundle install"
- --Come up, Kinch! Come up, you fearful jesuit!
+# copy_file File.expand_path('../indexer.rb', __FILE__), 'app/workers/indexer.rb'
+get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/indexer.rb',
+ 'app/workers/indexer.rb'
- Solemnly he came forward and mounted the round gunrest. He faced about
- and blessed gravely thrice the tower, the surrounding land and the
- awaking mountains. Then, catching sight of Stephen Dedalus, he bent
- towards him and made rapid crosses in the air, gurgling in his throat
- and shaking his head. Stephen Dedalus, displeased and sleepy, leaned
- his arms on the top of the staircase and looked coldly at the shaking
- gurgling face that blessed him, equine in its length, and at the light
- untonsured hair, grained and hued like pale oak.
+git add: "Gemfile* app/workers/"
+git commit: "-m 'Added a Sidekiq indexer\n\nRun:\n\n $ bundle exec sidekiq --queue elasticsearch --verbose\n\nSee http://sidekiq.org'"
- Buck Mulligan peeped an instant under the mirror and then covered the
- bowl smartly.
+# ----- Add SearchController -----------------------------------------------------------------------
- --Back to barracks! he said sternly.
+puts
+say_status "Controllers", "Adding SearchController...\n", :yellow
+puts '-'*80, ''; sleep 0.25
- He added in a preacher's tone:
+create_file 'app/controllers/search_controller.rb' do
+ <<-CODE.gsub(/^ /, '')
+ class SearchController < ApplicationController
+ respond_to :json, :html
- --For this, O dearly beloved, is the genuine Christine: body and soul
- and blood and ouns. Slow music, please. Shut your eyes, gents. One
- moment. A little trouble about those white corpuscles. Silence, all.
+ def index
+ options = {
+ category: params[:c],
+ author: params[:a],
+ published_week: params[:w],
+ published_day: params[:d],
+ sort: params[:s],
+ comments: params[:comments]
+ }
+ @articles = Article.search(params[:q], options).page(params[:page]).results
- He peered sideways up and gave a long slow whistle of call, then paused
- awhile in rapt attention, his even white teeth glistening here and there
- with gold points. Chrysostomos. Two strong shrill whistles answered
- through the calm.
+ respond_with @articles
+ end
- --Thanks, old chap, he cried briskly. That will do nicely. Switch off
- the current, will you?
+ end
- He skipped off the gunrest and looked gravely at his watcher, gathering
- about his legs the loose folds of his gown. The plump shadowed face and
- sullen oval jowl recalled a prelate, patron of arts in the middle ages.
- A pleasant smile broke quietly over his lips.
+ CODE
+end
- --The mockery of it! he said gaily. Your absurd name, an ancient Greek!
+route "get '/search', to: 'search#index', as: 'search'"
+gsub_file 'config/routes.rb', %r{root to: 'articles#index'$}, "root to: 'search#index'"
- He pointed his finger in friendly jest and went over to the parapet,
- laughing to himself. Stephen Dedalus stepped up, followed him wearily
- halfway and sat down on the edge of the gunrest, watching him still as
- he propped his mirror on the parapet, dipped the brush in the bowl and
- lathered cheeks and neck.
+# copy_file File.expand_path('../index.html.erb', __FILE__), 'app/views/search/index.html.erb'
+get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/index.html.erb',
+ 'app/views/search/index.html.erb'
- Buck Mulligan's gay voice went on.
+# copy_file File.expand_path('../search.css', __FILE__), 'app/assets/stylesheets/search.css'
+get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/search.css',
+ 'app/assets/stylesheets/search.css'
- --My name is absurd too: Malachi Mulligan, two dactyls. But it has a
- Hellenic ring, hasn't it? Tripping and sunny like the buck himself.
- We must go to Athens. Will you come if I can get the aunt to fork out
- twenty quid?
+git add: "app/controllers/ config/routes.rb"
+git add: "app/views/search/ app/assets/stylesheets/search.css"
+git commit: "-m 'Added SearchController#index'"
- He laid the brush aside and, laughing with delight, cried:
+# ----- Add initializer ---------------------------------------------------------------------------
- --Will he come? The jejune jesuit!
+puts
+say_status "Application", "Adding Elasticsearch configuration in an initializer...\n", :yellow
+puts '-'*80, ''; sleep 0.5
- Ceasing, he began to shave with care.
+create_file 'config/initializers/elasticsearch.rb', <<-CODE
+# Connect to specific Elasticsearch cluster
+ELASTICSEARCH_URL = ENV['ELASTICSEARCH_URL'] || 'http://localhost:9200'
- --Tell me, Mulligan, Stephen said quietly.
+Elasticsearch::Model.client = Elasticsearch::Client.new host: ELASTICSEARCH_URL
- --Yes, my love?
+# Print Curl-formatted traces in development into a file
+#
+if Rails.env.development?
+ tracer = ActiveSupport::Logger.new('log/elasticsearch.log')
+ tracer.level = Logger::DEBUG
+end
- --How long is Haines going to stay in this tower?
+Elasticsearch::Model.client.transport.tracer = tracer
+CODE
- Buck Mulligan showed a shaven cheek over his right shoulder.
+git add: "config/initializers"
+git commit: "-m 'Added Rails initializer with Elasticsearch configuration'"
-- :title: Metamorphosis
- :authors:
- - :last_name: Kafka
- :first_name: Franz
- :downloads: 22697
- :category: Fiction
- :content: |
- One morning, when Gregor Samsa woke from troubled dreams, he found
- himself transformed in his bed into a horrible vermin. He lay on
- his armour-like back, and if he lifted his head a little he could
- see his brown belly, slightly domed and divided by arches into stiff
- sections. The bedding was hardly able to cover it and seemed ready
- to slide off any moment. His many legs, pitifully thin compared
- with the size of the rest of him, waved about helplessly as he
- looked.
+# ----- Add Rake tasks ----------------------------------------------------------------------------
- "What's happened to me?" he thought. It wasn't a dream. His room,
- a proper human room although a little too small, lay peacefully
- between its four familiar walls. A collection of textile samples
- lay spread out on the table - Samsa was a travelling salesman - and
- above it there hung a picture that he had recently cut out of an
- illustrated magazine and housed in a nice, gilded frame. It showed
- a lady fitted out with a fur hat and fur boa who sat upright,
- raising a heavy fur muff that covered the whole of her lower arm
- towards the viewer.
+puts
+say_status "Application", "Adding Elasticsearch Rake tasks...\n", :yellow
+puts '-'*80, ''; sleep 0.5
- Gregor then turned to look out the window at the dull weather.
- Drops of rain could be heard hitting the pane, which made him feel
- quite sad. "How about if I sleep a little bit longer and forget all
- this nonsense", he thought, but that was something he was unable to
- do because he was used to sleeping on his right, and in his present
- state couldn't get into that position. However hard he threw
- himself onto his right, he always rolled back to where he was. He
- must have tried it a hundred times, shut his eyes so that he
- wouldn't have to look at the floundering legs, and only stopped when
- he began to feel a mild, dull pain there that he had never felt
- before.
-
- "Oh, God", he thought, "what a strenuous career it is that I've
- chosen! Travelling day in and day out. Doing business like this
- takes much more effort than doing your own business at home, and on
- top of that there's the curse of travelling, worries about making
- train connections, bad and irregular food, contact with different
- people all the time so that you can never get to know anyone or
- become friendly with them. It can all go to Hell!" He felt a
- slight itch up on his belly; pushed himself slowly up on his back
- towards the headboard so that he could lift his head better; found
- where the itch was, and saw that it was covered with lots of little
- white spots which he didn't know what to make of; and when he tried
- to feel the place with one of his legs he drew it quickly back
- because as soon as he touched it he was overcome by a cold shudder.
-
- He slid back into his former position. "Getting up early all the
- time", he thought, "it makes you stupid. You've got to get enough
- sleep. Other travelling salesmen live a life of luxury. For
- instance, whenever I go back to the guest house during the morning
- to copy out the contract, these gentlemen are always still sitting
- there eating their breakfasts. I ought to just try that with my
- boss; I'd get kicked out on the spot. But who knows, maybe that
- would be the best thing for me. If I didn't have my parents to
- think about I'd have given in my notice a long time ago, I'd have
- gone up to the boss and told him just what I think, tell him
- everything I would, let him know just what I feel. He'd fall right
- off his desk! And it's a funny sort of business to be sitting up
- there at your desk, talking down at your subordinates from up there,
- especially when you have to go right up close because the boss is
- hard of hearing. Well, there's still some hope; once I've got the
- money together to pay off my parents' debt to him - another five or
- six years I suppose - that's definitely what I'll do. That's when
- I'll make the big change. First of all though, I've got to get up,
- my train leaves at five."
-
-- :title: Crime and Punishment
- :authors:
- - :last_name: Dostoyevsky
- :first_name: Fyodor
- :downloads: 4590
- :category: Fiction
- :content: |
- On an exceptionally hot evening early in July a young man came out of
- the garret in which he lodged in S. Place and walked slowly, as though
- in hesitation, towards K. bridge.
-
- He had successfully avoided meeting his landlady on the staircase. His
- garret was under the roof of a high, five-storied house and was more
- like a cupboard than a room. The landlady who provided him with garret,
- dinners, and attendance, lived on the floor below, and every time
- he went out he was obliged to pass her kitchen, the door of which
- invariably stood open. And each time he passed, the young man had a
- sick, frightened feeling, which made him scowl and feel ashamed. He was
- hopelessly in debt to his landlady, and was afraid of meeting her.
-
- This was not because he was cowardly and abject, quite the contrary; but
- for some time past he had been in an overstrained irritable condition,
- verging on hypochondria. He had become so completely absorbed in
- himself, and isolated from his fellows that he dreaded meeting, not
- only his landlady, but anyone at all. He was crushed by poverty, but the
- anxieties of his position had of late ceased to weigh upon him. He had
- given up attending to matters of practical importance; he had lost all
- desire to do so. Nothing that any landlady could do had a real terror
- for him. But to be stopped on the stairs, to be forced to listen to her
- trivial, irrelevant gossip, to pestering demands for payment, threats
- and complaints, and to rack his brains for excuses, to prevaricate, to
- lie--no, rather than that, he would creep down the stairs like a cat and
- slip out unseen.
-
- This evening, however, on coming out into the street, he became acutely
- aware of his fears.
-
- "I want to attempt a thing _like that_ and am frightened by these
- trifles," he thought, with an odd smile. "Hm... yes, all is in a man's
- hands and he lets it all slip from cowardice, that's an axiom. It would
- be interesting to know what it is men are most afraid of. Taking a new
- step, uttering a new word is what they fear most.... But I am talking
- too much. It's because I chatter that I do nothing. Or perhaps it is
- that I chatter because I do nothing. I've learned to chatter this
- last month, lying for days together in my den thinking... of Jack the
- Giant-killer. Why am I going there now? Am I capable of _that_? Is
- _that_ serious? It is not serious at all. It's simply a fantasy to amuse
- myself; a plaything! Yes, maybe it is a plaything."
-
- The heat in the street was terrible: and the airlessness, the bustle
- and the plaster, scaffolding, bricks, and dust all about him, and that
- special Petersburg stench, so familiar to all who are unable to get out
- of town in summer--all worked painfully upon the young man's already
- overwrought nerves. The insufferable stench from the pot-houses, which
- are particularly numerous in that part of the town, and the drunken men
- whom he met continually, although it was a working day, completed
- the revolting misery of the picture. An expression of the profoundest
- disgust gleamed for a moment in the young man's refined face. He was,
- by the way, exceptionally handsome, above the average in height, slim,
- well-built, with beautiful dark eyes and dark brown hair. Soon he sank
- into deep thought, or more accurately speaking into a complete blankness
- of mind; he walked along not observing what was about him and not caring
- to observe it. From time to time, he would mutter something, from the
- habit of talking to himself, to which he had just confessed. At these
- moments he would become conscious that his ideas were sometimes in a
- tangle and that he was very weak; for two days he had scarcely tasted
- food.
-
-- :title: The Hound of the Baskervilles
- :authors:
- - :last_name: Doyle
- :first_name: Arthur Conan
- :downloads: 5021
- :category: Fiction
- :content: |
- Mr. Sherlock Holmes, who was usually very late in the mornings, save
- upon those not infrequent occasions when he was up all night, was seated
- at the breakfast table. I stood upon the hearth-rug and picked up the
- stick which our visitor had left behind him the night before. It was a
- fine, thick piece of wood, bulbous-headed, of the sort which is known as
- a "Penang lawyer." Just under the head was a broad silver band nearly
- an inch across. "To James Mortimer, M.R.C.S., from his friends of the
- C.C.H.," was engraved upon it, with the date "1884." It was just such a
- stick as the old-fashioned family practitioner used to carry--dignified,
- solid, and reassuring.
-
- "Well, Watson, what do you make of it?"
-
- Holmes was sitting with his back to me, and I had given him no sign of
- my occupation.
-
- "How did you know what I was doing? I believe you have eyes in the back
- of your head."
-
- "I have, at least, a well-polished, silver-plated coffee-pot in front of
- me," said he. "But, tell me, Watson, what do you make of our visitor's
- stick? Since we have been so unfortunate as to miss him and have no
- notion of his errand, this accidental souvenir becomes of importance.
- Let me hear you reconstruct the man by an examination of it."
-
- "I think," said I, following as far as I could the methods of my
- companion, "that Dr. Mortimer is a successful, elderly medical man,
- well-esteemed since those who know him give him this mark of their
- appreciation."
-
- "Good!" said Holmes. "Excellent!"
-
- "I think also that the probability is in favour of his being a country
- practitioner who does a great deal of his visiting on foot."
-
- "Why so?"
-
- "Because this stick, though originally a very handsome one has been so
- knocked about that I can hardly imagine a town practitioner carrying it.
- The thick-iron ferrule is worn down, so it is evident that he has done a
- great amount of walking with it."
-
- "Perfectly sound!" said Holmes.
-
- "And then again, there is the 'friends of the C.C.H.' I should guess
- that to be the Something Hunt, the local hunt to whose members he has
- possibly given some surgical assistance, and which has made him a small
- presentation in return."
-
- "Really, Watson, you excel yourself," said Holmes, pushing back his
- chair and lighting a cigarette. "I am bound to say that in all the
- accounts which you have been so good as to give of my own small
- achievements you have habitually underrated your own abilities. It may
- be that you are not yourself luminous, but you are a conductor of
- light. Some people without possessing genius have a remarkable power of
- stimulating it. I confess, my dear fellow, that I am very much in your
- debt."
-
- He had never said as much before, and I must admit that his words gave
- me keen pleasure, for I had often been piqued by his indifference to my
- admiration and to the attempts which I had made to give publicity to
- his methods. I was proud, too, to think that I had so far mastered his
- system as to apply it in a way which earned his approval. He now took
- the stick from my hands and examined it for a few minutes with his naked
- eyes. Then with an expression of interest he laid down his cigarette,
- and carrying the cane to the window, he looked over it again with a
- convex lens.
-
- "Interesting, though elementary," said he as he returned to his
- favourite corner of the settee. "There are certainly one or two
- indications upon the stick. It gives us the basis for several
- deductions."
-
-- :title: Madame Bovary
- :authors:
- - :last_name: Flaubert
- :first_name: Gustave
- :downloads: 4090
- :category: Fiction
- :content: |
- We were in class when the head-master came in, followed by a "new
- fellow," not wearing the school uniform, and a school servant carrying a
- large desk. Those who had been asleep woke up, and every one rose as if
- just surprised at his work.
-
- The head-master made a sign to us to sit down. Then, turning to the
- class-master, he said to him in a low voice--
-
- "Monsieur Roger, here is a pupil whom I recommend to your care; he'll be
- in the second. If his work and conduct are satisfactory, he will go into
- one of the upper classes, as becomes his age."
-
- The "new fellow," standing in the corner behind the door so that he
- could hardly be seen, was a country lad of about fifteen, and taller
- than any of us. His hair was cut square on his forehead like a village
- chorister's; he looked reliable, but very ill at ease. Although he was
- not broad-shouldered, his short school jacket of green cloth with black
- buttons must have been tight about the arm-holes, and showed at the
- opening of the cuffs red wrists accustomed to being bare. His legs, in
- blue stockings, looked out from beneath yellow trousers, drawn tight by
- braces, He wore stout, ill-cleaned, hob-nailed boots.
-
- We began repeating the lesson. He listened with all his ears, as
- attentive as if at a sermon, not daring even to cross his legs or lean
- on his elbow; and when at two o'clock the bell rang, the master was
- obliged to tell him to fall into line with the rest of us.
-
- When we came back to work, we were in the habit of throwing our caps on
- the ground so as to have our hands more free; we used from the door to
- toss them under the form, so that they hit against the wall and made a
- lot of dust: it was "the thing."
-
- But, whether he had not noticed the trick, or did not dare to attempt
- it, the "new fellow," was still holding his cap on his knees even after
- prayers were over. It was one of those head-gears of composite order, in
- which we can find traces of the bearskin, shako, billycock hat, sealskin
- cap, and cotton night-cap; one of those poor things, in fine, whose
- dumb ugliness has depths of expression, like an imbecile's face. Oval,
- stiffened with whalebone, it began with three round knobs; then came in
- succession lozenges of velvet and rabbit-skin separated by a red band;
- after that a sort of bag that ended in a cardboard polygon covered with
- complicated braiding, from which hung, at the end of a long thin cord,
- small twisted gold threads in the manner of a tassel. The cap was new;
- its peak shone.
-
- "Rise," said the master.
-
- He stood up; his cap fell. The whole class began to laugh. He stooped to
- pick it up. A neighbor knocked it down again with his elbow; he picked
- it up once more.
-
-- :title: Tractatus Logico-Philosophicus
- :authors:
- - :last_name: Wittgenstein
- :first_name: Ludwig
- :downloads: 4036
- :category: Philosophy
- :content: |
- 1 The world is everything that is the case.∗
- 1.1 The world is the totality of facts, not of things.
- 1.11 The world is determined by the facts, and by these being all the facts.
- 1.12 For the totality of facts determines both what is the case, and also all that is not the case.
- 1.13 The facts in logical space are the world.
- 1.2 The world divides into facts.
- 1.21 Any one can either be the case or not be the case, and everything else remain the same.
-- :title: A General Introduction to Psychoanalysis
- :authors:
- - :last_name: Freud
- :first_name: Sigmund
- :downloads: 1355
- :category: Psychology
- :content: |
- I do not know how familiar some of you may be, either from your reading
- or from hearsay, with psychoanalysis. But, in keeping with the title of
- these lectures--_A General Introduction to Psychoanalysis_--I am obliged
- to proceed as though you knew nothing about this subject, and stood in
- need of preliminary instruction.
-
- To be sure, this much I may presume that you do know, namely, that
- psychoanalysis is a method of treating nervous patients medically. And
- just at this point I can give you an example to illustrate how the
- procedure in this field is precisely the reverse of that which is the
- rule in medicine. Usually when we introduce a patient to a medical
- technique which is strange to him we minimize its difficulties and give
- him confident promises concerning the result of the treatment. When,
- however, we undertake psychoanalytic treatment with a neurotic patient
- we proceed differently. We hold before him the difficulties of the
- method, its length, the exertions and the sacrifices which it will cost
- him; and, as to the result, we tell him that we make no definite
- promises, that the result depends on his conduct, on his understanding,
- on his adaptability, on his perseverance. We have, of course, excellent
- motives for conduct which seems so perverse, and into which you will
- perhaps gain insight at a later point in these lectures.
-
- Do not be offended, therefore, if, for the present, I treat you as I
- treat these neurotic patients. Frankly, I shall dissuade you from coming
- to hear me a second time. With this intention I shall show what
- imperfections are necessarily involved in the teaching of psychoanalysis
- and what difficulties stand in the way of gaining a personal judgment. I
- shall show you how the whole trend of your previous training and all
- your accustomed mental habits must unavoidably have made you opponents
- of psychoanalysis, and how much you must overcome in yourselves in
- order to master this instinctive opposition. Of course I cannot predict
- how much psychoanalytic understanding you will gain from my lectures,
- but I can promise this, that by listening to them you will not learn how
- to undertake a psychoanalytic treatment or how to carry one to
- completion. Furthermore, should I find anyone among you who does not
- feel satisfied with a cursory acquaintance with psychoanalysis, but who
- would like to enter into a more enduring relationship with it, I shall
- not only dissuade him, but I shall actually warn him against it. As
- things now stand, a person would, by such a choice of profession, ruin
- his every chance of success at a university, and if he goes out into the
- world as a practicing physician, he will find himself in a society which
- does not understand his aims, which regards him with suspicion and
- hostility, and which turns loose upon him all the malicious spirits
- which lurk within it.
-- :title: Grimms' Fairy Tales
- :authors:
- - :last_name: Grimm
- :first_name: Jacob
- - :last_name: Grimm
- :first_name: Wilhelm
- :downloads: 25050
- :content: |
- A certain king had a beautiful garden, and in the garden stood a tree
- which bore golden apples. These apples were always counted, and about
- the time when they began to grow ripe it was found that every night one
- of them was gone. The king became very angry at this, and ordered the
- gardener to keep watch all night under the tree. The gardener set his
- eldest son to watch; but about twelve o'clock he fell asleep, and in
- the morning another of the apples was missing. Then the second son was
- ordered to watch; and at midnight he too fell asleep, and in the morning
- another apple was gone. Then the third son offered to keep watch; but
- the gardener at first would not let him, for fear some harm should come
- to him: however, at last he consented, and the young man laid himself
- under the tree to watch. As the clock struck twelve he heard a rustling
- noise in the air, and a bird came flying that was of pure gold; and as
- it was snapping at one of the apples with its beak, the gardener's son
- jumped up and shot an arrow at it. But the arrow did the bird no harm;
- only it dropped a golden feather from its tail, and then flew away.
- The golden feather was brought to the king in the morning, and all the
- council was called together. Everyone agreed that it was worth more than
- all the wealth of the kingdom: but the king said, 'One feather is of no
- use to me, I must have the whole bird.'
-
-- :title: An English Grammar
- :authors:
- - :last_name: Baskervill
- :first_name: William Malone
- - :last_name: Sewell
- :first_name: James Witt
- :downloads: 1211
- :category: Linguistics
- :content: |
- Of making many English grammars there is no end; nor should there be
- till theoretical scholarship and actual practice are more happily
- wedded. In this field much valuable work has already been
- accomplished; but it has been done largely by workers accustomed to
- take the scholar's point of view, and their writings are addressed
- rather to trained minds than to immature learners. To find an advanced
- grammar unencumbered with hard words, abstruse thoughts, and difficult
- principles, is not altogether an easy matter. These things enhance the
- difficulty which an ordinary youth experiences in grasping and
- assimilating the facts of grammar, and create a distaste for the
- study. It is therefore the leading object of this book to be both as
- scholarly and as practical as possible. In it there is an attempt to
- present grammatical facts as simply, and to lead the student to
- assimilate them as thoroughly, as possible, and at the same time to do
- away with confusing difficulties as far as may be.
-DATA
-
-[Book, Author, Authorship, Category].each { |model| model.delete_all }
-
-books.to_ruby.each do |b|
- book = Book.create \
- title: b[:title],
- downloads: b[:downloads],
- content: b[:content]
-
- b[:authors].each do |a|
- author = Author.where(first_name: a[:first_name], last_name: a[:last_name]).first_or_create
- book.authors << author
- end
-
- category = Category.where(title: b[:category]).first_or_create
- book.category = category
-
- book.save
-end
+create_file 'lib/tasks/elasticsearch.rake', <<-CODE
+require 'elasticsearch/rails/tasks/import'
CODE
-git :add => '.'
-git :commit => "-m 'Added data model and seed script (books, categories, authors)'"
+git add: "lib/tasks"
+git commit: "-m 'Added Rake tasks for Elasticsearch'"
-# === TODO: ===
-#
-# * Update views (show authors, category name, bootstrap)
-# <table class="table table-hover">
-# class: 'btn btn-default btn-xs'
-# class: 'btn btn-primary btn-xs', style: 'color: #fff'
-# <td><%= book.authors.map(&:full_name).to_sentence %></td>
-# <td><%= book.category.try(:title) || 'n/a' %></td>
-# Update controller (fight n+1)
-# @books = Book.includes(:authors, :category)
-#
+# ----- Insert and index data ---------------------------------------------------------------------
-# ----- Add search support into Book model ---------------------------------------------------------
-
-insert_into_file "app/models/book.rb", :before => "end" do
- <<-CODE
-
- include Searchable
- CODE
-end
-
-git :add => 'app/models/book.rb'
-git :commit => "-m 'Added search support into the Book model'"
-
-# === TODO: ===
-#
-# * Create search action or controller
-# @books = Book.search(params[:q]).records.includes(:authors, :category)
-# * Create view
-#
-
-# ----- Insert seed data into the database ---------------------------------------------------------
-
puts
-say_status "Database", "Seeding the database with data...", :yellow
+say_status "Database", "Re-creating the database with data and importing into Elasticsearch...", :yellow
puts '-'*80, ''; sleep 0.25
-rake "db:seed"
+# copy_file File.expand_path('../articles.yml.gz', __FILE__), 'db/articles.yml.gz'
+get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/articles.yml.gz',
+ 'db/articles.yml.gz'
-# ----- Import data into Elasticsearch ------------------------------------------------------------
+remove_file 'db/seeds.rb'
+# copy_file File.expand_path('../seeds.rb', __FILE__), 'db/seeds.rb'
+get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/seeds.rb',
+ 'db/seeds.rb'
-puts
-say_status "Index", "Indexing the database...", :yellow
-puts '-'*80, ''; sleep 0.25
+rake "db:reset"
+rake "environment elasticsearch:import:model CLASS='Article' BATCH=100 FORCE=y"
-# rake "environment elasticsearch:import:model CLASS='Article' FORCE=true"
-run "rails runner 'Book.__elasticsearch__.client.indices.delete index: Book.__elasticsearch__.index_name rescue nil; Book.__elasticsearch__.client.indices.create index: Book.__elasticsearch__.index_name; Book.__elasticsearch__.import'"
+git add: "db/seeds.rb db/articles.yml.gz"
+git commit: "-m 'Added a seed script and source data'"
# ----- Print Git log -----------------------------------------------------------------------------
puts
say_status "Git", "Details about the application:", :yellow
puts '-'*80, ''
-git :tag => "complex"
-git :log => "--reverse --oneline HEAD...pretty"
+git tag: "expert"
+git log: "--reverse --oneline HEAD...pretty"
# ----- Start the application ---------------------------------------------------------------------
-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
+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
+ port = ask("Please provide free port:", :bold)
+ else
+ port = '3000'
+ end
-puts "", "="*80
-say_status "DONE", "\e[1mStarting the application. Open http://localhost:#{port}\e[0m", :yellow
-puts "="*80, ""
+ puts "", "="*80
+ say_status "DONE", "\e[1mStarting the application. Open http://localhost:#{port}\e[0m", :yellow
+ puts "="*80, ""
-run "rails server --port=#{port}"
+ run "rails server --port=#{port}"
+end