我建立了一个能够搜索Rebuild.fm的Shownote的服务
我其实是Rebuild.fm的忠实听众。
Rebuild每一期都有丰富的新技术话题,然后几个月后这些话题开始流行,很多时候都会想起那个时候,在Rebuild听到的那个话题,然后重新回顾一下当时的那一期节目。
最近,关于Redux的话题真的很多。第114集的时候我稍微听过一点(Miyagawa先生对此也有一些”这个会流行吗?”的反应),但直到我在各个地方看到它的名字,读了Web+DBPress的文章之后,才想起来再次听了一遍第114集,这是最近的事情。
所以,我突然想要轻松地搜索与Rebuild中热门话题相关的讨论场景。
由于可以从RSS获取每个剧集和Shownote的信息,所以如果将其存入数据库,就可以进行搜索了。
为了学习,我正在使用Elasticsearch和React,但我还不能很好地使用它们。
在开发过程中,我们在本地构建了一个Rails应用程序,并在Vagrant上部署了Elasticsearch。
弹性搜索
我在Vagrant上通过itamae编写了Elasticsearch安装配置的配方。
这个配方包括了Elasticsearch本身和一些插件。
配方和VagrantFile等都与Rails应用程序分别存放在以下存储库中。
中文的选项:食谱/ Elasticsearch/ 默认.rb
package "java-1.8.0-openjdk.x86_64" do
action :install
end
# https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-repositories.html
template "/etc/yum.repos.d/elasticsearch.repo" do
user "root"
group "root"
source "./templates/etc/yum.repos.d/elasticsearch.repo.erb"
not_if "test -e /etc/yum.repos.d/elasticsearch.repo"
end
package "elasticsearch" do
action :install
end
# kuromoji
# https://www.elastic.co/guide/en/elasticsearch/plugins/2.0/analysis-kuromoji.html
execute "install analysis-kuromoji" do
user "root"
cwd "/usr/share/elasticsearch"
command "bin/plugin install analysis-kuromoji"
not_if "test -e /usr/share/elasticsearch/plugins/analysis-kuromoji"
end
template "/etc/elasticsearch/elasticsearch.yml" do
user "root"
group "root"
source "./templates/etc/elasticsearch.yml.erb"
end
# user,groupをelasticsearchにしないとサービス起動でエラーになる
execute "change owner to elasticsearch" do
user "root"
cwd "/etc/"
command "chown -R elasticsearch elasticsearch;chgrp -R elasticsearch elasticsearch"
end
Rails + Elasticsearch:Rails框架和Elasticsearch的结合
我正在参考以下文章将elasticsearch-rails gem集成到Rails中。
使用Elasticsearch创建一个使用Rails的示例应用程序
大部分是使用上述示例代码的原样。
由于Elasticsearch是在Vagrant上构建的,所以在模型内设置了虚拟机的主机名。
开发环境配置文件:config/environments/development.rb
Rails.application.configure do
# elasticsearch server host
config.elasticsearch_server_host = "192.168.33.10:9200"
end
app/models/shownote.rb 的内容
# == Schema Information
#
# Table name: shownotes
#
# id :integer not null, primary key
# episode_id :integer
# title :string
# link :string
# created_at :datetime not null
# updated_at :datetime not null
#
class Shownote < ActiveRecord::Base
belongs_to :episode, foreign_key: :episode_id, class_name: :Episode
include Elasticsearch::Model
self.__elasticsearch__.client = Elasticsearch::Client.new host: RebuildFulltextSearch::Application.config.elasticsearch_server_host, log: true
INDEX_FIELDS = %w(title link).freeze
index_name "rebuild_shownote_#{Rails.env}"
settings do
mappings dynamic: "false" do
indexes :title, analyzer: "kuromoji", type: "string"
indexes :link, analyzer: "kuromoji", type: "string"
end
end
def as_indexed_json(options = {})
self.as_json.select{|k, _| INDEX_FIELDS.include?(k) }
end
def self.create_index!
client = __elasticsearch__.client
client.indices.delete index: self.index_name rescue nil
client.indices.create(
index: self.index_name,
body: {
settings: self.settings.to_hash,
mappings: self.mappings.to_hash
}
)
end
end
应用程序/控制器/显示笔记控制器
# GET /shownotes
# GET /shownotes.json
def index
@shownotes = if params[:search]
Shownote.search(query:{match: {_all: params[:search] }}).records
else
Shownote.includes(:episode).all
end
if request.format.to_s == "application/json"
@shownotes = @shownotes.map{|r|
{
id: r.id,
episode_id: r.episode_id,
title: r.title,
link: r.link,
episode_no: r.episode.episode_no,
episode_title: r.episode.title ,
episode_subtitle: r.episode.subtitle,
episode_link: r.episode.link,
episode_pubdate: r.episode.pubdate
}
}
end
end
回应
前端是用React+Redux实现的。
这个应用程序的动作很少,所以用Redux没有太多意义。
代码是参考Web+DBPress Vol.92特辑中的内容。
顺便说一下,第92期中除了有关Redux的文章外,还收录了使用Rails+React构建的TODO应用程序示例,非常有参考价值。
使用superagent进行向服务器端发送请求,并接收以JSON格式返回的响应。
前端/src/app.jsx
onKyewordChange(e){
this.setState({keyword: e.target.value});
var url = "/shownotes.json?search=" + this.state.keyword
request.get(url)
.accept("application/json")
.end((err, res) => {
if(err || !res.ok){
console.error(this.props.url, status, err.toString())
}
else{
this.setState({data: res.body})
}
})
}
使用webpack来编译jsx文件时,我曾为如何将其集成到Rails的配置目录中而烦恼,但参考了下面的文章后,我创建了一个frontend目录,并将其中的package.json和其他一些文件放入其中。
当我要编写jsx时,我会切换到frontend目录下执行”webpack –watch”命令。
使用Webpack可以方便地将JavaScript从Rails中分离并达到良好的效果。
$ tree -L 3
.
├── app
│ ├── assets
│ │ ├── images
│ │ ├── javascripts
│ │ └── stylesheets
│ ├── controllers
│ │ ├── application_controller.rb
│ │ ├── concerns
│ │ ├── episodes_controller.rb
│ │ ├── main_controller.rb
│ │ └── shownotes_controller.rb
│ ├── helpers
│ ├── mailers
│ ├── models
│ │ ├── concerns
│ │ ├── episode.rb
│ │ └── shownote.rb
│ └── views
│ ├── episodes
│ ├── layouts
│ ├── main
│ └── shownotes
├── bin
├── config
├── config.ru
├── db
├── frontend
│ ├── package.json
│ ├── src
│ │ ├── app.jsx
│ │ └── index.html
│ └── webpack.config.js
├── lib
│ ├── assets
│ └── tasks
│ ├── elasticsearch.rake
│ └── rebuild.rake
画面设计
我們使用了Bulma的組件進行構建。
不知怎地,我觉得花费最多时间的部分是这个设计。最开始的调色方式还是保持了bulma的默认配色,但我反复无数次地调整了这个不好那个不好的。
组件的布局没有改变,只是在调整背景和颜色等细节,但是始终无法达到我喜欢的感觉。
以下是修正过程中的内容。很难辨识吧。

我认为现在的东西已经变得很不错了,你觉得怎么样呢?
因为主题颜色和背景图片都完美地配合在一起,所以我们决定采用。
真希望一次就能做出这样的东西。
