elasticsearch-rails 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +6 -0
- data/README.md +15 -13
- data/elasticsearch-rails.gemspec +1 -0
- data/lib/elasticsearch/rails/tasks/import.rb +6 -4
- data/lib/elasticsearch/rails/version.rb +1 -1
- data/lib/rails/templates/01-basic.rb +45 -27
- data/lib/rails/templates/02-pretty.rb +30 -15
- data/lib/rails/templates/03-expert.rb +240 -825
- data/lib/rails/templates/articles.yml.gz +0 -0
- data/lib/rails/templates/index.html.erb +157 -0
- data/lib/rails/templates/indexer.rb +27 -0
- data/lib/rails/templates/search.css +72 -0
- data/lib/rails/templates/searchable.rb +212 -0
- data/lib/rails/templates/seeds.rb +56 -0
- metadata +25 -2
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -78,30 +78,32 @@ You should see the duration of the request to Elasticsearch as part of each log
|
|
78
78
|
|
79
79
|
You can generate a fully working example Ruby on Rails application, with an `Article` model and a search form,
|
80
80
|
to play with (it even downloads _Elasticsearch_ itself, generates the application skeleton and leaves you with
|
81
|
-
a _Git_ repository to explore the steps and the code)
|
81
|
+
a _Git_ repository to explore the steps and the code) with the
|
82
|
+
[`01-basic.rb`](https://github.com/elasticsearch/elasticsearch-rails/blob/master/elasticsearch-rails/lib/rails/templates/01-basic.rb) template:
|
82
83
|
|
83
84
|
```bash
|
84
85
|
rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/01-basic.rb
|
85
86
|
```
|
86
87
|
|
87
|
-
Run the same command again, in the same folder, with the
|
88
|
-
|
88
|
+
Run the same command again, in the same folder, with the
|
89
|
+
[`02-pretty`](https://github.com/elasticsearch/elasticsearch-rails/blob/master/elasticsearch-rails/lib/rails/templates/02-pretty.rb)
|
90
|
+
template to add features such as a custom `Article.search` method, result highlighting and
|
91
|
+
[_Bootstrap_](http://getbootstrap.com) integration:
|
89
92
|
|
90
93
|
```bash
|
91
94
|
rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/02-pretty.rb
|
92
95
|
```
|
93
96
|
|
94
|
-
|
95
|
-
|
97
|
+
Run the same command with the [`03-expert.rb`](https://github.com/elasticsearch/elasticsearch-rails/blob/master/elasticsearch-rails/lib/rails/templates/03-expert.rb)
|
98
|
+
template to refactor the application into a more complex use case,
|
99
|
+
with couple of hundreds of The New York Times articles as the example content.
|
100
|
+
The template will extract the Elasticsearch integration into a `Searchable` "concern" module,
|
101
|
+
define complex mapping, custom serialization, implement faceted navigation and suggestions as a part of
|
102
|
+
a complex query, and add a _Sidekiq_-based worker for updating the index in the background.
|
96
103
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
being worked on, such as:
|
101
|
-
|
102
|
-
* Rake tasks for convenient (re)indexing your models from the command line
|
103
|
-
* Hooking into Rails' notification system to display Elasticsearch related statistics in the application log
|
104
|
-
* Instrumentation support for NewRelic integration
|
104
|
+
```bash
|
105
|
+
rails new searchapp --skip --skip-bundle --template https://raw.github.com/elasticsearch/elasticsearch-rails/master/elasticsearch-rails/lib/rails/templates/03-expert.rb
|
106
|
+
```
|
105
107
|
|
106
108
|
## License
|
107
109
|
|
data/elasticsearch-rails.gemspec
CHANGED
@@ -56,16 +56,17 @@ namespace :elasticsearch do
|
|
56
56
|
rescue NoMethodError; end
|
57
57
|
end
|
58
58
|
|
59
|
-
klass.import force: ENV.fetch('FORCE', false),
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
total_errors = klass.import force: ENV.fetch('FORCE', false),
|
60
|
+
batch_size: ENV.fetch('BATCH', 1000).to_i,
|
61
|
+
index: ENV.fetch('INDEX', nil),
|
62
|
+
type: ENV.fetch('TYPE', nil) do |response|
|
63
63
|
pbar.inc response['items'].size if pbar
|
64
64
|
STDERR.flush
|
65
65
|
STDOUT.flush
|
66
66
|
end
|
67
67
|
pbar.finish if pbar
|
68
68
|
|
69
|
+
puts "[IMPORT] #{total_errors} errors occurred" unless total_errors.zero?
|
69
70
|
puts '[IMPORT] Done'
|
70
71
|
end
|
71
72
|
|
@@ -96,6 +97,7 @@ namespace :elasticsearch do
|
|
96
97
|
|
97
98
|
ENV['CLASS'] = klass.to_s
|
98
99
|
Rake::Task["elasticsearch:import:model"].invoke
|
100
|
+
Rake::Task["elasticsearch:import:model"].reenable
|
99
101
|
puts
|
100
102
|
end
|
101
103
|
end
|
@@ -20,8 +20,8 @@
|
|
20
20
|
#
|
21
21
|
# =====================================================================================================
|
22
22
|
|
23
|
-
require '
|
24
|
-
|
23
|
+
require 'uri'
|
24
|
+
require 'net/http'
|
25
25
|
|
26
26
|
at_exit do
|
27
27
|
pid = File.read("#{destination_root}/tmp/pids/elasticsearch.pid") rescue nil
|
@@ -33,7 +33,7 @@ end
|
|
33
33
|
|
34
34
|
run "touch tmp/.gitignore"
|
35
35
|
|
36
|
-
append_to_file ".gitignore", "vendor/elasticsearch-0.
|
36
|
+
append_to_file ".gitignore", "vendor/elasticsearch-1.0.1/\n"
|
37
37
|
|
38
38
|
git :init
|
39
39
|
git add: "."
|
@@ -41,12 +41,12 @@ git commit: "-m 'Initial commit: Clean application'"
|
|
41
41
|
|
42
42
|
# ----- Download Elasticsearch --------------------------------------------------------------------
|
43
43
|
|
44
|
-
unless (
|
44
|
+
unless (Net::HTTP.get(URI.parse('http://localhost:9200')) rescue false)
|
45
45
|
COMMAND = <<-COMMAND.gsub(/^ /, '')
|
46
|
-
curl -# -O "http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.
|
47
|
-
tar -zxf elasticsearch-0.
|
48
|
-
rm -f elasticsearch-0.
|
49
|
-
./elasticsearch-0.
|
46
|
+
curl -# -O "http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.0.1.tar.gz"
|
47
|
+
tar -zxf elasticsearch-1.0.1.tar.gz
|
48
|
+
rm -f elasticsearch-1.0.1.tar.gz
|
49
|
+
./elasticsearch-1.0.1/bin/elasticsearch -d -p #{destination_root}/tmp/pids/elasticsearch.pid
|
50
50
|
COMMAND
|
51
51
|
|
52
52
|
puts "\n"
|
@@ -70,7 +70,7 @@ unless (client.ping rescue false)
|
|
70
70
|
run "(#{exec})" # Launch Elasticsearch in subshell
|
71
71
|
end
|
72
72
|
end
|
73
|
-
end
|
73
|
+
end unless ENV['RAILS_NO_ES_INSTALL']
|
74
74
|
|
75
75
|
# ----- Add README --------------------------------------------------------------------------------
|
76
76
|
|
@@ -123,6 +123,7 @@ gem 'mocha', group: 'test', require: 'mocha/setup'
|
|
123
123
|
comment_lines 'Gemfile', /gem 'coffee/
|
124
124
|
comment_lines 'Gemfile', /gem 'sass/
|
125
125
|
comment_lines 'Gemfile', /gem 'uglifier/
|
126
|
+
uncomment_lines 'Gemfile', /gem 'therubyracer/
|
126
127
|
|
127
128
|
# ----- Add gems into Gemfile ---------------------------------------------------------------------
|
128
129
|
|
@@ -134,6 +135,23 @@ gem 'elasticsearch', git: 'git://github.com/elasticsearch/elasticsearch-ru
|
|
134
135
|
gem 'elasticsearch-model', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
|
135
136
|
gem 'elasticsearch-rails', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
|
136
137
|
|
138
|
+
|
139
|
+
git add: "Gemfile*"
|
140
|
+
git commit: "-m 'Added libraries into Gemfile'"
|
141
|
+
|
142
|
+
# ----- Disable asset logging in development ------------------------------------------------------
|
143
|
+
|
144
|
+
puts
|
145
|
+
say_status "Application", "Disabling asset logging in development...\n", :yellow
|
146
|
+
puts '-'*80, ''; sleep 0.25
|
147
|
+
|
148
|
+
environment 'config.assets.logger = false', env: 'development'
|
149
|
+
gem 'quiet_assets', group: "development"
|
150
|
+
|
151
|
+
git add: "Gemfile*"
|
152
|
+
git add: "config/"
|
153
|
+
git commit: "-m 'Disabled asset logging in development'"
|
154
|
+
|
137
155
|
# ----- Install gems ------------------------------------------------------------------------------
|
138
156
|
|
139
157
|
puts
|
@@ -142,9 +160,6 @@ puts '-'*80, ''
|
|
142
160
|
|
143
161
|
run "bundle install"
|
144
162
|
|
145
|
-
git add: "Gemfile*"
|
146
|
-
git commit: "-m 'Added libraries into Gemfile'"
|
147
|
-
|
148
163
|
# ----- Generate Article resource -----------------------------------------------------------------
|
149
164
|
|
150
165
|
puts
|
@@ -169,6 +184,7 @@ file 'app/models/article.rb', <<-CODE
|
|
169
184
|
class Article < ActiveRecord::Base
|
170
185
|
include Elasticsearch::Model
|
171
186
|
include Elasticsearch::Model::Callbacks
|
187
|
+
#{'attr_accessible :title, :content, :published_on' if Rails::VERSION::STRING < '4'}
|
172
188
|
end
|
173
189
|
CODE
|
174
190
|
|
@@ -221,7 +237,7 @@ resources :articles do
|
|
221
237
|
end
|
222
238
|
CODE
|
223
239
|
|
224
|
-
gsub_file 'test/controllers/articles_controller_test.rb
|
240
|
+
gsub_file "#{Rails::VERSION::STRING > '4' ? 'test/controllers' : 'test/functional'}/articles_controller_test.rb", %r{setup do.*?end}m, <<-CODE
|
225
241
|
setup do
|
226
242
|
@article = articles(:one)
|
227
243
|
|
@@ -230,7 +246,7 @@ setup do
|
|
230
246
|
end
|
231
247
|
CODE
|
232
248
|
|
233
|
-
inject_into_file 'test/controllers/articles_controller_test.rb
|
249
|
+
inject_into_file "#{Rails::VERSION::STRING > '4' ? 'test/controllers' : 'test/functional'}/articles_controller_test.rb", after: %r{test "should get index" do.*?end}m do
|
234
250
|
<<-CODE
|
235
251
|
|
236
252
|
|
@@ -300,19 +316,21 @@ git log: "--reverse --oneline"
|
|
300
316
|
|
301
317
|
# ----- Start the application ---------------------------------------------------------------------
|
302
318
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
319
|
+
unless ENV['RAILS_NO_SERVER_START']
|
320
|
+
require 'net/http'
|
321
|
+
if (begin; Net::HTTP.get(URI('http://localhost:3000')); rescue Errno::ECONNREFUSED; false; rescue Exception; true; end)
|
322
|
+
puts "\n"
|
323
|
+
say_status "ERROR", "Some other application is running on port 3000!\n", :red
|
324
|
+
puts '-'*80
|
308
325
|
|
309
|
-
|
310
|
-
else
|
311
|
-
|
312
|
-
end
|
326
|
+
port = ask("Please provide free port:", :bold)
|
327
|
+
else
|
328
|
+
port = '3000'
|
329
|
+
end
|
313
330
|
|
314
|
-
puts "", "="*80
|
315
|
-
say_status "DONE", "\e[1mStarting the application.\e[0m", :yellow
|
316
|
-
puts "="*80, ""
|
331
|
+
puts "", "="*80
|
332
|
+
say_status "DONE", "\e[1mStarting the application.\e[0m", :yellow
|
333
|
+
puts "="*80, ""
|
317
334
|
|
318
|
-
run "rails server --port=#{port}"
|
335
|
+
run "rails server --port=#{port}"
|
336
|
+
end
|
@@ -22,6 +22,19 @@ README
|
|
22
22
|
git add: "README.rdoc"
|
23
23
|
git commit: "-m '[02] Updated the application README'"
|
24
24
|
|
25
|
+
# ----- Update application.rb ---------------------------------------------------------------------
|
26
|
+
|
27
|
+
puts
|
28
|
+
say_status "Rubygems", "Adding Rails logger integration...\n", :yellow
|
29
|
+
puts '-'*80, ''; sleep 0.25
|
30
|
+
|
31
|
+
insert_into_file 'config/application.rb',
|
32
|
+
"\n\nrequire 'elasticsearch/rails/instrumentation'\n",
|
33
|
+
after: 'Bundler.require(:default, Rails.env)'
|
34
|
+
|
35
|
+
git add: "config/application.rb"
|
36
|
+
git commit: "-m 'Added the Rails logger integration to application.rb'"
|
37
|
+
|
25
38
|
# ----- Add gems into Gemfile ---------------------------------------------------------------------
|
26
39
|
|
27
40
|
puts
|
@@ -73,7 +86,7 @@ insert_into_file 'app/models/article.rb', <<-CODE, after: 'include Elasticsearch
|
|
73
86
|
end
|
74
87
|
CODE
|
75
88
|
|
76
|
-
gsub_file "test/models/article_test.rb", %r{# test "the truth" do.*?# end}m, <<-CODE
|
89
|
+
gsub_file "#{Rails::VERSION::STRING > '4' ? 'test/models' : 'test/unit' }/article_test.rb", %r{# test "the truth" do.*?# end}m, <<-CODE
|
77
90
|
|
78
91
|
test "has a search method delegating to __elasticsearch__" do
|
79
92
|
Article.__elasticsearch__.expects(:search).with do |definition|
|
@@ -85,7 +98,7 @@ gsub_file "test/models/article_test.rb", %r{# test "the truth" do.*?# end}m, <<-
|
|
85
98
|
CODE
|
86
99
|
|
87
100
|
git add: "app/models/article.rb"
|
88
|
-
git add: "test
|
101
|
+
git add: "test/**/article_test.rb"
|
89
102
|
git commit: "-m 'Added an `Article.search` method'"
|
90
103
|
|
91
104
|
# ----- Add loading Bootstrap assets --------------------------------------------------------------
|
@@ -266,19 +279,21 @@ git log: "--reverse --oneline pretty...basic"
|
|
266
279
|
|
267
280
|
# ----- Start the application ---------------------------------------------------------------------
|
268
281
|
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
282
|
+
unless ENV['RAILS_NO_SERVER_START']
|
283
|
+
require 'net/http'
|
284
|
+
if (begin; Net::HTTP.get(URI('http://localhost:3000')); rescue Errno::ECONNREFUSED; false; rescue Exception; true; end)
|
285
|
+
puts "\n"
|
286
|
+
say_status "ERROR", "Some other application is running on port 3000!\n", :red
|
287
|
+
puts '-'*80
|
274
288
|
|
275
|
-
|
276
|
-
else
|
277
|
-
|
278
|
-
end
|
289
|
+
port = ask("Please provide free port:", :bold)
|
290
|
+
else
|
291
|
+
port = '3000'
|
292
|
+
end
|
279
293
|
|
280
|
-
puts "", "="*80
|
281
|
-
say_status "DONE", "\e[1mStarting the application. Open http://localhost:#{port}\e[0m", :yellow
|
282
|
-
puts "="*80, ""
|
294
|
+
puts "", "="*80
|
295
|
+
say_status "DONE", "\e[1mStarting the application. Open http://localhost:#{port}\e[0m", :yellow
|
296
|
+
puts "="*80, ""
|
283
297
|
|
284
|
-
run "rails server --port=#{port}"
|
298
|
+
run "rails server --port=#{port}"
|
299
|
+
end
|
@@ -2,113 +2,98 @@
|
|
2
2
|
|
3
3
|
# (See: 01-basic.rb, 02-pretty.rb)
|
4
4
|
|
5
|
-
|
5
|
+
append_to_file 'README.rdoc', <<-README
|
6
|
+
|
7
|
+
== [3] Expert
|
8
|
+
|
9
|
+
The `expert` template changes to a complex database schema with model relationships: article belongs
|
10
|
+
to a category, has many authors and comments.
|
11
|
+
|
12
|
+
* The Elasticsearch integration is refactored into the `Searchable` concern
|
13
|
+
* A complex mapping for the index is defined
|
14
|
+
* A custom serialization is defined in `Article#as_indexed_json`
|
15
|
+
* The `search` method is amended with facets and suggestions
|
16
|
+
* A [Sidekiq](http://sidekiq.org) worker for handling index updates in background is added
|
17
|
+
* A custom `SearchController` with associated view is added
|
18
|
+
* A Rails initializer is added to customize the Elasticsearch client configuration
|
19
|
+
* Seed script and example data from New York Times is added
|
20
|
+
|
21
|
+
README
|
22
|
+
|
23
|
+
git add: "README.rdoc"
|
24
|
+
git commit: "-m '[03] Updated the application README'"
|
25
|
+
|
26
|
+
# ----- Add gems into Gemfile ---------------------------------------------------------------------
|
6
27
|
|
7
28
|
puts
|
8
|
-
say_status "
|
9
|
-
puts '-'*80, ''; sleep 0.
|
29
|
+
say_status "Rubygems", "Adding Rubygems into Gemfile...\n", :yellow
|
30
|
+
puts '-'*80, ''; sleep 0.25
|
10
31
|
|
11
|
-
|
12
|
-
create_file "app/views/articles/_search_form.html.erb", match
|
13
|
-
"\n<%= render partial: 'search_form' %>\n"
|
14
|
-
end
|
32
|
+
gem "oj"
|
15
33
|
|
16
|
-
git :
|
17
|
-
git :
|
34
|
+
git add: "Gemfile*"
|
35
|
+
git commit: "-m 'Added Ruby gems'"
|
18
36
|
|
19
|
-
# -----
|
37
|
+
# ----- Customize the Rails console ---------------------------------------------------------------
|
20
38
|
|
21
39
|
puts
|
22
|
-
say_status "
|
23
|
-
puts '-'*80, ''; sleep 0.
|
40
|
+
say_status "Rails", "Customizing `rails console`...\n", :yellow
|
41
|
+
puts '-'*80, ''; sleep 0.25
|
24
42
|
|
25
|
-
create_file 'app/models/concerns/searchable.rb', <<-CODE
|
26
|
-
module Searchable
|
27
|
-
extend ActiveSupport::Concern
|
28
43
|
|
29
|
-
|
30
|
-
include Elasticsearch::Model
|
31
|
-
end
|
44
|
+
gem "pry", group: 'development'
|
32
45
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
fields: ['title^10', 'content']
|
41
|
-
}
|
42
|
-
},
|
43
|
-
highlight: {
|
44
|
-
pre_tags: ['<em class="label label-highlight">'],
|
45
|
-
post_tags: ['</em>'],
|
46
|
-
fields: {
|
47
|
-
title: { number_of_fragments: 0 },
|
48
|
-
content: { fragment_size: 25 }
|
49
|
-
}
|
50
|
-
}
|
51
|
-
}
|
52
|
-
)
|
53
|
-
end
|
46
|
+
environment nil, env: 'development' do
|
47
|
+
%q{
|
48
|
+
console do
|
49
|
+
config.console = Pry
|
50
|
+
Pry.config.history.file = Rails.root.join('tmp/console_history.rb').to_s
|
51
|
+
Pry.config.prompt = [ proc { |obj, nest_level, _| "(#{obj})> " },
|
52
|
+
proc { |obj, nest_level, _| ' '*obj.to_s.size + ' '*(nest_level+1) + '| ' } ]
|
54
53
|
end
|
54
|
+
}
|
55
55
|
end
|
56
|
-
CODE
|
57
56
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
include Searchable
|
62
|
-
end
|
63
|
-
CODE
|
57
|
+
git add: "Gemfile*"
|
58
|
+
git add: "config/"
|
59
|
+
git commit: "-m 'Added Pry as the console for development'"
|
64
60
|
|
65
|
-
|
66
|
-
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/'"
|
67
|
-
|
68
|
-
# ----- Add initializer ---------------------------------------------------------------------------
|
61
|
+
# ----- Disable asset logging in development ------------------------------------------------------
|
69
62
|
|
70
63
|
puts
|
71
|
-
say_status "Application", "
|
72
|
-
puts '-'*80, ''; sleep 0.
|
64
|
+
say_status "Application", "Disabling asset logging in development...\n", :yellow
|
65
|
+
puts '-'*80, ''; sleep 0.25
|
73
66
|
|
74
|
-
|
75
|
-
|
76
|
-
ELASTICSEARCH_URL = ENV['ELASTICSEARCH_URL'] || 'http://localhost:9200'
|
67
|
+
environment 'config.assets.logger = false', env: 'development'
|
68
|
+
gem 'quiet_assets', group: "development"
|
77
69
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
tracer = ActiveSupport::Logger.new(STDERR)
|
82
|
-
tracer.level = Logger::INFO
|
83
|
-
end
|
70
|
+
git add: "Gemfile*"
|
71
|
+
git add: "config/"
|
72
|
+
git commit: "-m 'Disabled asset logging in development'"
|
84
73
|
|
85
|
-
|
86
|
-
CODE
|
74
|
+
# ----- Run bundle install ------------------------------------------------------------------------
|
87
75
|
|
88
|
-
|
89
|
-
git :commit => "-m 'Added application initializer with Elasticsearch configuration'"
|
76
|
+
run "bundle install"
|
90
77
|
|
91
|
-
# -----
|
78
|
+
# ----- Define and generate schema ----------------------------------------------------------------
|
92
79
|
|
93
80
|
puts
|
94
|
-
say_status "
|
95
|
-
puts '-'*80, ''
|
81
|
+
say_status "Models", "Adding complex schema...\n", :yellow
|
82
|
+
puts '-'*80, ''
|
96
83
|
|
97
84
|
generate :scaffold, "Category title"
|
98
|
-
generate :scaffold, "Book title:string content:text downloads:integer category:references"
|
99
85
|
generate :scaffold, "Author first_name last_name"
|
100
|
-
generate :scaffold, "Authorship
|
86
|
+
generate :scaffold, "Authorship article:references author:references"
|
101
87
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
88
|
+
generate :model, "Comment body:text user:string user_location:string stars:integer pick:boolean article:references"
|
89
|
+
generate :migration, "CreateArticlesCategories article:references category:references"
|
90
|
+
|
91
|
+
rake "db:drop"
|
92
|
+
rake "db:migrate"
|
107
93
|
|
108
|
-
insert_into_file "app/models/
|
94
|
+
insert_into_file "app/models/category.rb", :before => "end" do
|
109
95
|
<<-CODE
|
110
|
-
|
111
|
-
has_many :authors, through: :authorships
|
96
|
+
has_and_belongs_to_many :articles
|
112
97
|
CODE
|
113
98
|
end
|
114
99
|
|
@@ -122,764 +107,192 @@ insert_into_file "app/models/author.rb", :before => "end" do
|
|
122
107
|
CODE
|
123
108
|
end
|
124
109
|
|
125
|
-
|
110
|
+
gsub_file "app/models/authorship.rb", %r{belongs_to :article$}, <<-CODE
|
111
|
+
belongs_to :article, touch: true
|
112
|
+
CODE
|
113
|
+
|
114
|
+
insert_into_file "app/models/article.rb", after: "ActiveRecord::Base" do
|
115
|
+
<<-CODE
|
116
|
+
|
117
|
+
has_and_belongs_to_many :categories, after_add: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ],
|
118
|
+
after_remove: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ]
|
119
|
+
has_many :authorships
|
120
|
+
has_many :authors, through: :authorships
|
121
|
+
has_many :comments
|
122
|
+
CODE
|
123
|
+
end
|
124
|
+
|
125
|
+
gsub_file "app/models/comment.rb", %r{belongs_to :article$}, <<-CODE
|
126
|
+
belongs_to :article, touch: true
|
127
|
+
CODE
|
126
128
|
|
127
|
-
|
129
|
+
git add: "."
|
130
|
+
git commit: "-m 'Generated Category, Author and Comment resources'"
|
128
131
|
|
129
|
-
# -----
|
132
|
+
# ----- Add the `abstract` column -----------------------------------------------------------------
|
130
133
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
books = YAML.parse <<-DATA
|
138
|
-
---
|
139
|
-
- :title: Dracula
|
140
|
-
:authors:
|
141
|
-
- :last_name: Stoker
|
142
|
-
:first_name: Bram
|
143
|
-
:downloads: 12197
|
144
|
-
:category: Fiction
|
145
|
-
:content: |
|
146
|
-
_3 May. Bistritz._--Left Munich at 8:35 P. M., on 1st May, arriving at
|
147
|
-
Vienna early next morning; should have arrived at 6:46, but train was an
|
148
|
-
hour late. Buda-Pesth seems a wonderful place, from the glimpse which I
|
149
|
-
got of it from the train and the little I could walk through the
|
150
|
-
streets. I feared to go very far from the station, as we had arrived
|
151
|
-
late and would start as near the correct time as possible. The
|
152
|
-
impression I had was that we were leaving the West and entering the
|
153
|
-
East; the most western of splendid bridges over the Danube, which is
|
154
|
-
here of noble width and depth, took us among the traditions of Turkish
|
155
|
-
rule.
|
156
|
-
|
157
|
-
We left in pretty good time, and came after nightfall to Klausenburgh.
|
158
|
-
Here I stopped for the night at the Hotel Royale. I had for dinner, or
|
159
|
-
rather supper, a chicken done up some way with red pepper, which was
|
160
|
-
very good but thirsty. (_Mem._, get recipe for Mina.) I asked the
|
161
|
-
waiter, and he said it was called "paprika hendl," and that, as it was a
|
162
|
-
national dish, I should be able to get it anywhere along the
|
163
|
-
Carpathians. I found my smattering of German very useful here; indeed, I
|
164
|
-
don't know how I should be able to get on without it.
|
165
|
-
|
166
|
-
Having had some time at my disposal when in London, I had visited the
|
167
|
-
British Museum, and made search among the books and maps in the library
|
168
|
-
regarding Transylvania; it had struck me that some foreknowledge of the
|
169
|
-
country could hardly fail to have some importance in dealing with a
|
170
|
-
nobleman of that country. I find that the district he named is in the
|
171
|
-
extreme east of the country, just on the borders of three states,
|
172
|
-
Transylvania, Moldavia and Bukovina, in the midst of the Carpathian
|
173
|
-
mountains; one of the wildest and least known portions of Europe. I was
|
174
|
-
not able to light on any map or work giving the exact locality of the
|
175
|
-
Castle Dracula, as there are no maps of this country as yet to compare
|
176
|
-
with our own Ordnance Survey maps; but I found that Bistritz, the post
|
177
|
-
town named by Count Dracula, is a fairly well-known place. I shall enter
|
178
|
-
here some of my notes, as they may refresh my memory when I talk over my
|
179
|
-
travels with Mina.
|
180
|
-
|
181
|
-
In the population of Transylvania there are four distinct nationalities:
|
182
|
-
Saxons in the South, and mixed with them the Wallachs, who are the
|
183
|
-
descendants of the Dacians; Magyars in the West, and Szekelys in the
|
184
|
-
East and North. I am going among the latter, who claim to be descended
|
185
|
-
from Attila and the Huns. This may be so, for when the Magyars conquered
|
186
|
-
the country in the eleventh century they found the Huns settled in it. I
|
187
|
-
read that every known superstition in the world is gathered into the
|
188
|
-
horseshoe of the Carpathians, as if it were the centre of some sort of
|
189
|
-
imaginative whirlpool; if so my stay may be very interesting. (_Mem._, I
|
190
|
-
must ask the Count all about them.)
|
191
|
-
|
192
|
-
I did not sleep well, though my bed was comfortable enough, for I had
|
193
|
-
all sorts of queer dreams. There was a dog howling all night under my
|
194
|
-
window, which may have had something to do with it; or it may have been
|
195
|
-
the paprika, for I had to drink up all the water in my carafe, and was
|
196
|
-
still thirsty. Towards morning I slept and was wakened by the continuous
|
197
|
-
knocking at my door, so I guess I must have been sleeping soundly then.
|
198
|
-
I had for breakfast more paprika, and a sort of porridge of maize flour
|
199
|
-
which they said was "mamaliga," and egg-plant stuffed with forcemeat, a
|
200
|
-
very excellent dish, which they call "impletata." (_Mem._, get recipe
|
201
|
-
for this also.) I had to hurry breakfast, for the train started a little
|
202
|
-
before eight, or rather it ought to have done so, for after rushing to
|
203
|
-
the station at 7:30 I had to sit in the carriage for more than an hour
|
204
|
-
before we began to move. It seems to me that the further east you go the
|
205
|
-
more unpunctual are the trains. What ought they to be in China?
|
206
|
-
|
207
|
-
All day long we seemed to dawdle through a country which was full of
|
208
|
-
beauty of every kind. Sometimes we saw little towns or castles on the
|
209
|
-
top of steep hills such as we see in old missals; sometimes we ran by
|
210
|
-
rivers and streams which seemed from the wide stony margin on each side
|
211
|
-
of them to be subject to great floods. It takes a lot of water, and
|
212
|
-
running strong, to sweep the outside edge of a river clear. At every
|
213
|
-
station there were groups of people, sometimes crowds, and in all sorts
|
214
|
-
of attire. Some of them were just like the peasants at home or those I
|
215
|
-
saw coming through France and Germany, with short jackets and round hats
|
216
|
-
and home-made trousers; but others were very picturesque. The women
|
217
|
-
looked pretty, except when you got near them, but they were very clumsy
|
218
|
-
about the waist. They had all full white sleeves of some kind or other,
|
219
|
-
and most of them had big belts with a lot of strips of something
|
220
|
-
fluttering from them like the dresses in a ballet, but of course there
|
221
|
-
were petticoats under them. The strangest figures we saw were the
|
222
|
-
Slovaks, who were more barbarian than the rest, with their big cow-boy
|
223
|
-
hats, great baggy dirty-white trousers, white linen shirts, and enormous
|
224
|
-
heavy leather belts, nearly a foot wide, all studded over with brass
|
225
|
-
nails. They wore high boots, with their trousers tucked into them, and
|
226
|
-
had long black hair and heavy black moustaches. They are very
|
227
|
-
picturesque, but do not look prepossessing. On the stage they would be
|
228
|
-
set down at once as some old Oriental band of brigands. They are,
|
229
|
-
however, I am told, very harmless and rather wanting in natural
|
230
|
-
self-assertion.
|
231
|
-
|
232
|
-
It was on the dark side of twilight when we got to Bistritz, which is a
|
233
|
-
very interesting old place. Being practically on the frontier--for the
|
234
|
-
Borgo Pass leads from it into Bukovina--it has had a very stormy
|
235
|
-
existence, and it certainly shows marks of it. Fifty years ago a series
|
236
|
-
of great fires took place, which made terrible havoc on five separate
|
237
|
-
occasions. At the very beginning of the seventeenth century it underwent
|
238
|
-
a siege of three weeks and lost 13,000 people, the casualties of war
|
239
|
-
proper being assisted by famine and disease.
|
240
|
-
|
241
|
-
Count Dracula had directed me to go to the Golden Krone Hotel, which I
|
242
|
-
found, to my great delight, to be thoroughly old-fashioned, for of
|
243
|
-
course I wanted to see all I could of the ways of the country. I was
|
244
|
-
evidently expected, for when I got near the door I faced a
|
245
|
-
cheery-looking elderly woman in the usual peasant dress--white
|
246
|
-
undergarment with long double apron, front, and back, of coloured stuff
|
247
|
-
fitting almost too tight for modesty. When I came close she bowed and
|
248
|
-
said, "The Herr Englishman?" "Yes," I said, "Jonathan Harker." She
|
249
|
-
smiled, and gave some message to an elderly man in white shirt-sleeves,
|
250
|
-
who had followed her to the door. He went, but immediately returned with
|
251
|
-
a letter:--
|
252
|
-
|
253
|
-
"My Friend.--Welcome to the Carpathians. I am anxiously expecting
|
254
|
-
you. Sleep well to-night. At three to-morrow the diligence will
|
255
|
-
start for Bukovina; a place on it is kept for you. At the Borgo
|
256
|
-
Pass my carriage will await you and will bring you to me. I trust
|
257
|
-
that your journey from London has been a happy one, and that you
|
258
|
-
will enjoy your stay in my beautiful land.
|
259
|
-
|
260
|
-
"Your friend,
|
261
|
-
|
262
|
-
"DRACULA."
|
263
|
-
|
264
|
-
- :title: Beyond Good and Evil
|
265
|
-
:authors:
|
266
|
-
- :last_name: Nietzsche
|
267
|
-
:first_name: Friedrich Wilhelm
|
268
|
-
:downloads: 8222
|
269
|
-
:category: Philosophy
|
270
|
-
:content: |
|
271
|
-
SUPPOSING that Truth is a woman--what then? Is there not ground
|
272
|
-
for suspecting that all philosophers, in so far as they have been
|
273
|
-
dogmatists, have failed to understand women--that the terrible
|
274
|
-
seriousness and clumsy importunity with which they have usually paid
|
275
|
-
their addresses to Truth, have been unskilled and unseemly methods for
|
276
|
-
winning a woman? Certainly she has never allowed herself to be won; and
|
277
|
-
at present every kind of dogma stands with sad and discouraged mien--IF,
|
278
|
-
indeed, it stands at all! For there are scoffers who maintain that it
|
279
|
-
has fallen, that all dogma lies on the ground--nay more, that it is at
|
280
|
-
its last gasp. But to speak seriously, there are good grounds for hoping
|
281
|
-
that all dogmatizing in philosophy, whatever solemn, whatever conclusive
|
282
|
-
and decided airs it has assumed, may have been only a noble puerilism
|
283
|
-
and tyronism; and probably the time is at hand when it will be once
|
284
|
-
and again understood WHAT has actually sufficed for the basis of such
|
285
|
-
imposing and absolute philosophical edifices as the dogmatists have
|
286
|
-
hitherto reared: perhaps some popular superstition of immemorial time
|
287
|
-
(such as the soul-superstition, which, in the form of subject- and
|
288
|
-
ego-superstition, has not yet ceased doing mischief): perhaps some
|
289
|
-
play upon words, a deception on the part of grammar, or an
|
290
|
-
audacious generalization of very restricted, very personal, very
|
291
|
-
human--all-too-human facts. The philosophy of the dogmatists, it is to
|
292
|
-
be hoped, was only a promise for thousands of years afterwards, as was
|
293
|
-
astrology in still earlier times, in the service of which probably more
|
294
|
-
labour, gold, acuteness, and patience have been spent than on any
|
295
|
-
actual science hitherto: we owe to it, and to its "super-terrestrial"
|
296
|
-
pretensions in Asia and Egypt, the grand style of architecture. It seems
|
297
|
-
that in order to inscribe themselves upon the heart of humanity with
|
298
|
-
everlasting claims, all great things have first to wander about the
|
299
|
-
earth as enormous and awe-inspiring caricatures: dogmatic philosophy has
|
300
|
-
been a caricature of this kind--for instance, the Vedanta doctrine in
|
301
|
-
Asia, and Platonism in Europe. Let us not be ungrateful to it, although
|
302
|
-
it must certainly be confessed that the worst, the most tiresome,
|
303
|
-
and the most dangerous of errors hitherto has been a dogmatist
|
304
|
-
error--namely, Plato's invention of Pure Spirit and the Good in Itself.
|
305
|
-
But now when it has been surmounted, when Europe, rid of this nightmare,
|
306
|
-
can again draw breath freely and at least enjoy a healthier--sleep,
|
307
|
-
we, WHOSE DUTY IS WAKEFULNESS ITSELF, are the heirs of all the strength
|
308
|
-
which the struggle against this error has fostered. It amounted to
|
309
|
-
the very inversion of truth, and the denial of the PERSPECTIVE--the
|
310
|
-
fundamental condition--of life, to speak of Spirit and the Good as Plato
|
311
|
-
spoke of them; indeed one might ask, as a physician: "How did such a
|
312
|
-
malady attack that finest product of antiquity, Plato? Had the wicked
|
313
|
-
Socrates really corrupted him? Was Socrates after all a corrupter of
|
314
|
-
youths, and deserved his hemlock?" But the struggle against Plato,
|
315
|
-
or--to speak plainer, and for the "people"--the struggle against
|
316
|
-
the ecclesiastical oppression of millenniums of Christianity (FOR
|
317
|
-
CHRISTIANITY IS PLATONISM FOR THE "PEOPLE"), produced in Europe
|
318
|
-
a magnificent tension of soul, such as had not existed anywhere
|
319
|
-
previously; with such a tensely strained bow one can now aim at the
|
320
|
-
furthest goals. As a matter of fact, the European feels this tension as
|
321
|
-
a state of distress, and twice attempts have been made in grand style to
|
322
|
-
unbend the bow: once by means of Jesuitism, and the second time by means
|
323
|
-
of democratic enlightenment--which, with the aid of liberty of the press
|
324
|
-
and newspaper-reading, might, in fact, bring it about that the spirit
|
325
|
-
would not so easily find itself in "distress"! (The Germans invented
|
326
|
-
gunpowder--all credit to them! but they again made things square--they
|
327
|
-
invented printing.) But we, who are neither Jesuits, nor democrats,
|
328
|
-
nor even sufficiently Germans, we GOOD EUROPEANS, and free, VERY free
|
329
|
-
spirits--we have it still, all the distress of spirit and all the
|
330
|
-
tension of its bow! And perhaps also the arrow, the duty, and, who
|
331
|
-
knows? THE GOAL TO AIM AT....
|
332
|
-
|
333
|
-
Sils Maria Upper Engadine, JUNE, 1885.
|
334
|
-
|
335
|
-
- :title: Ulysses
|
336
|
-
:authors:
|
337
|
-
- :last_name: Joyce
|
338
|
-
:first_name: James
|
339
|
-
:downloads: 14679
|
340
|
-
:category: Fiction
|
341
|
-
:content: |
|
342
|
-
Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of
|
343
|
-
lather on which a mirror and a razor lay crossed. A yellow dressinggown,
|
344
|
-
ungirdled, was sustained gently behind him on the mild morning air. He
|
345
|
-
held the bowl aloft and intoned:
|
346
|
-
|
347
|
-
--_Introibo ad altare Dei_.
|
348
|
-
|
349
|
-
Halted, he peered down the dark winding stairs and called out coarsely:
|
350
|
-
|
351
|
-
--Come up, Kinch! Come up, you fearful jesuit!
|
352
|
-
|
353
|
-
Solemnly he came forward and mounted the round gunrest. He faced about
|
354
|
-
and blessed gravely thrice the tower, the surrounding land and the
|
355
|
-
awaking mountains. Then, catching sight of Stephen Dedalus, he bent
|
356
|
-
towards him and made rapid crosses in the air, gurgling in his throat
|
357
|
-
and shaking his head. Stephen Dedalus, displeased and sleepy, leaned
|
358
|
-
his arms on the top of the staircase and looked coldly at the shaking
|
359
|
-
gurgling face that blessed him, equine in its length, and at the light
|
360
|
-
untonsured hair, grained and hued like pale oak.
|
361
|
-
|
362
|
-
Buck Mulligan peeped an instant under the mirror and then covered the
|
363
|
-
bowl smartly.
|
364
|
-
|
365
|
-
--Back to barracks! he said sternly.
|
366
|
-
|
367
|
-
He added in a preacher's tone:
|
368
|
-
|
369
|
-
--For this, O dearly beloved, is the genuine Christine: body and soul
|
370
|
-
and blood and ouns. Slow music, please. Shut your eyes, gents. One
|
371
|
-
moment. A little trouble about those white corpuscles. Silence, all.
|
372
|
-
|
373
|
-
He peered sideways up and gave a long slow whistle of call, then paused
|
374
|
-
awhile in rapt attention, his even white teeth glistening here and there
|
375
|
-
with gold points. Chrysostomos. Two strong shrill whistles answered
|
376
|
-
through the calm.
|
377
|
-
|
378
|
-
--Thanks, old chap, he cried briskly. That will do nicely. Switch off
|
379
|
-
the current, will you?
|
380
|
-
|
381
|
-
He skipped off the gunrest and looked gravely at his watcher, gathering
|
382
|
-
about his legs the loose folds of his gown. The plump shadowed face and
|
383
|
-
sullen oval jowl recalled a prelate, patron of arts in the middle ages.
|
384
|
-
A pleasant smile broke quietly over his lips.
|
385
|
-
|
386
|
-
--The mockery of it! he said gaily. Your absurd name, an ancient Greek!
|
387
|
-
|
388
|
-
He pointed his finger in friendly jest and went over to the parapet,
|
389
|
-
laughing to himself. Stephen Dedalus stepped up, followed him wearily
|
390
|
-
halfway and sat down on the edge of the gunrest, watching him still as
|
391
|
-
he propped his mirror on the parapet, dipped the brush in the bowl and
|
392
|
-
lathered cheeks and neck.
|
393
|
-
|
394
|
-
Buck Mulligan's gay voice went on.
|
395
|
-
|
396
|
-
--My name is absurd too: Malachi Mulligan, two dactyls. But it has a
|
397
|
-
Hellenic ring, hasn't it? Tripping and sunny like the buck himself.
|
398
|
-
We must go to Athens. Will you come if I can get the aunt to fork out
|
399
|
-
twenty quid?
|
400
|
-
|
401
|
-
He laid the brush aside and, laughing with delight, cried:
|
402
|
-
|
403
|
-
--Will he come? The jejune jesuit!
|
404
|
-
|
405
|
-
Ceasing, he began to shave with care.
|
406
|
-
|
407
|
-
--Tell me, Mulligan, Stephen said quietly.
|
408
|
-
|
409
|
-
--Yes, my love?
|
410
|
-
|
411
|
-
--How long is Haines going to stay in this tower?
|
412
|
-
|
413
|
-
Buck Mulligan showed a shaven cheek over his right shoulder.
|
414
|
-
|
415
|
-
- :title: Metamorphosis
|
416
|
-
:authors:
|
417
|
-
- :last_name: Kafka
|
418
|
-
:first_name: Franz
|
419
|
-
:downloads: 22697
|
420
|
-
:category: Fiction
|
421
|
-
:content: |
|
422
|
-
One morning, when Gregor Samsa woke from troubled dreams, he found
|
423
|
-
himself transformed in his bed into a horrible vermin. He lay on
|
424
|
-
his armour-like back, and if he lifted his head a little he could
|
425
|
-
see his brown belly, slightly domed and divided by arches into stiff
|
426
|
-
sections. The bedding was hardly able to cover it and seemed ready
|
427
|
-
to slide off any moment. His many legs, pitifully thin compared
|
428
|
-
with the size of the rest of him, waved about helplessly as he
|
429
|
-
looked.
|
430
|
-
|
431
|
-
"What's happened to me?" he thought. It wasn't a dream. His room,
|
432
|
-
a proper human room although a little too small, lay peacefully
|
433
|
-
between its four familiar walls. A collection of textile samples
|
434
|
-
lay spread out on the table - Samsa was a travelling salesman - and
|
435
|
-
above it there hung a picture that he had recently cut out of an
|
436
|
-
illustrated magazine and housed in a nice, gilded frame. It showed
|
437
|
-
a lady fitted out with a fur hat and fur boa who sat upright,
|
438
|
-
raising a heavy fur muff that covered the whole of her lower arm
|
439
|
-
towards the viewer.
|
440
|
-
|
441
|
-
Gregor then turned to look out the window at the dull weather.
|
442
|
-
Drops of rain could be heard hitting the pane, which made him feel
|
443
|
-
quite sad. "How about if I sleep a little bit longer and forget all
|
444
|
-
this nonsense", he thought, but that was something he was unable to
|
445
|
-
do because he was used to sleeping on his right, and in his present
|
446
|
-
state couldn't get into that position. However hard he threw
|
447
|
-
himself onto his right, he always rolled back to where he was. He
|
448
|
-
must have tried it a hundred times, shut his eyes so that he
|
449
|
-
wouldn't have to look at the floundering legs, and only stopped when
|
450
|
-
he began to feel a mild, dull pain there that he had never felt
|
451
|
-
before.
|
452
|
-
|
453
|
-
"Oh, God", he thought, "what a strenuous career it is that I've
|
454
|
-
chosen! Travelling day in and day out. Doing business like this
|
455
|
-
takes much more effort than doing your own business at home, and on
|
456
|
-
top of that there's the curse of travelling, worries about making
|
457
|
-
train connections, bad and irregular food, contact with different
|
458
|
-
people all the time so that you can never get to know anyone or
|
459
|
-
become friendly with them. It can all go to Hell!" He felt a
|
460
|
-
slight itch up on his belly; pushed himself slowly up on his back
|
461
|
-
towards the headboard so that he could lift his head better; found
|
462
|
-
where the itch was, and saw that it was covered with lots of little
|
463
|
-
white spots which he didn't know what to make of; and when he tried
|
464
|
-
to feel the place with one of his legs he drew it quickly back
|
465
|
-
because as soon as he touched it he was overcome by a cold shudder.
|
466
|
-
|
467
|
-
He slid back into his former position. "Getting up early all the
|
468
|
-
time", he thought, "it makes you stupid. You've got to get enough
|
469
|
-
sleep. Other travelling salesmen live a life of luxury. For
|
470
|
-
instance, whenever I go back to the guest house during the morning
|
471
|
-
to copy out the contract, these gentlemen are always still sitting
|
472
|
-
there eating their breakfasts. I ought to just try that with my
|
473
|
-
boss; I'd get kicked out on the spot. But who knows, maybe that
|
474
|
-
would be the best thing for me. If I didn't have my parents to
|
475
|
-
think about I'd have given in my notice a long time ago, I'd have
|
476
|
-
gone up to the boss and told him just what I think, tell him
|
477
|
-
everything I would, let him know just what I feel. He'd fall right
|
478
|
-
off his desk! And it's a funny sort of business to be sitting up
|
479
|
-
there at your desk, talking down at your subordinates from up there,
|
480
|
-
especially when you have to go right up close because the boss is
|
481
|
-
hard of hearing. Well, there's still some hope; once I've got the
|
482
|
-
money together to pay off my parents' debt to him - another five or
|
483
|
-
six years I suppose - that's definitely what I'll do. That's when
|
484
|
-
I'll make the big change. First of all though, I've got to get up,
|
485
|
-
my train leaves at five."
|
486
|
-
|
487
|
-
- :title: Crime and Punishment
|
488
|
-
:authors:
|
489
|
-
- :last_name: Dostoyevsky
|
490
|
-
:first_name: Fyodor
|
491
|
-
:downloads: 4590
|
492
|
-
:category: Fiction
|
493
|
-
:content: |
|
494
|
-
On an exceptionally hot evening early in July a young man came out of
|
495
|
-
the garret in which he lodged in S. Place and walked slowly, as though
|
496
|
-
in hesitation, towards K. bridge.
|
497
|
-
|
498
|
-
He had successfully avoided meeting his landlady on the staircase. His
|
499
|
-
garret was under the roof of a high, five-storied house and was more
|
500
|
-
like a cupboard than a room. The landlady who provided him with garret,
|
501
|
-
dinners, and attendance, lived on the floor below, and every time
|
502
|
-
he went out he was obliged to pass her kitchen, the door of which
|
503
|
-
invariably stood open. And each time he passed, the young man had a
|
504
|
-
sick, frightened feeling, which made him scowl and feel ashamed. He was
|
505
|
-
hopelessly in debt to his landlady, and was afraid of meeting her.
|
506
|
-
|
507
|
-
This was not because he was cowardly and abject, quite the contrary; but
|
508
|
-
for some time past he had been in an overstrained irritable condition,
|
509
|
-
verging on hypochondria. He had become so completely absorbed in
|
510
|
-
himself, and isolated from his fellows that he dreaded meeting, not
|
511
|
-
only his landlady, but anyone at all. He was crushed by poverty, but the
|
512
|
-
anxieties of his position had of late ceased to weigh upon him. He had
|
513
|
-
given up attending to matters of practical importance; he had lost all
|
514
|
-
desire to do so. Nothing that any landlady could do had a real terror
|
515
|
-
for him. But to be stopped on the stairs, to be forced to listen to her
|
516
|
-
trivial, irrelevant gossip, to pestering demands for payment, threats
|
517
|
-
and complaints, and to rack his brains for excuses, to prevaricate, to
|
518
|
-
lie--no, rather than that, he would creep down the stairs like a cat and
|
519
|
-
slip out unseen.
|
520
|
-
|
521
|
-
This evening, however, on coming out into the street, he became acutely
|
522
|
-
aware of his fears.
|
523
|
-
|
524
|
-
"I want to attempt a thing _like that_ and am frightened by these
|
525
|
-
trifles," he thought, with an odd smile. "Hm... yes, all is in a man's
|
526
|
-
hands and he lets it all slip from cowardice, that's an axiom. It would
|
527
|
-
be interesting to know what it is men are most afraid of. Taking a new
|
528
|
-
step, uttering a new word is what they fear most.... But I am talking
|
529
|
-
too much. It's because I chatter that I do nothing. Or perhaps it is
|
530
|
-
that I chatter because I do nothing. I've learned to chatter this
|
531
|
-
last month, lying for days together in my den thinking... of Jack the
|
532
|
-
Giant-killer. Why am I going there now? Am I capable of _that_? Is
|
533
|
-
_that_ serious? It is not serious at all. It's simply a fantasy to amuse
|
534
|
-
myself; a plaything! Yes, maybe it is a plaything."
|
535
|
-
|
536
|
-
The heat in the street was terrible: and the airlessness, the bustle
|
537
|
-
and the plaster, scaffolding, bricks, and dust all about him, and that
|
538
|
-
special Petersburg stench, so familiar to all who are unable to get out
|
539
|
-
of town in summer--all worked painfully upon the young man's already
|
540
|
-
overwrought nerves. The insufferable stench from the pot-houses, which
|
541
|
-
are particularly numerous in that part of the town, and the drunken men
|
542
|
-
whom he met continually, although it was a working day, completed
|
543
|
-
the revolting misery of the picture. An expression of the profoundest
|
544
|
-
disgust gleamed for a moment in the young man's refined face. He was,
|
545
|
-
by the way, exceptionally handsome, above the average in height, slim,
|
546
|
-
well-built, with beautiful dark eyes and dark brown hair. Soon he sank
|
547
|
-
into deep thought, or more accurately speaking into a complete blankness
|
548
|
-
of mind; he walked along not observing what was about him and not caring
|
549
|
-
to observe it. From time to time, he would mutter something, from the
|
550
|
-
habit of talking to himself, to which he had just confessed. At these
|
551
|
-
moments he would become conscious that his ideas were sometimes in a
|
552
|
-
tangle and that he was very weak; for two days he had scarcely tasted
|
553
|
-
food.
|
554
|
-
|
555
|
-
- :title: The Hound of the Baskervilles
|
556
|
-
:authors:
|
557
|
-
- :last_name: Doyle
|
558
|
-
:first_name: Arthur Conan
|
559
|
-
:downloads: 5021
|
560
|
-
:category: Fiction
|
561
|
-
:content: |
|
562
|
-
Mr. Sherlock Holmes, who was usually very late in the mornings, save
|
563
|
-
upon those not infrequent occasions when he was up all night, was seated
|
564
|
-
at the breakfast table. I stood upon the hearth-rug and picked up the
|
565
|
-
stick which our visitor had left behind him the night before. It was a
|
566
|
-
fine, thick piece of wood, bulbous-headed, of the sort which is known as
|
567
|
-
a "Penang lawyer." Just under the head was a broad silver band nearly
|
568
|
-
an inch across. "To James Mortimer, M.R.C.S., from his friends of the
|
569
|
-
C.C.H.," was engraved upon it, with the date "1884." It was just such a
|
570
|
-
stick as the old-fashioned family practitioner used to carry--dignified,
|
571
|
-
solid, and reassuring.
|
572
|
-
|
573
|
-
"Well, Watson, what do you make of it?"
|
574
|
-
|
575
|
-
Holmes was sitting with his back to me, and I had given him no sign of
|
576
|
-
my occupation.
|
577
|
-
|
578
|
-
"How did you know what I was doing? I believe you have eyes in the back
|
579
|
-
of your head."
|
580
|
-
|
581
|
-
"I have, at least, a well-polished, silver-plated coffee-pot in front of
|
582
|
-
me," said he. "But, tell me, Watson, what do you make of our visitor's
|
583
|
-
stick? Since we have been so unfortunate as to miss him and have no
|
584
|
-
notion of his errand, this accidental souvenir becomes of importance.
|
585
|
-
Let me hear you reconstruct the man by an examination of it."
|
586
|
-
|
587
|
-
"I think," said I, following as far as I could the methods of my
|
588
|
-
companion, "that Dr. Mortimer is a successful, elderly medical man,
|
589
|
-
well-esteemed since those who know him give him this mark of their
|
590
|
-
appreciation."
|
591
|
-
|
592
|
-
"Good!" said Holmes. "Excellent!"
|
593
|
-
|
594
|
-
"I think also that the probability is in favour of his being a country
|
595
|
-
practitioner who does a great deal of his visiting on foot."
|
596
|
-
|
597
|
-
"Why so?"
|
598
|
-
|
599
|
-
"Because this stick, though originally a very handsome one has been so
|
600
|
-
knocked about that I can hardly imagine a town practitioner carrying it.
|
601
|
-
The thick-iron ferrule is worn down, so it is evident that he has done a
|
602
|
-
great amount of walking with it."
|
603
|
-
|
604
|
-
"Perfectly sound!" said Holmes.
|
605
|
-
|
606
|
-
"And then again, there is the 'friends of the C.C.H.' I should guess
|
607
|
-
that to be the Something Hunt, the local hunt to whose members he has
|
608
|
-
possibly given some surgical assistance, and which has made him a small
|
609
|
-
presentation in return."
|
610
|
-
|
611
|
-
"Really, Watson, you excel yourself," said Holmes, pushing back his
|
612
|
-
chair and lighting a cigarette. "I am bound to say that in all the
|
613
|
-
accounts which you have been so good as to give of my own small
|
614
|
-
achievements you have habitually underrated your own abilities. It may
|
615
|
-
be that you are not yourself luminous, but you are a conductor of
|
616
|
-
light. Some people without possessing genius have a remarkable power of
|
617
|
-
stimulating it. I confess, my dear fellow, that I am very much in your
|
618
|
-
debt."
|
619
|
-
|
620
|
-
He had never said as much before, and I must admit that his words gave
|
621
|
-
me keen pleasure, for I had often been piqued by his indifference to my
|
622
|
-
admiration and to the attempts which I had made to give publicity to
|
623
|
-
his methods. I was proud, too, to think that I had so far mastered his
|
624
|
-
system as to apply it in a way which earned his approval. He now took
|
625
|
-
the stick from my hands and examined it for a few minutes with his naked
|
626
|
-
eyes. Then with an expression of interest he laid down his cigarette,
|
627
|
-
and carrying the cane to the window, he looked over it again with a
|
628
|
-
convex lens.
|
629
|
-
|
630
|
-
"Interesting, though elementary," said he as he returned to his
|
631
|
-
favourite corner of the settee. "There are certainly one or two
|
632
|
-
indications upon the stick. It gives us the basis for several
|
633
|
-
deductions."
|
634
|
-
|
635
|
-
- :title: Madame Bovary
|
636
|
-
:authors:
|
637
|
-
- :last_name: Flaubert
|
638
|
-
:first_name: Gustave
|
639
|
-
:downloads: 4090
|
640
|
-
:category: Fiction
|
641
|
-
:content: |
|
642
|
-
We were in class when the head-master came in, followed by a "new
|
643
|
-
fellow," not wearing the school uniform, and a school servant carrying a
|
644
|
-
large desk. Those who had been asleep woke up, and every one rose as if
|
645
|
-
just surprised at his work.
|
646
|
-
|
647
|
-
The head-master made a sign to us to sit down. Then, turning to the
|
648
|
-
class-master, he said to him in a low voice--
|
649
|
-
|
650
|
-
"Monsieur Roger, here is a pupil whom I recommend to your care; he'll be
|
651
|
-
in the second. If his work and conduct are satisfactory, he will go into
|
652
|
-
one of the upper classes, as becomes his age."
|
653
|
-
|
654
|
-
The "new fellow," standing in the corner behind the door so that he
|
655
|
-
could hardly be seen, was a country lad of about fifteen, and taller
|
656
|
-
than any of us. His hair was cut square on his forehead like a village
|
657
|
-
chorister's; he looked reliable, but very ill at ease. Although he was
|
658
|
-
not broad-shouldered, his short school jacket of green cloth with black
|
659
|
-
buttons must have been tight about the arm-holes, and showed at the
|
660
|
-
opening of the cuffs red wrists accustomed to being bare. His legs, in
|
661
|
-
blue stockings, looked out from beneath yellow trousers, drawn tight by
|
662
|
-
braces, He wore stout, ill-cleaned, hob-nailed boots.
|
663
|
-
|
664
|
-
We began repeating the lesson. He listened with all his ears, as
|
665
|
-
attentive as if at a sermon, not daring even to cross his legs or lean
|
666
|
-
on his elbow; and when at two o'clock the bell rang, the master was
|
667
|
-
obliged to tell him to fall into line with the rest of us.
|
668
|
-
|
669
|
-
When we came back to work, we were in the habit of throwing our caps on
|
670
|
-
the ground so as to have our hands more free; we used from the door to
|
671
|
-
toss them under the form, so that they hit against the wall and made a
|
672
|
-
lot of dust: it was "the thing."
|
673
|
-
|
674
|
-
But, whether he had not noticed the trick, or did not dare to attempt
|
675
|
-
it, the "new fellow," was still holding his cap on his knees even after
|
676
|
-
prayers were over. It was one of those head-gears of composite order, in
|
677
|
-
which we can find traces of the bearskin, shako, billycock hat, sealskin
|
678
|
-
cap, and cotton night-cap; one of those poor things, in fine, whose
|
679
|
-
dumb ugliness has depths of expression, like an imbecile's face. Oval,
|
680
|
-
stiffened with whalebone, it began with three round knobs; then came in
|
681
|
-
succession lozenges of velvet and rabbit-skin separated by a red band;
|
682
|
-
after that a sort of bag that ended in a cardboard polygon covered with
|
683
|
-
complicated braiding, from which hung, at the end of a long thin cord,
|
684
|
-
small twisted gold threads in the manner of a tassel. The cap was new;
|
685
|
-
its peak shone.
|
686
|
-
|
687
|
-
"Rise," said the master.
|
688
|
-
|
689
|
-
He stood up; his cap fell. The whole class began to laugh. He stooped to
|
690
|
-
pick it up. A neighbor knocked it down again with his elbow; he picked
|
691
|
-
it up once more.
|
692
|
-
|
693
|
-
- :title: Tractatus Logico-Philosophicus
|
694
|
-
:authors:
|
695
|
-
- :last_name: Wittgenstein
|
696
|
-
:first_name: Ludwig
|
697
|
-
:downloads: 4036
|
698
|
-
:category: Philosophy
|
699
|
-
:content: |
|
700
|
-
1 The world is everything that is the case.∗
|
701
|
-
1.1 The world is the totality of facts, not of things.
|
702
|
-
1.11 The world is determined by the facts, and by these being all the facts.
|
703
|
-
1.12 For the totality of facts determines both what is the case, and also all that is not the case.
|
704
|
-
1.13 The facts in logical space are the world.
|
705
|
-
1.2 The world divides into facts.
|
706
|
-
1.21 Any one can either be the case or not be the case, and everything else remain the same.
|
707
|
-
- :title: A General Introduction to Psychoanalysis
|
708
|
-
:authors:
|
709
|
-
- :last_name: Freud
|
710
|
-
:first_name: Sigmund
|
711
|
-
:downloads: 1355
|
712
|
-
:category: Psychology
|
713
|
-
:content: |
|
714
|
-
I do not know how familiar some of you may be, either from your reading
|
715
|
-
or from hearsay, with psychoanalysis. But, in keeping with the title of
|
716
|
-
these lectures--_A General Introduction to Psychoanalysis_--I am obliged
|
717
|
-
to proceed as though you knew nothing about this subject, and stood in
|
718
|
-
need of preliminary instruction.
|
719
|
-
|
720
|
-
To be sure, this much I may presume that you do know, namely, that
|
721
|
-
psychoanalysis is a method of treating nervous patients medically. And
|
722
|
-
just at this point I can give you an example to illustrate how the
|
723
|
-
procedure in this field is precisely the reverse of that which is the
|
724
|
-
rule in medicine. Usually when we introduce a patient to a medical
|
725
|
-
technique which is strange to him we minimize its difficulties and give
|
726
|
-
him confident promises concerning the result of the treatment. When,
|
727
|
-
however, we undertake psychoanalytic treatment with a neurotic patient
|
728
|
-
we proceed differently. We hold before him the difficulties of the
|
729
|
-
method, its length, the exertions and the sacrifices which it will cost
|
730
|
-
him; and, as to the result, we tell him that we make no definite
|
731
|
-
promises, that the result depends on his conduct, on his understanding,
|
732
|
-
on his adaptability, on his perseverance. We have, of course, excellent
|
733
|
-
motives for conduct which seems so perverse, and into which you will
|
734
|
-
perhaps gain insight at a later point in these lectures.
|
735
|
-
|
736
|
-
Do not be offended, therefore, if, for the present, I treat you as I
|
737
|
-
treat these neurotic patients. Frankly, I shall dissuade you from coming
|
738
|
-
to hear me a second time. With this intention I shall show what
|
739
|
-
imperfections are necessarily involved in the teaching of psychoanalysis
|
740
|
-
and what difficulties stand in the way of gaining a personal judgment. I
|
741
|
-
shall show you how the whole trend of your previous training and all
|
742
|
-
your accustomed mental habits must unavoidably have made you opponents
|
743
|
-
of psychoanalysis, and how much you must overcome in yourselves in
|
744
|
-
order to master this instinctive opposition. Of course I cannot predict
|
745
|
-
how much psychoanalytic understanding you will gain from my lectures,
|
746
|
-
but I can promise this, that by listening to them you will not learn how
|
747
|
-
to undertake a psychoanalytic treatment or how to carry one to
|
748
|
-
completion. Furthermore, should I find anyone among you who does not
|
749
|
-
feel satisfied with a cursory acquaintance with psychoanalysis, but who
|
750
|
-
would like to enter into a more enduring relationship with it, I shall
|
751
|
-
not only dissuade him, but I shall actually warn him against it. As
|
752
|
-
things now stand, a person would, by such a choice of profession, ruin
|
753
|
-
his every chance of success at a university, and if he goes out into the
|
754
|
-
world as a practicing physician, he will find himself in a society which
|
755
|
-
does not understand his aims, which regards him with suspicion and
|
756
|
-
hostility, and which turns loose upon him all the malicious spirits
|
757
|
-
which lurk within it.
|
758
|
-
- :title: Grimms' Fairy Tales
|
759
|
-
:authors:
|
760
|
-
- :last_name: Grimm
|
761
|
-
:first_name: Jacob
|
762
|
-
- :last_name: Grimm
|
763
|
-
:first_name: Wilhelm
|
764
|
-
:downloads: 25050
|
765
|
-
:content: |
|
766
|
-
A certain king had a beautiful garden, and in the garden stood a tree
|
767
|
-
which bore golden apples. These apples were always counted, and about
|
768
|
-
the time when they began to grow ripe it was found that every night one
|
769
|
-
of them was gone. The king became very angry at this, and ordered the
|
770
|
-
gardener to keep watch all night under the tree. The gardener set his
|
771
|
-
eldest son to watch; but about twelve o'clock he fell asleep, and in
|
772
|
-
the morning another of the apples was missing. Then the second son was
|
773
|
-
ordered to watch; and at midnight he too fell asleep, and in the morning
|
774
|
-
another apple was gone. Then the third son offered to keep watch; but
|
775
|
-
the gardener at first would not let him, for fear some harm should come
|
776
|
-
to him: however, at last he consented, and the young man laid himself
|
777
|
-
under the tree to watch. As the clock struck twelve he heard a rustling
|
778
|
-
noise in the air, and a bird came flying that was of pure gold; and as
|
779
|
-
it was snapping at one of the apples with its beak, the gardener's son
|
780
|
-
jumped up and shot an arrow at it. But the arrow did the bird no harm;
|
781
|
-
only it dropped a golden feather from its tail, and then flew away.
|
782
|
-
The golden feather was brought to the king in the morning, and all the
|
783
|
-
council was called together. Everyone agreed that it was worth more than
|
784
|
-
all the wealth of the kingdom: but the king said, 'One feather is of no
|
785
|
-
use to me, I must have the whole bird.'
|
786
|
-
|
787
|
-
- :title: An English Grammar
|
788
|
-
:authors:
|
789
|
-
- :last_name: Baskervill
|
790
|
-
:first_name: William Malone
|
791
|
-
- :last_name: Sewell
|
792
|
-
:first_name: James Witt
|
793
|
-
:downloads: 1211
|
794
|
-
:category: Linguistics
|
795
|
-
:content: |
|
796
|
-
Of making many English grammars there is no end; nor should there be
|
797
|
-
till theoretical scholarship and actual practice are more happily
|
798
|
-
wedded. In this field much valuable work has already been
|
799
|
-
accomplished; but it has been done largely by workers accustomed to
|
800
|
-
take the scholar's point of view, and their writings are addressed
|
801
|
-
rather to trained minds than to immature learners. To find an advanced
|
802
|
-
grammar unencumbered with hard words, abstruse thoughts, and difficult
|
803
|
-
principles, is not altogether an easy matter. These things enhance the
|
804
|
-
difficulty which an ordinary youth experiences in grasping and
|
805
|
-
assimilating the facts of grammar, and create a distaste for the
|
806
|
-
study. It is therefore the leading object of this book to be both as
|
807
|
-
scholarly and as practical as possible. In it there is an attempt to
|
808
|
-
present grammatical facts as simply, and to lead the student to
|
809
|
-
assimilate them as thoroughly, as possible, and at the same time to do
|
810
|
-
away with confusing difficulties as far as may be.
|
811
|
-
DATA
|
812
|
-
|
813
|
-
[Book, Author, Authorship, Category].each { |model| model.delete_all }
|
814
|
-
|
815
|
-
books.to_ruby.each do |b|
|
816
|
-
book = Book.create \
|
817
|
-
title: b[:title],
|
818
|
-
downloads: b[:downloads],
|
819
|
-
content: b[:content]
|
820
|
-
|
821
|
-
b[:authors].each do |a|
|
822
|
-
author = Author.where(first_name: a[:first_name], last_name: a[:last_name]).first_or_create
|
823
|
-
book.authors << author
|
824
|
-
end
|
134
|
+
puts
|
135
|
+
say_status "Model", "Adding the `abstract` column to Article...\n", :yellow
|
136
|
+
puts '-'*80, ''
|
137
|
+
|
138
|
+
generate :migration, "AddColumnsToArticle abstract:text url:string shares:integer"
|
139
|
+
rake "db:migrate"
|
825
140
|
|
826
|
-
|
827
|
-
|
141
|
+
git add: "db/"
|
142
|
+
git commit: "-m 'Added additional columns to Article'"
|
143
|
+
|
144
|
+
# ----- Move the model integration into a concern -------------------------------------------------
|
828
145
|
|
829
|
-
|
146
|
+
puts
|
147
|
+
say_status "Model", "Refactoring the model integration...\n", :yellow
|
148
|
+
puts '-'*80, ''; sleep 0.25
|
149
|
+
|
150
|
+
remove_file 'app/models/article.rb'
|
151
|
+
create_file 'app/models/article.rb', <<-CODE
|
152
|
+
class Article < ActiveRecord::Base
|
153
|
+
include Searchable
|
830
154
|
end
|
831
155
|
CODE
|
832
156
|
|
833
|
-
|
834
|
-
|
157
|
+
# copy_file File.expand_path('../searchable.rb', __FILE__), 'app/models/concerns/searchable.rb'
|
158
|
+
get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/searchable.rb',
|
159
|
+
'app/models/concerns/searchable.rb'
|
835
160
|
|
836
|
-
|
837
|
-
|
838
|
-
# * Update views (show authors, category name, bootstrap)
|
839
|
-
# <table class="table table-hover">
|
840
|
-
# class: 'btn btn-default btn-xs'
|
841
|
-
# class: 'btn btn-primary btn-xs', style: 'color: #fff'
|
842
|
-
# <td><%= book.authors.map(&:full_name).to_sentence %></td>
|
843
|
-
# <td><%= book.category.try(:title) || 'n/a' %></td>
|
844
|
-
# Update controller (fight n+1)
|
845
|
-
# @books = Book.includes(:authors, :category)
|
846
|
-
#
|
161
|
+
insert_into_file "app/models/article.rb", after: "ActiveRecord::Base" do
|
162
|
+
<<-CODE
|
847
163
|
|
848
|
-
|
164
|
+
has_and_belongs_to_many :categories, after_add: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ],
|
165
|
+
after_remove: [ lambda { |a,c| Indexer.perform_async(:update, a.class.to_s, a.id) } ]
|
166
|
+
has_many :authorships
|
167
|
+
has_many :authors, through: :authorships
|
168
|
+
has_many :comments
|
849
169
|
|
850
|
-
|
851
|
-
|
170
|
+
CODE
|
171
|
+
end
|
172
|
+
|
173
|
+
git add: "app/models/"
|
174
|
+
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/'"
|
175
|
+
|
176
|
+
# ----- Add Sidekiq indexer -----------------------------------------------------------------------
|
177
|
+
|
178
|
+
puts
|
179
|
+
say_status "Application", "Adding Sidekiq worker for updating the index...\n", :yellow
|
180
|
+
puts '-'*80, ''; sleep 0.25
|
181
|
+
|
182
|
+
gem "sidekiq"
|
183
|
+
|
184
|
+
run "bundle install"
|
185
|
+
|
186
|
+
# copy_file File.expand_path('../indexer.rb', __FILE__), 'app/workers/indexer.rb'
|
187
|
+
get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/indexer.rb',
|
188
|
+
'app/workers/indexer.rb'
|
189
|
+
|
190
|
+
git add: "Gemfile* app/workers/"
|
191
|
+
git commit: "-m 'Added a Sidekiq indexer\n\nRun:\n\n $ bundle exec sidekiq --queue elasticsearch --verbose\n\nSee http://sidekiq.org'"
|
192
|
+
|
193
|
+
# ----- Add SearchController -----------------------------------------------------------------------
|
194
|
+
|
195
|
+
puts
|
196
|
+
say_status "Controllers", "Adding SearchController...\n", :yellow
|
197
|
+
puts '-'*80, ''; sleep 0.25
|
198
|
+
|
199
|
+
create_file 'app/controllers/search_controller.rb' do
|
200
|
+
<<-CODE.gsub(/^ /, '')
|
201
|
+
class SearchController < ApplicationController
|
202
|
+
respond_to :json, :html
|
203
|
+
|
204
|
+
def index
|
205
|
+
options = {
|
206
|
+
category: params[:c],
|
207
|
+
author: params[:a],
|
208
|
+
published_week: params[:w],
|
209
|
+
published_day: params[:d],
|
210
|
+
sort: params[:s],
|
211
|
+
comments: params[:comments]
|
212
|
+
}
|
213
|
+
@articles = Article.search(params[:q], options).page(params[:page]).results
|
214
|
+
|
215
|
+
respond_with @articles
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
852
219
|
|
853
|
-
include Searchable
|
854
220
|
CODE
|
855
221
|
end
|
856
222
|
|
857
|
-
|
858
|
-
|
223
|
+
route "get '/search', to: 'search#index', as: 'search'"
|
224
|
+
gsub_file 'config/routes.rb', %r{root to: 'articles#index'$}, "root to: 'search#index'"
|
859
225
|
|
860
|
-
#
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
#
|
226
|
+
# copy_file File.expand_path('../index.html.erb', __FILE__), 'app/views/search/index.html.erb'
|
227
|
+
get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/index.html.erb',
|
228
|
+
'app/views/search/index.html.erb'
|
229
|
+
|
230
|
+
# copy_file File.expand_path('../search.css', __FILE__), 'app/assets/stylesheets/search.css'
|
231
|
+
get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/search.css',
|
232
|
+
'app/assets/stylesheets/search.css'
|
233
|
+
|
234
|
+
git add: "app/controllers/ config/routes.rb"
|
235
|
+
git add: "app/views/search/ app/assets/stylesheets/search.css"
|
236
|
+
git commit: "-m 'Added SearchController#index'"
|
237
|
+
|
238
|
+
# ----- Add initializer ---------------------------------------------------------------------------
|
239
|
+
|
240
|
+
puts
|
241
|
+
say_status "Application", "Adding Elasticsearch configuration in an initializer...\n", :yellow
|
242
|
+
puts '-'*80, ''; sleep 0.5
|
243
|
+
|
244
|
+
create_file 'config/initializers/elasticsearch.rb', <<-CODE
|
245
|
+
# Connect to specific Elasticsearch cluster
|
246
|
+
ELASTICSEARCH_URL = ENV['ELASTICSEARCH_URL'] || 'http://localhost:9200'
|
247
|
+
|
248
|
+
Elasticsearch::Model.client = Elasticsearch::Client.new host: ELASTICSEARCH_URL
|
249
|
+
|
250
|
+
# Print Curl-formatted traces in development into a file
|
865
251
|
#
|
252
|
+
if Rails.env.development?
|
253
|
+
tracer = ActiveSupport::Logger.new('log/elasticsearch.log')
|
254
|
+
tracer.level = Logger::DEBUG
|
255
|
+
end
|
866
256
|
|
867
|
-
|
257
|
+
Elasticsearch::Model.client.transport.tracer = tracer
|
258
|
+
CODE
|
259
|
+
|
260
|
+
git add: "config/initializers"
|
261
|
+
git commit: "-m 'Added Rails initializer with Elasticsearch configuration'"
|
262
|
+
|
263
|
+
# ----- Add Rake tasks ----------------------------------------------------------------------------
|
868
264
|
|
869
265
|
puts
|
870
|
-
say_status "
|
871
|
-
puts '-'*80, ''; sleep 0.
|
266
|
+
say_status "Application", "Adding Elasticsearch Rake tasks...\n", :yellow
|
267
|
+
puts '-'*80, ''; sleep 0.5
|
268
|
+
|
269
|
+
create_file 'lib/tasks/elasticsearch.rake', <<-CODE
|
270
|
+
require 'elasticsearch/rails/tasks/import'
|
271
|
+
CODE
|
872
272
|
|
873
|
-
|
273
|
+
git add: "lib/tasks"
|
274
|
+
git commit: "-m 'Added Rake tasks for Elasticsearch'"
|
874
275
|
|
875
|
-
# -----
|
276
|
+
# ----- Insert and index data ---------------------------------------------------------------------
|
876
277
|
|
877
278
|
puts
|
878
|
-
say_status "
|
279
|
+
say_status "Database", "Re-creating the database with data and importing into Elasticsearch...", :yellow
|
879
280
|
puts '-'*80, ''; sleep 0.25
|
880
281
|
|
881
|
-
#
|
882
|
-
|
282
|
+
# copy_file File.expand_path('../articles.yml.gz', __FILE__), 'db/articles.yml.gz'
|
283
|
+
get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/articles.yml.gz',
|
284
|
+
'db/articles.yml.gz'
|
285
|
+
|
286
|
+
remove_file 'db/seeds.rb'
|
287
|
+
# copy_file File.expand_path('../seeds.rb', __FILE__), 'db/seeds.rb'
|
288
|
+
get 'https://raw.github.com/elasticsearch/elasticsearch-rails/templates/elasticsearch-rails/lib/rails/templates/seeds.rb',
|
289
|
+
'db/seeds.rb'
|
290
|
+
|
291
|
+
rake "db:reset"
|
292
|
+
rake "environment elasticsearch:import:model CLASS='Article' BATCH=100 FORCE=y"
|
293
|
+
|
294
|
+
git add: "db/seeds.rb db/articles.yml.gz"
|
295
|
+
git commit: "-m 'Added a seed script and source data'"
|
883
296
|
|
884
297
|
# ----- Print Git log -----------------------------------------------------------------------------
|
885
298
|
|
@@ -887,24 +300,26 @@ puts
|
|
887
300
|
say_status "Git", "Details about the application:", :yellow
|
888
301
|
puts '-'*80, ''
|
889
302
|
|
890
|
-
git :
|
891
|
-
git :
|
303
|
+
git tag: "expert"
|
304
|
+
git log: "--reverse --oneline HEAD...pretty"
|
892
305
|
|
893
306
|
# ----- Start the application ---------------------------------------------------------------------
|
894
307
|
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
308
|
+
unless ENV['RAILS_NO_SERVER_START']
|
309
|
+
require 'net/http'
|
310
|
+
if (begin; Net::HTTP.get(URI('http://localhost:3000')); rescue Errno::ECONNREFUSED; false; rescue Exception; true; end)
|
311
|
+
puts "\n"
|
312
|
+
say_status "ERROR", "Some other application is running on port 3000!\n", :red
|
313
|
+
puts '-'*80
|
900
314
|
|
901
|
-
|
902
|
-
else
|
903
|
-
|
904
|
-
end
|
315
|
+
port = ask("Please provide free port:", :bold)
|
316
|
+
else
|
317
|
+
port = '3000'
|
318
|
+
end
|
905
319
|
|
906
|
-
puts "", "="*80
|
907
|
-
say_status "DONE", "\e[1mStarting the application. Open http://localhost:#{port}\e[0m", :yellow
|
908
|
-
puts "="*80, ""
|
320
|
+
puts "", "="*80
|
321
|
+
say_status "DONE", "\e[1mStarting the application. Open http://localhost:#{port}\e[0m", :yellow
|
322
|
+
puts "="*80, ""
|
909
323
|
|
910
|
-
run "rails server --port=#{port}"
|
324
|
+
run "rails server --port=#{port}"
|
325
|
+
end
|