古いバージョンの mecab を homebrew でいれたのでメモ とちょっとしたエラー対処
今現在の mecab 最新バージョンは 0.996 なので、単純に $ homebrew install mecab
とすると 0.996 が入ってしまいます。
今回は、mecab-ruby とのバージョンの兼ね合いで mecab 0.99 を使う必要が出たのでそのインストール手順をメモします。
環境
- Homebrew 0.9.5
前提
少し前だと、
$ brew versions mecab
で過去のバージョンを調べ、Formula の過去バージョン にチェックアウトしてから インストールすればよかったらしいです。
しかーし!
homebrew のアップデートに伴いその機能がなくなってしまったみたいです。
現在はそれに変わる機能で、Homebrew-versions というものが使われだしたらしいのですが、使い方がわからず(というかそもそも mecab 自体組み込まれてない???) 断念。
なので、今回は参考URLあげたリンク先のページから拝借して、各バージョンとそれに伴う git ブランチを以下に書きます。
0.996 git checkout ee21df2 /usr/local/Library/Formula/mecab.rb 0.995 git checkout 1c6ad82 /usr/local/Library/Formula/mecab.rb 0.994 git checkout 4844910 /usr/local/Library/Formula/mecab.rb 0.993 git checkout 642c664 /usr/local/Library/Formula/mecab.rb 0.992 git checkout bb95f13 /usr/local/Library/Formula/mecab.rb 0.99 git checkout 01788c0 /usr/local/Library/Formula/mecab.rb 0.98 git checkout 0476235 /usr/local/Library/Formula/mecab.rb
これを参考にいれたいバージョンをいれてください。
実際の手順
今回は 0.99 を使いたいので、
$ git checkout 01788c0 /usr/local/Library/Formula/mecab.rb
$ brew install mecab mecab-ipadic
こうする。
※ mecab-ipadic は辞書です。
これで、たいていの方ははいると思います。
$ mecab すもももももももものうち すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ EOS
すげええええええ。
補足
で、
実は mecab のインストール時に以下のようなメッセージが出てけっこうはまりました。
$ brew install mecab ==> Downloading http://mecab.googlecode.com/files/mecab-0.99.tar.gz ######################################################################## 100.0% ==> ./configure --prefix=/usr/local/Cellar/mecab/0.99 ==> make install MeCab::Iconv::open(char const*, char const*) in iconv_utils.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make[1]: *** [libmecab.la] Error 1 make: *** [install-recursive] Error 1
詳しいことはよくわかりませんw
$ brew doctor
してみると、
Warning: Some keg-only formula are linked into the Cellar. Linking a keg-only formula, such as gettext, into the cellar with `brew link <formula>` will cause other formulae to detect them during the `./configure` step. This may cause problems when compiling those other formulae. Binaries provided by keg-only formulae may override system binaries with other strange results. You may wish to `brew unlink` these brews: libiconv libxml2 libxslt
と出て、思い出しました。
最近 nokogiri を入れた際に警告を出すようになって、その時に
$ brew link libiconv libxml2 libxslt
としたのがどうやら原因みたいです。(曖昧)
なので、
$ brew unlink libiconv libxml2 libxslt
としたあとに、$ brew install mecab
すればうまくはいります。
参考URL
Solr をとりあえず Rails で動かしてみた
Ruby アプリケーションに全文検索機能をさくっと追加できるらしい sunspot を使ってみたのでそのメモ。
Solr を初めて知って、まずは Rails で動けばいいやって人はこの手順通りにやってみればさくっといけるかもしれない。
詳しい動作をもっと知りたいって方はドキュメントやら下記参考URLを覗いてみてください。
環境
手順
事前準備
$ be rais new sun
$ cd sun
- Gemfile
gem 'sunspot_rails' gem 'sunspot_solr'
$ bundle install --path vendor/bundle
sunspot をいじる
- sunspot を使うために設定ファイルを作る
$ be rails g sunspot_rails:install` create config/sunspot.yml
- 起動する
$ be rake sunspot:solr:start
ちなみ停止は
$ be rake sunspot:solr:stop
今回は以下の様な感じで Scaffold する。
$ be rails g scaffold Article title content:text $ be rake db:migrate
- 実際に検索する対象を
searchable
に渡す。app/models/article.rb
を編集。text
で全文検索対象の属性を指定:stored
オプションで Hit 時にその情報を保持できる (ハイライト機能で使える)
class Article < ActiveRecord::Base searchable do text :title text :content, :stored => true end end
$ be rails s
でサーバを立ち上げ、http://localhost:3000/articles
にアクセス後、適当にデータを挿入- 自分は yahoo news から適当に3つほど挿れました
ひとまず検索が機能してるか調べる
$ be rails console
irb(main):001:0> search = Article.search do irb(main):002:1* fulltext 'ドルトムント' irb(main):003:1> end
下のような値が返ってくればとりあえず動いてる。
D, [2014-10-10T01:52:55.472090 #8950] DEBUG -- : SOLR Request (12.3ms) [ path=select parameters={fq: ["type:Article"], q: "ドルトムント", fl: "* score", qf: "title_text content_texts", defType: "edismax", start: 0, rows: 30} ] => <Sunspot::Search:{:fq=>["type:Article"], :q=>"ドルトムント", :fl=>"* score", :qf=>"title_text content_texts", :defType=>"edismax", :start=>0, :rows=>30}>
コンソールからではなくブラウザからも操作してみる
- コントローラを作る
$ be rails g controller article_search index search
検索窓を作る
app/views/article_search/index.html.erb
を編集する。
<%= form_tag '/article_search/search', method: "get" do %> <%= text_field_tag :q %> <%= submit_tag '検索' %> <% end %>
- 検索結果を表示するページを作る
app/views/article_search/search.html.erb
を編集する。each_hit_with_result
メソッドを使う- ちなみにここでハイライト機能を使っている
<p> 検索ワード: <%= params[:q] %> </p> <p> <%= @search.total %> 件ヒット </p> <ul> <% @search.each_hit_with_result do |hit, result| %> <li><div>Article #{<%= hit.primary_key %>}</div> <div><%= result.title %></div> <% hit.highlights(:content).each do |highlight| %> <%= highlight.format { |word| "*#{word}*" } %> <% end %> </li> <% end %> </ul>
- アクションをまだ作っていなかったのでコントローラに以下を追記する
app/controllers/article_search_controller.rb
def search @search = Article.search do fulltext params[:q] do highlight :content end end end
http://localhost:3000/article_search/index
にアクセスして検索ワードをつっこんでみる。
どや!
ハイライトもされてていい感じですね。 簡単ではありましたが、以上です。
参考URL
homebrew update したら Error: Failed to update tap: homebrew/dupes って出たので解消した
おもむろに homebrew をアップデートしようとしたら、唐突にエラーが出たのでその解消法を。
$ brew update
エラーメッセージは以下。
error: insufficient permission for adding an object to repository database .git/objects fatal: failed to write object fatal: unpack-objects failed Error: Failed to update tap: homebrew/dupes
なにやらパーミッションの問題で、 homebrew/dupes (?) がアップデートできないらしい。
とりあえず、 homebrew/dupes のありかを探して
$ sudo find / -name homebrew-dupes
移動します。
$ cd /usr/local/Library/Taps/homebrew/homebrew-dupes
強制的に リモートリポジトリから引っ張ってきます。
$ git co .
$ sudo git pull --force
で、homebrew をアップデート。
$ brew update
どや!
Already up-to-date.
ふう。
簡単ではありましたが、以上です。
参考URL
エラーの監視に便利な gem , exception_notification を使ってみた
なんかしらのエラーが発生すると、メールを自動的に送付してくれる gem 、exception_notification を実際にかる〜く使ってみたので、そのメモ。
例によって、bundler 経由で gem をがしがしいれていきます。
環境
手順
事前準備
適当に rails アプリを作る。
be rails new AppName --skip-bundle
Gemfile に 以下の二つを追加。
gem 'mailcatcher' gem 'exception_notification'
- gem をインストール。
bundle install --path vendor/bundle
これで必要なものが揃いました。
exception_notification を使ってみる
まずは設定ファイルをいじっていく。
rails デフォルト設定の修正
development 環境では、エラーが発生してもデフォルトでメールを送らないような設定になっているので、以下のように config/environments/development.rb
を true
に修正。
config.action_mailer.raise_delivery_errors = ture
SMTP サーバの設定
config/application.rb
のを次のように書き換える。
※ 余計なコメントは削除しました
require File.expand_path('../boot', __FILE__) require "active_model/railtie" require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" require "action_view/railtie" require "sprockets/railtie" Bundler.require(*Rails.groups) module Notifi class Application < Rails::Application config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 } end end
これらは、 本家の書き方に習っている。
sj26/mailcatcher
exception_notification の設定
エラー時に送信されるメール情報についての設定を config/environments/development.rb
に追記する。
config.middleware.use ExceptionNotification::Rack, :email => { email_prefix: "[Exception] ", sender_address: %{"Exception Notifier" <no-reply@example.com>}, exception_recipients: ["notification@example.com"] }
コントローラを作成する
わざとエラーを発生させるためのページを作ります。
$ be rails g controller home index
そして、HomeController#index に例外を発生させるため以下を追記。
class HomeController < ApplicationController def index raise 'aaa' end end
サーバを起動し、確認する
$ be rails s
で rails サーバを立てつつ、 Command + t
でタブを増やすなりして、$ be mailcatcher
で SMPT サーバを起動する。
まず、rails サーバにアクセスして例外を発生させる。
デフォルトでは以下。
http://localhost:3000/home/index
その次に、SMPT サーバにアクセスしてメールがと届いているか確認する。
デフォルトでは以下。
http://127.0.0.1:1080
こんな感じで、さっきまで空だったのが、なんか来てます。
ここまで来たら成功。
参考URL
CentOS 6.5 に solr をいれていじってみた
solr をローカル開発環境で使ってみたのでそのメモ。
ローカル開発環境の構築はドットインストールさんを参考に書いた ローカル開発環境 ドットインストールまとめ - gotagota日記 を参照にしてみてください。
環境
- CentOS 6.5
手順
java をインストール
$ sudo yum install -y java-1.7.0-openjdk
solr をダウンロード
$ sudo wget http://ftp.jaist.ac.jp/pub/apache/lucene/solr/4.8.1/solr-4.8.java-1.tgz
解凍
$ tar -xzf solr-4.8.1.tgz
起動
$ cd solr-4.8.1/example
$ java -jar start.jar
管理画面を覗いてみる
ブラウザで、http://<hostname>:8080/solr/
を叩くサンプルデータをインデックス
$ java -jar exampledocs/post.jar exampledocs/*.xml
検索してみる
$ curl "http://localhost:8983/solr/collection1/select?q=hello&wt=xml&indent=true"
- パラメータの意味は、
- q=検索文字列
- wt=出力フォーマット
- indent=出力結果にインデントをつけるか否か
- パラメータの意味は、
参考URL
- Apache Solr + Tomcat を CentOS にインストール - ダメ出し Blog
- Apache Solr で全文検索(1) – とりあえず使ってみる
- ビッグデータ処理の常識をJavaで身につける(1)
- Apache Solrを利用して本格的な検索エンジンを導入する|A Day In The Boy
データ構成やらの設定など、より発展的な内容はこのサイトが詳しい。
rails new のデフォルトオプションを設定した
どうも潔癖症日本代表です。
嘘です、実際そこまで潔癖症ではありません。
ですが、 Bunlder で Gem を管理する際には Ruby 環境下に余計な gem を入れたくないという思いは強いです。
この度、 Rails を復習しようかと思い、久しぶりに Ruby on Rails チュートリアル をやり直そうとした際に何も考えず bundle update
、bundle install
してしまい、gem をどこどこ Ruby 環境下にインストールしてしまいました。。。
自分のポンコツ具合からするとこれからいくらでも同じようなことをやらかしそうなので、なにかいい方法がないかと探すと、まさにな方法があったので紹介します。
といってもすごく簡単で、rails new のデフォルトオプションを設定するだけ。
Rails 3.2 からできるようになっていたみたいです。知らなかった。
手順としては
$ echo "--skip-bundle -T" >> ~/.railsrc
とするだけ。
これで、 rails new
した時にデフォルトで、「 bundle install
しない。テストユニットをインストールしない 。」に設定できました。
-T
オプションは任意ですが、 現在は Rspec の方が主流かと思いますので、この際デフォルトにしちまってもいいかと思います。
ちなみに、このデフォルト設定を無視したいときは、
rails new appname --no-rc
としてください。
以前にも書いた記事 rbenv と bundler で rails 環境構築メモ - gotagota日記 と合わせて gem をすっきりと管理したいと思います。
参考URL:
ドットインストール Rails まとめ
ドットインストールさんで Rails について振り返ったので、勉強メモ。
Rails は前にちょこっとやった時は、ただコードを書き写していただけに等しかったのですが、今回、RubyやらActiveRecord やらを勉強しなおした後にやると理解、納得しながらできたので得るものは大きかったです。
これは、自分で何もみずに同じようなアプリを作るという試みの際の解答のようなものになればと思い残しておきます。
[1] 事前準備
実行環境
自分の実行環境は以下のとおり。
補足
gem に関しては全て Bundler を使って入れます。
詳しくは rbenv と bundler で rails 環境構築メモ に書きましたので宜しければ。
あと、毎回 bundle exec
と打つのがめんどかったので be
というエイリアスを設定しています。適宜読み替えてください。
手順
まずは事前準備をしていきます。
1. rails new してフォルダに移動
$ be rails new taskapp
$ cd taskapp
2. Gemfile
を編集
gem 'therubyracer', platforms: :ruby
のコメントを外す
3. gem をインストールする
$ bundle install
[2] Project に関するあれやこれ
タスク管理アプリということで、プロジェクト毎にタスクがあると思うので、まずは大本となるプロジェクト部分に関するあれやこれを作っていきます。
以下、実際の手順。
手順
1. Model と Controller を用意する
$ be rails g model Project title:string
で Model を作成- Model の名前は単数形で最初を大文字にする必要がある
- データ型のデフォルトは文字列なので
:string
は省略可能
$ be rake db:migrate
でデータベースを作る。$ be rails g controller Projects
でController を作成- Controller の名前は複数形で最初を大文字にする必要がある
2. ルーティングをいじる
config/routes.rb
を編集
Rails.application.routes.draw do resources :projects root 'projects#index' end
3. View を作る
app/views/projects/index.html.erb
を作成する- 現時点で中身は空でもおk
4. 共通点プレートをいじる
① 共通ロゴと共通リンクを設定する
app/assets/images
に 適当なlogo.png
ファイルを入れておくapp/views/layouts/application.html.erb
を編集
<!DOCTYPE html> <html> <head> <title>Taskapp2</title> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> </head> <body> <%= image_tag "logo.png" %> <%= yield %> <%= link_to "Home", projects_path %> </body> </html>
image_tag
ヘルパーとlink_to
ヘルパーを利用して上記のように書くprojects_path
は$ be rake routes
でルーティングを確認した際の左端( Prefix カラム) に_path
をつけたもの
② 共通スタイルシートを設定する
app/assets/stylesheets/application.css
をいじる
body {background-color: #eee;}
5. 新規作成フォームを作成し、データを保存し、表示する
① app/controllers/projects_controller.rb
をいじる
class ProjectsController < ApplicationController def index @projects = Project.all end def show @project = Project.find(params[:id]) end def new @project = Project.new end def create @project = Project.new(project_params) @project.save redirect_to projects_path end private def project_params params[:project].permit(:title) end end
private
以下はセキュリティ対策のためのもの。
② app/views/projects/new.html.erb
を作成する
<h1>Add New</h1> <%= form_for @project do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> </p> <p> <%= f.submit %> </p> <% end %>
form_for
ヘルパーを利用する- submit したものが Projects#create に送られる
③ app/views/layouts/application.html.erb
をいじる
<!DOCTYPE html> <html> <head> <title>Taskapp2</title> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> </head> <body> <%= image_tag "logo.png" %> <%= yield %> <%= link_to "Add New", new_project_path %> | <%= link_to "Home", projects_path %> </body> </html>
④ app/views/projects/index.html.erb
を編集する
<h1>Projects</h1> <ul> <% @projects.each do |project| %> <li> <%= link_to project.title, project_path(project.id) %> </li> <% end %> </ul>
⑤ app/views/projects/show.html.erb
を作成する
<h1><%= @project.title %></h1>
6. Validation を設定してエラーメッセージを表示する
- 今ままでは空の状態でも新規登録できてしまうので、
app/models/project.rb
を編集
class Project < ActiveRecord::Base validates :title, presence: true end
- 今の設定のままだと、Validation に引っかかった時でも、 プロジェクト一覧にリダイレクトしてしまうので、
app/controllers/projects_controller.rb
の create アクション を次のように編集
def create @project = Project.new(project_params) if @project.save redirect_to projects_path else render 'new' end end
- エラーメッセージを表示するとより親切なので
app/views/projects/new.html.erb
を編集していく
<h1>Add New</h1> <%= form_for @project do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> <% if @project.errors.any? %> <%= @project.errors.messages[:title][0] %> <% end %> </p> <p> <%= f.submit %> </p> <% end %>
エラーが発生している場合、
@project.errors
にエラーメッセージが入るので、<% if @project.errors.any? %>
で条件分岐をかけて、メッセージを表示させている。また、エラーメッセージ、バリデーションルールは任意のものに設定できる。
app/models/project.rb
を編集
class Project < ActiveRecord::Base validates :title, presence: {message: "入力してください"}, length: {minimum: 3, message: "短すぎ!"} end
7. 編集フォームを作ってデータを更新する
- まずは編集フォームを作っていく。
app/views/projects/edit.html.erb
を作成。といっても中身は<h1>
タグだけ変えて、あとはapp/views/projects/new.html.erb
と一緒。
<h1>Edit</h1> <%= form_for @project do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> <% if @project.errors.any? %> <%= @project.errors.messages[:title][0] %> <% end %> </p> <p> <%= f.submit %> </p> <% end %>
- 次に編集画面へのリンクを追加する。
app/views/projects/index.html.erb
を編集
<h1>Projects</h1> <ul> <% @projects.each do |project| %> <li> <%= link_to project.title, project_path(project.id) %> <%= link_to "[Edit]", edit_project_path(project.id) %> </li> <% end %> </ul>
- アクションをまだ作っていないので、
app/controllers/projects_controller.rb
に edit アクションを追加
def edit @project = Project.find(params[:id]) end
- この時点で編集画面へジャンプできるが、update アクションをまだ作っていないので、更新できない。
app/controllers/projects_controller.rb
に update アクションを追加
def update @project = Project.find(params[:id]) if @project.update(project_params) redirect_to projects_path else render 'edit' end end
8. データを削除する
app/views/projects/index.html.erb
を編集し、Delete リンクを追加する。data: {confirm: "are you sure?"}
と記述することで確認アラートを出すことができる。
<h1>Projects</h1> <ul> <% @projects.each do |project| %> <li> <%= link_to project.title, project_path(project.id) %> <%= link_to "[Edit]", edit_project_path(project.id) %> <%= link_to "[Delete]", project_path(project.id), method: :delete, data: {confirm: "are you sure?"} %> </li> <% end %> </ul>
- destroy アクションを追加する。
app/controllers/projects_controller.rb
に追加。
def destroy @project = Project.find(params[:id]) @project.destroy redirect_to projects_path end
9. 重複するコードを共通化し、 Dry を目指す
まずフォームで重複する部分があるので、共通化していく。
app/views/projects/new.html.erb
とapp/views/projects/edit.html.erb
の共通部分をカットし、<%= render 'form' %>
で置き換える。
<h1>Add New</h1> <%= render 'form' %>
<h1>Edit</h1> <%= render 'form' %>
app/views/projects/_form.html.erb
を作成し、共通部分をコピペ。
<%= form_for @project do |f| %> <p> <%= f.label :title %><br> <%= f.text_field :title %> <% if @project.errors.any? %> <%= @project.errors.messages[:title][0] %> <% end %> </p> <p> <%= f.submit %> </p> <% end %>
次に、Controller でも重複する部分があるので、共通化していく。
@project = Project.find(params[:id])
が大量に含まれるため、before_action
でまとめる。その際、set_project
関数を private に用意すると後々編集する際に便利。
class ProjectsController < ApplicationController before_action :set_project, only: [:show, :edit, :update, :destroy] def index @projects = Project.all end def show end (中略) private def project_params params[:project].permit(:title) end def set_project @project = Project.find(params[:id]) end end
[3] Task に関するあれやこれ
次に、プロジェクトに属するタスクを設定するあれやこれを作っていきます。
以下、実際の手順。
手順
1. Model と Controller を用意する
$ be rails g model Task title done:boolean project:references
で Model を作る- 繰り返しになるが、モデル名は単数形、
stirng
型は省略可能 booelan
は真偽値型で、project:references
は Project モデルと紐付けろ、という意味- タスクが終わっているかどうかという項目の
done
はデフォルトで 未完了を表すfalse
であるのが望ましいので、db/migrate/**********_create_tasks.rb
を以下のように修正。
- 繰り返しになるが、モデル名は単数形、
class CreateTasks < ActiveRecord::Migration def change create_table :tasks do |t| t.string :title t.boolean :done, default: false t.references :project, index: true t.timestamps end end end
$ be rake db:migrate
でデータベースを作る$ be rails g controller Tasks
で Controller を作る
2. Association を設定する
- 先ほど Task モデルを作った際には Project モデルとの紐付けオプションをつけて実行したが、 Project モデルを作った際にそのようなオプションはつけなかったので手動で設定する必要がある。
app/models/project.rb
を編集。
class Project < ActiveRecord::Base has_many :tasks validates :title, presence: {message: "入力してください"}, length: {minimum: 3, message: "短すぎ!"} end
これで、「一対多の関係」、つまり、「1つの Project に対して、複数の Task」 という関係ができた。
続いて、Task に関するルーティングをいじっていく。とりあえず、 create アクションと、 destroy アクションができればいいので以下のように、
config/routes.rb
を編集する
Rails.application.routes.draw do resources :projects do resources :tasks, only: [:create, :destroy] end root 'projects#index' end
3. 新規作成フォームを作り、 task を保存する
- task の新規作成フォームを作るために、
app/views/projects/show.html.erb
を編集する
<h1><%= @project.title %></h1> <u1> <% @project.tasks.each do |task| %> <li><%= task.title %></li> <% end %> <li> <%= form_for [@project, @project.tasks.build] do |f| %> <%= f.text_field :title %> <%= f.submit %> <% end %> </li> </u1>
- create アクションがまだないので、
app/controllers/tasks_controller.rb
に追加
class TasksController < ApplicationController def create @project = Project.find(params[:project_id]) @task = @project.tasks.create(task_params) redirect_to project_path(@project.id) end private def task_params params[:task].permit(:title) end end
- 空の task を弾くためのバリデーションを設定する。
app/models/task.rb
を編集
class Task < ActiveRecord::Base belongs_to :project validates :title, presence: true end
4. Task を削除する
- Delete リンクを追加するために、
app/views/projects/show.html.erb
を編集する
<h1><%= @project.title %></h1> <u1> <% @project.tasks.each do |task| %> <li> <%= task.title %> <%= link_to "[Delete]", project_task_path(task.project_id, task.id), method: :delete, data: {confirm: "are you sure?"} %> </li> <% end %> <li> <%= form_for [@project, @project.tasks.build] do |f| %> <%= f.text_field :title %> <%= f.submit %> <% end %> </li> </u1>
- destroy アクションをまだ作っていないので、
app/controllers/tasks_controller.rb
に追加
def destroy @task = Task.find(params[:id]) @task.destroy redirect_to project_path(params[:project_id]) end
5. チェックボックスを用意して done を切り替える
app/views/projects/show.html.erb
のリストの中のタスクタイトルの前にチェックボックスを追加。check_box_tag
ヘルパーを利用。最初の引数にはid
を、2番目の引数にはvalue
を、3番目の引数にはチェックされているかどうかのtrue/false
をそれぞれ指定できる。- その後ろには、 HTML に渡したい属性をいくらでも追加できる。今回は、後で jQuery で使いたいので、扱いやすいように
task.id
とproject_id
をdata-id
とdata-project-id
という属性で管理できるようにした。 - 下のコードを追記してから、ブラウザでソースを見ると、
<input data-id="…" data-project_id="…" id="" name="" type="checkbox" value="" />
というのが出てきており、data-id 属性と data-project_id 属性で Task の id と Project の id が管理できているのがわかる。
<h1><%= @project.title %></h1> <u1> <% @project.tasks.each do |task| %> <li> <%= check_box_tag '', '', task.done, {'data-id' => task.id, 'data-project_id' => task.project_id} %> <%= task.title %> <%= link_to "[Delete]", project_task_path(task.project_id, task.id), method: :delete, data: {confirm: "are you sure?"} %> </li> <% end %> <li> <%= form_for [@project, @project.tasks.build] do |f| %> <%= f.text_field :title %> <%= f.submit %> <% end %> </li> </u1>
- 次に、チェックボックスが切り替わるたびに、 POST を送りたい。そのための toggle アクションを jQuery を用いつつ、用意する。
app/views/projects/show.html.erb
の一番下に以下のスクリプトを追加する。 - このスクリプトの意味は、「チェックボックスがクリックされた際に、 Ajax で
/projects/xxx/tasks/xxx/toggle
に POST しなさい」という意味。
<script> $(function(){ $("input[type=checkbox]").click(function(){ $.post('/projects/'+$(this).data('project_id')+'/tasks/'+$(this).data('id')+'/toggle'); }); }) </script>
- POST のルーティングが未設定なので
config/routes.rb
で設定する。以下を追記。
post '/projects/:project_id/tasks/:id/toggle' => 'tasks#toggle'
- POST 先の toggle アクションがないので作る。
app/controllers/tasks_controller.rb
に追加。また、今回は、 toggle アクションリクエストした際に、テンプレートを使わないので、その旨も書く。
def toggle @task = Task.find(params[:id]) @task.done = !@task.done @task.save render nothing: true end
- 以上で、タスクの完了/未完了がページをまたいでも保持されるようになる。
6. Tasks の数を表示する
- まず残タスク数を表示したいので、「
done
がfalse
のものを検索条件として保存しなさい」という意味で、app/models/tasks.rb
に以下を追記。 - これで
:unfinished
関数ができるので、どこからでも残タスク数にアクセスできる。
scope :unfinished, -> {where(done: false)}
- 実際に表示するために、
app/views/projects/index.html.erb
を以下のように書き換える。タイトル部分に先ほど定義した:unfinished
関数 を用いて、残タスク数を表示している。
<h1>Projects</h1> <ul> <% @projects.each do |project| %> <li> <%= link_to project.title, project_path(project.id) %> (<%= project.tasks.unfinished.count %>/<%= project.tasks.count %>) <%= link_to "[Edit]", edit_project_path(project.id) %> <%= link_to "[Delete]", project_path(project.id), method: :delete, data: {confirm: "are you sure?"} %> </li> <% end %> </ul>