diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb
index ec84559..2c38c38 100644
--- a/app/controllers/messages_controller.rb
+++ b/app/controllers/messages_controller.rb
@@ -3,12 +3,26 @@ class MessagesController < ApplicationController
# GET /messages or /messages.json
def index
- @messages = Message.all
+ query = params[:q]
+ if query
+ # %> and <-> are defined by pg_trgm.
+ # https://www.postgresql.org/docs/17/pgtrgm.html
+ @messages = Message.find_by_sql([
+ 'SELECT * FROM messages WHERE body %> ? ORDER BY body <-> ? LIMIT 20',
+ query, query,
+ ])
+ else
+ @messages = Message.all
+ end
end
# GET /messages/1 or /messages/1.json
def show
- @message = Message.from_s3(params[:list_name], params[:list_seq])
+ if params[:id]
+ @message = Message.find(params[:id])
+ else
+ @message = Message.from_s3(params[:list_name], params[:list_seq])
+ end
end
# GET /messages/new
diff --git a/app/models/message.rb b/app/models/message.rb
index 87d0bf4..56c9368 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -9,7 +9,7 @@ def self.from_s3(list_name, list_seq)
end
def self.from_string(str)
- hs, body = str.split(/\n\n/, 2)
+ hs, body = str.encode('utf-8', invalid: :replace).split(/\n\n/, 2)
headers = hs.split(/\n/).map { |line|
line.split(/:\s+/, 2)
}.to_h
diff --git a/app/views/messages/index.html.erb b/app/views/messages/index.html.erb
index 809266a..0d32916 100644
--- a/app/views/messages/index.html.erb
+++ b/app/views/messages/index.html.erb
@@ -2,13 +2,13 @@
Messages
-
+
<% @messages.each do |message| %>
- <%= render message %>
-
- <%= link_to "Show this message", message %>
-
+ -
+ <%= link_to message.subject, message %>
+ <%= message.body %>
+
<% end %>
-
+
<%= link_to "New message", new_message_path %>
diff --git a/db/migrate/20240810063115_add_pg_trgm.rb b/db/migrate/20240810063115_add_pg_trgm.rb
new file mode 100644
index 0000000..9629962
--- /dev/null
+++ b/db/migrate/20240810063115_add_pg_trgm.rb
@@ -0,0 +1,5 @@
+class AddPgTrgm < ActiveRecord::Migration[7.1]
+ def change
+ enable_extension 'pg_trgm'
+ end
+end
diff --git a/db/migrate/20240810064037_add_trigram_index.rb b/db/migrate/20240810064037_add_trigram_index.rb
new file mode 100644
index 0000000..291a602
--- /dev/null
+++ b/db/migrate/20240810064037_add_trigram_index.rb
@@ -0,0 +1,15 @@
+class AddTrigramIndex < ActiveRecord::Migration[7.1]
+ def up
+ # According to https://www.postgresql.org/docs/9.1/textsearch-indexes.html
+ #
+ # > As a rule of thumb, GIN indexes are best for static data because
+ # > lookups are faster. For dynamic data, GiST indexes are faster to update.
+ #
+ # So we use GIN here instead of GiST.
+ add_index(:messages, :body, using: :gin, opclass: { body: :gin_trgm_ops })
+ end
+
+ def down
+ remove_index(:messages, :body)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3330b7b..fcde555 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,13 +10,14 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2024_08_10_040807) do
+ActiveRecord::Schema[7.1].define(version: 2024_08_10_064037) do
create_table "messages", force: :cascade do |t|
t.string "subject"
t.string "from"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["body"], name: "index_messages_on_body"
end
end