Rails4 チュートリアル写経
WEB+DB Press の特集記事を見つつ。さっきナニした通り Ruby は 2.0.0-p0 です。
$ ruby -v ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]
とりあえず bundler 入れなさい、とあるな。
$ gem i bundler --no-ri --no-rdoc Fetching: bundler-1.3.2.gem (100%) Successfully installed bundler-1.3.2 Done installing documentation for bundler (0 sec). 1 gem installed
で、rails を普通に導入すれば 4 なナニが入るのかな。
$ gem i rails
確認。
$ rails -v Rails 3.2.12
む。--pre を付けろ、とか注釈がありますね。リトライできるのかな。
$ gem i rails --pre --no-ri --no-rdoc
なんか導入でハマりそうな予感。案の定以下な出力。
ERROR: While executing gem ... (Gem::DependencyError)
gem list --local してみると action* なナニが導入されてるのでこれがいかんのかな。手動で全部 uninstall してみます。で、リトライ。
駄目か。-v 指定で云々、なのかな。と思ったら --pre 指定なのか。
む、thread_safe 入れれ、ときた。
$ gem i thread_safe -v 0.1 --no-ri --no-rdoc
で、
$ gem i activesupport --pre --no-ri --no-rdoc
actionpack を入れようとしたら builder (~> 3.1.0), rack (~>1.5.2) と出た。
gem i builder -v 3.1.0 --no-ri --no-rdoc gem i rack -v 1.5.2 --no-ri --no-rdoc
これはなかなかにキツいな。で、再開。
$ gem i actionpack --pre --no-ri --no-rdoc
activerecord が activemodel (=4.0.0) および arel (~>4.0.0) activerecord-deprecated_finders (~>0.0.3) を要求したので導入。
$ gem i activemodel --pre --no-ri --no-rdoc $ gem i arel --pre --no-ri --no-rdoc $ gem i activerecord-deprecated_finders -v 0.0.3 --no-ri --no-rdoc
で、再開。
$ gem i activerecord --pre --no-ri --no-rdoc
次は actionmailer が mail (~>2.5.3) を要求。
$ gem i mail -v 2.5.3 --no-ri --no-rdoc
再開。
$ gem i actionmailer --pre --no-ri --no-rdoc $ gem i railties --pre --no-ri --no-rdoc
これはなかなかにキツいな。で、sprockets-rails が sprockets (~>2.8) を要求。
$ gem i sprockets -v 2.8 --no-ri --no-rdoc
再開。
$ gem i sprockets-rails --pre 2.0.0 --no-ri --no-rdoc
そして最後に
$ gem i rails --pre --no-ri --no-rdoc
を、終わった。
$ rails -v Rails 4.0.0.beta1
やれやれ。
アプリケーションの作成
写経着手。まずプロジェクトの作成。
$ rails new tetsuzine
で cd して ls したら以下なカンジ。
$ ls app bin config config.ru db Gemfile Gemfile.lock lib log public Rakefile README.rdoc test tmp vendor
spring なるソレを入れとけ、とあるので導入。
$ gem i spring --no-ri --no-rdoc
書店なアプリらしく、とりあえず scaffold で本を表現するリソースを、とのこと。
$ spring generate scaffold book title price:integer
あら、Could not find a JavaScript runtime と言われたぞ。Gemfile に以下を追加して
gem 'execjs' gem 'therubyracer'
bundle install してリトライ。て駄目じゃん。この症状で苦しんだ方が沢山いらっしゃるようですが、nodejs 入れれ、とかあるな。あと Gemfile を以下に修正。
gem 'therubyracer', :platforms => :ruby
で、bundle install してどうか。つうかなかなかにアレですね。beta だから仕方が無いのでしょうが、これは色々な意味で地雷の域を超えてますね。あ、正常終了。
$ spring generate scaffold book title price:integer invoke active_record create db/migrate/20130310063816_create_books.rb create app/models/book.rb invoke test_unit create test/models/book_test.rb create test/fixtures/books.yml invoke resource_route route resources :books invoke jbuilder_scaffold_controller create app/controllers/books_controller.rb invoke erb create app/views/books create app/views/books/index.html.erb create app/views/books/edit.html.erb create app/views/books/show.html.erb create app/views/books/new.html.erb create app/views/books/_form.html.erb invoke test_unit create test/controllers/books_controller_test.rb invoke helper create app/helpers/books_helper.rb invoke test_unit create test/helpers/books_helper_test.rb invoke jbuilder exist app/views/books create app/views/books/index.json.jbuilder create app/views/books/show.json.jbuilder invoke assets invoke coffee create app/assets/javascripts/books.js.coffee invoke scss create app/assets/stylesheets/books.css.scss invoke scss create app/assets/stylesheets/scaffolds.css.scss
あんま時間無いのでどんどん進めます。中身確認は別途で。
まず DB 作成。
$ spring rake db:migrate == CreateBooks: migrating ==================================================== -- create_table(:books) -> 0.0026s == CreateBooks: migrated (0.0028s) ===========================================
で、試験実行。rake のデフォなソレが試験になってるのか。
$ spring rake Run options: --seed 54073 # Running tests: Finished tests in 0.005872s, 0.0000 tests/s, 0.0000 assertions/s. 0 tests, 0 assertions, 0 failures, 0 errors, 0 skips Run options: --seed 63666 # Running tests: ....... Finished tests in 2.177550s, 3.2146 tests/s, 5.9700 assertions/s. 7 tests, 13 assertions, 0 failures, 0 errors, 0 skips
で、動作確認。
$ rails s => Booting WEBrick => Rails 4.0.0.beta1 application starting in development on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server [2013-03-10 15:43:04] INFO WEBrick 1.3.1 [2013-03-10 15:43:04] INFO ruby 2.0.0 (2013-02-24) [x86_64-linux] [2013-03-10 15:43:04] INFO WEBrick::HTTPServer#start: pid=22708 port=3000
む、config/routes.rb を云々とありますね。以下を追加。
root 'books#index'
すげー。アプリケーションの再起動も不要なのか。しかも public/index.html の削除も不要とか書いてありますね。
カラム追加
以下、とのこと。
$ spring generate migration add_published_on_to_books published_on:date invoke active_record create db/migrate/20130310064951_add_published_on_to_books.rb
内容は以下。
class AddPublishedOnToBooks < ActiveRecord::Migration def change add_column :books, :published_on, :date end end
むむ。実行して各種パーツを修正とのこと。
$ spring rake db:migrate == AddPublishedOnToBooks: migrating ========================================== -- add_column(:books, :published_on, :date) -> 0.0006s == AddPublishedOnToBooks: migrated (0.0007s) =================================
なんとなく実行も早い気がする。以下を修正なのか
- app/views/books
- index.html.erb
- show.html.erb
- _form.html.erb
StrongParameters の働きを確認
このままではフォームからの入力はできるけど、登録はされない、とのこと。確かに反映されないですね。app/controllers/books_controller.rb のいっちゃん下に以下な記述があります。
# Never trust parameters from the scary internet, only allow the white list through. def book_params params.require(:book).permit(:title, :price) end
ここに published_on なフィールドを追加すれば、とのこと。ここで明示的に許可した属性のみがデータベースの引き渡されるとのこと。
動作もそのとおりになってますね。
検索機能の実装
むむ、なんかよく分からんが手順としては
- 検索モデルを追加
- app/views/books/index.html.erb に検索フォームを追加
- コントローラの index アクションに処理を追加
- books モデルに検索処理を追加
Rails4 では model の all メソド呼び出し時には SQL は発行されない、とか書いてありますね。では盛り込んでみます。
まず model 追加。app/models/search_form.rb として以下を新規作成。
class SearchForm include ActiveModel::Model attr_accessor :q end
で、app/views/books/index.html.erb に以下を盛り込み。先頭って書いてますね。
<%= form_for @search_form, url: books_path, html: {method: :get} do |f| %> <%= f.search_field :q %> <%= f.submit 'search' %> <% end %> <h1>Listing books</h1>
次に app/controllers/books_controllers.rb の index なアクションを云々。
# GET /books # GET /books.json def index @search_form = SearchForm.new params[:search_form] @books = Book.all if @search_form.q.present? @books = @books.titled @search_form.q end end
で、最後に app/models/book.rb に検索処理を記述。
class Book < ActiveRecord::Base scope :titled, ->(q) {where 'title like ?', "%#{q}%" } end
これでサーバ起動して動作確認。落ちてるな。何が悪いのか。てコントローラ上書きしてなかったorz
で動作確認してみたのですが検索できるようになってますね。
検索処理の AJAX 化
手順としては
- 各行で book オブジェクトの id を覚えておくように修正 (view)
- JSON テンプレートの修正
- AJAX 処理の実装
- 問題があるらしいので修正
とのこと。
まず、app/views/books/index.html.erb を以下に、とのこと。
<tbody> <% @books.each do |book| %> <%= content_tag_for tr:, @books do |book| %> <td><%= book.title %></td>
次に app/views/books/index.json.jbuilder を以下に。
json.array!(@books) do |book| json.extract! book, :id end
で、app/views/books/index.html.erb を以下に。
<%= form_for @search_form, url: books_path(format: :json), remote: true, html: {method: :get} do |f| %> <%= f.search_field :q %> <%= f.submit 'search' %> <% end %>
で、app/assets/javascripts/books.js.coffee を以下に。
$ -> $('#new_search_form').on 'ajax:success', (e, books) -> $('tr.book').hide() ids = (books.map (b) -> "#book#{b.id}").join(',') $(ids).show()
このへんさっぱりワケワカですな。サーバ再起動して確認。あ、表示されなくなっちゃいましたねorz
あ、typo 発見。books.js.coffee が以下でした (一部のみ)。
ids = (books.map (b) -> "#book_#{b.id}").join(',')
これで表示された。でもまだ何かがおかしい。さっきは S で両方表示されてたけど今は駄目だし。
とりあえず
写経終了。問題解決できれば追記するかも。それにしても JS が出てくるとさっぱりなのは何とかしないとマズい。