これは、最新のRuby on Rails ガイド(v5.1.3) を読んだ際の学習記録です。
Getting Started with Rails — Ruby on Rails Guides
#1 Start Here
以下を学ぶ
Rails インストール、Rails アプリケーションの作成、そしてアプリケーションをデータベースへ接続する方法
一般的なRails アプリケーションのレイアウト
MVC , RESTfulデザインの基本原則
Rails アプリケーションを素早く生成する方法
Rails はRuby で書かれたWebアプリケーションフレームワーク 。Rails には以下の2つの重要な原則がある。
Don't repeat yourself - Wikipedia
Don’t repeat yourself (DRY) あるいはSingle Source of truth(英)[要出典]は、特にコンピューティングの領域で、重複を防ぐ考え方である。この哲学は、情報の重複は変更の困難さを増大し透明性を減少させ、不一致を生じる可能性につながるため、重複するべきでないことを強調する。
Convention Over Configuration
設定より規約 - Wikipedia
設定より規約(せっていよりきやく、英: convention over configuration)とは、開発者の決定すべきことを減少させ、単純にするが柔軟性は失わせないというソフトウェア設計パラダイム 。
Creating a New Rails Project
Creating the Blog Application
‘blog’ アプリケーションを生成する。
$ rails new blog
blog配下には以下のファイルを生成される。
app/ Contains the controllers, models, views, helpers, mailers, channels, jobs and assets for your application. You’ll focus on this folder for the remainder of this guide.
bin/ Contains the rails script that starts your app and can contain other scripts you use to setup, update, deploy or run your application.
config/ Configure your application’s routes, database, and more. This is covered in more detail in Configuring Rails Applications.
config.ru Rack configuration for Rack based servers used to start the application.
db/ Contains your current database schema, as well as the database migrations.
Gemfile
Gemfile.lock These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see the Bundler website.
lib/ Extended modules for your application.
log/ Application log files.
public/ The only folder seen by the world as-is. Contains static files and compiled assets.
Rakefile This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails . Rather than changing Rakefile , you should add your own tasks by adding files to the lib/tasks directory of your application.
README.md This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.
test/ Unit tests, fixtures, and other test apparatus. These are covered in Testing Rails Applications.
tmp/ Temporary files (like cache and pid files).
vendor/ A place for all third-party code. In a typical Rails application this includes vendored gems.
.gitignore This file tells git which files (or patterns) it should ignore. See Github - Ignoring files for more info about ignoring files.
Starting up the Web Server
web serverを起動する。
$ cd blog
$ rails server
#shorthand: rails s
Say “Hello”, Rails
Rails で"Hello" を表示させるために、viewとcontrollerを生成する。
‘Welcome’ controllerの'index' アクションを生成する。
$ rails generate controller Welcome index
上記のgenerateコマンドで以下のファイル群が生成される。
create app/controllers/welcome_controller.rb
route get 'welcome/index'
invoke erb
create app/views/welcome
create app/views/welcome/index.html.erb
invoke test_unit
create test/controllers/welcome_controller_test.rb
invoke helper
create app/helpers/welcome_helper.rb
invoke test_unit
invoke assets
invoke coffee
create app/assets/javascripts/welcome.coffee
invoke scss
create app/assets/stylesheets/welcome.scss
controllerは、app/controllers/welcome_controller.rb, viewはapp/views/welcome/index.html.erb へ生成された。
app/views/welcome/index.html.erb のh1タグを以下のように修正する。
<h1>Hello, Rails!</h1>
Setting the Application Home Page
Rails のroot を設定する。
config/routes.rb へ以下を追加する。
root 'welcome#index'
http://localhost:3000 へアクセスすると、Hello, Rails が表示される。
Getting Up and Running
CRUD 操作を実現するためのresourceを定義する。
以下をconfig/routes.rb へ追加。
resources :articles
rails routes コマンドを実行すると、標準のRESTfulアクションが定義される。
$ rails routes
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
articles GET /articles(.:format) articles#index
POST /articles(.:format) articles#create
new_article GET /articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PATCH /articles/:id(.:format) articles#update
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
root GET / welcome#index
Laying down the groundwork
生成した、http://localhost:3000/articles/new へアクセスしてみよう。'Routing Error'が出る。
これはrouteは生成したが、まだcontroller、viewが生成されてないため。
コントローラーを生成する。
$ rails generate controller Articles
生成した、app/controllers/articles_controller.rb を見てみよう。
class ArticlesController < ApplicationController
end
ApplicationController を継承した、ArticlesControllerが定義されているが、まだ中には何も定義されていない。
この状態で先程のURI へアクセスしてみよう。
http://localhost:3000/articles/new
‘Unknown action’ エラーが出る。
app/controllers/articles_controller.rb を以下のように更新する。
class ArticlesController < ApplicationController
def new
end
end
この状態で先程のURI へアクセスしてみよう。
http://localhost:3000/articles/new
‘ActionController ::UnknownFormat in ArticlesController#new’ 今度は先程と別のエラーが出る。
viewがないためこのようなExceptionがなげられているため、次のviewテンプレートを新規作成する。
app/views/articles/new.html.erb
< h1 > New Article</ h1 >
これでlocalhost :3000/articles/new へアクセスすると正常にページが表示される。
The first form
Rails のフォームビルダーは form_for と呼ぶヘルパーメソッドで提供される。
form_for: ActionView::Helpers::FormHelper
app/views/articles/new.html.erb へ以下を追加する。
<%= form_for :article do |f| %>
< p >
<%= f.label :title %>< br >
<%= f.text_field :title %>
</ p >
< p >
<%= f.label : text %>< br >
<%= f.text_area : text %>
</ p >
< p >
<%= f.submit %>
</ p >
<% end %>
生成されたhtmlを見ると、formのアクション属性が /articles/new を指している。
これを、/articles へ移動するように変更するため、form_forを以下のように書き換える。
<%= form_for :article, url : articles_path do |f| %>
ここで、rails routes コマンドでRails のアクションを振り返ってみる。
$ rails routes
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
articles GET /articles(.:format) articles#index
POST /articles(.:format) articles#create
new_article GET /articles/new(.:format) articles#new
edit_article GET /articles/:id/edit(.:format) articles#edit
article GET /articles/:id(.:format) articles#show
PATCH /articles/:id(.:format) articles#update
PUT /articles/:id(.:format) articles#update
DELETE /articles/:id(.:format) articles#destroy
root GET / welcome#index
POST /articles のアクションは create となっているため、画面のsave articleボタンを押すと ‘Unknown action’ エラーとなる。
Creating articles
‘Unknown action’ エラーを取り除くため、create アクションをコントローラへ追加する必要がある。
app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def new
end
def create
end
end
このままだと 204 No Content エラーが出てしまう。
フォームがsubmitされるとパラメータがRails に送信されるので、以下のようにして表示してみよう。
def create
render plain : params[:article ].inspect
end
これで再度画面の'save submit' を押すと以下が表示される。title, text はformに入力した値が反映される。
<ActionController::Parameters {"title"=>"First Article!", "text"=>"This is my first article."} permitted: false>
Creating the Article model
次のコメンドでArticleモデルを生成する。モデルには単数形が使われる。
$ rails generate model Article title:string text:text
Running via Spring preloader in process 12909
invoke active_record
create db/migrate/20170815123358_create_articles.rb
create app/models/article.rb
invoke test_unit
create test/models/article_test.rb
create test/fixtures/articles.yml
このコマンドは、Rails にArticleモデルを共にstring型のtitle, text型のtextの属性を生成する。
これらの属性は自動的にarticlesテーブルに追加され、さらにArticleモデルにマッピング される。
Active Recordは列名をモデル属性に自動的に対応させる。つまり、Rails モデル内で属性を宣言する必要はない。これは、Active Recordによって自動的に行われる。
Running a Migration
生成された db/migrate/20170815123358_create_articles.rb
class CreateArticles < ActiveRecord ::Migration [5.0 ]
def change
create_table :articles do |t |
t.string :title
t.text :text
t.timestamps
end
end
end
次のコマンドで、articles テーブルを実際にデータベースへ生成する。
$ rails db:migrate
Saving data in the controller
ArticlesControllerへ戻り、submitしたデータをデータベースへ保存するためにcreateアクションを変更する。
app/controllers/articles_controller.rb
def create
@article = Article .new(params[:article ])
@article .save
redirect_to @article
end
実際に画面から'save article'を押すと ‘ActiveModel::ForbiddenAttributesError in ArticlesController#create’ エラーが表示される。
Rails が備えているセキュリティ機能が働いているため、コントローラーにどのパラメータが許可されているか伝える必要がある。
title と text を許可してみよう。
app/controllers/articles_controller.rb
def create
@article = Article .new(article_params)
@article .save
redirect_to @article
end
private
def article_params
params.require(:article ).permit(:title , :text )
end
article_params は外部から意図せず呼ばれることを防ぐため、基本はprivateメソッドとして定義される。
Showing Articles
再度画面から、'Save Article'を押してみよう。すると、show アクションがないため以下のエラーが表示される。
Unknown action
The action 'show' could not be found for ArticlesController
rails routes で確認。
$ rails routes
...
article GET /articles/:id(.:format) articles#show
show アクションをコントローラへ追加しよう。
app/controllers/articles_controller.rb
def show
@article = Article .find(params[:id ])
end
続いてshowアクションのためのviewを追加する。
app/views/articles/show.html.erb
< p >
< strong > Title:</ strong >
<%= @article.title %>
</ p >
< p >
< strong > Text:</ strong >
<%= @article.text %>
</ p >
再度画面から'Save Article'を押してみると、以下が画面に表示される。
Title: test title
Text: test Text
Listing all articles
記事リストページを追加する。
$ rails routes
articles GET /articles(.:format) articles#index
app/controllers/articles_controller.rb
def index
@articles = Article .all
end
app/views/articles/index.html.erb
< h1 > Listing articles</ h1 >
< table >
< tr >
< th > Title</ th >
< th > Text</ th >
</ tr >
<% @articles.each do |article| %>
< tr >
< td ><%= article.title %></ td >
< td ><%= article.text %></ td >
< td ><%= link_to 'Show' , article_path(article) %></ td >
</ tr >
<% end %>
</ table >
Adding links
記事のcreate, show, list が作成できたので、今度は記事へナビゲートするためのリンクを追加してみよう。
app/views/welcome/index.html.erb
< h1 > Hello, Rails!</ h1 >
<%= link_to 'My Blog' , controller: 'articles' %>
link_to メソッドはRails のview helperの1つ。articles へのリンクを生成する。
app/views/articles/index.html.erb の
タグの上に以下を追加してみよう。
<%= link_to 'New article' , new_article_path %>
上記は新しい記事作成ページへのリンクとなる。
次に indexアクションへのbackリンクを追加してみよう。
app/views/articles/new.html.erb
<%= form_for :article, url : articles_path do |f| %>
...
<% end %>
<%= link_to 'Back' , articles_path %>
最後にshowページにもbackボタンを追加してみよう。
app/views/articles/show.html.erb
< p >
< strong > Title:</ strong >
<%= @article.title %>
</ p >
< p >
< strong > Text:</ strong >
<%= @article.text %>
</ p >
<%= link_to 'Back' , articles_path %>
Adding Some Validation
app/models/article.rb ファイルを見てみよう
class Article < ApplicationRecord
end
Article クラスは ApplicationRecord を継承している。
さらにApplicationRecordクラスは、ActiveRecord ::Baseを継承しており、様々な機能が使えるようになっている。
Rails はモデルに送信するデータのバリデーションを行うメソッドを備えている。以下のようにarticle.rbモデルを変更してみよう。
class Article < ApplicationRecord
validates :title , presence : true ,
length : { minimum : 5 }
end
この変更により、すべてのArticleのタイトルが5文字以上になるようになります。
不正なタイトルで@article.saveを呼び出すと、falseが返されるようになるので、
@article.save の結果をチェックするコードを追加しよう。
app/controllers/articles_controller.rb
def new
@article = Article .new
end
def create
@article = Article .new(article_params)
if @article .save
redirect_to @article
else
render ' new '
end
end
private
def article_params
params.require(:article ).permit(:title , :text )
end
上記の変更で@article.save がfalseを返す場合は、 new アクションへ遷移するようになった。
ただ、これだけでは不十分なので、app/views/articles/new.html.erb を修正して、ユーザにエラーを通知しよう。
app/views/articles/new.html.erb
<%= form_for :article, url : articles_path do |f| %>
<% if @article.errors.any? %>
< div id = "error_explanation" >
< h2 >
<%= pluralize(@article.errors.count, "error" ) %> prohibited
this article from being saved:
</ h2 >
< ul >
<% @article.errors.full_messages.each do |msg| %>
< li ><%= msg %></ li >
<% end %>
</ ul >
</ div >
<% end %>
< p >
<%= f.label :title %>< br >
<%= f.text_field :title %>
</ p >
< p >
<%= f.label : text %>< br >
<%= f.text_area : text %>
</ p >
< p >
<%= f.submit %>
</ p >
<% end %>
<%= link_to 'Back' , articles_path %>
ArticlesControllerに@article = Article.newを追加した理由は、@articleがビューでnil となり、@article.errors.any?でエラーが発生するため。
Updating Articles
CRUD のreadとcreateについては学んだので、次のはupdateを行う。
edit メソッドをコントローラーへ追加する。
app/controllers/articles_controller.rb
def edit
@article = Article .find(params[:id ])
end
editテンプレートファイルを作成する。
app/views/articles/edit.html.erb
< h1 > Edit article</ h1 >
<%= form_for(@article) do |f| %>
<% if @article.errors.any? %>
< div id = "error_explanation" >
< h2 >
<%= pluralize(@article.errors.count, "error" ) %> prohibited
this article from being saved:
</ h2 >
< ul >
<% @article.errors.full_messages.each do |msg| %>
< li ><%= msg %></ li >
<% end %>
</ ul >
</ div >
<% end %>
< p >
<%= f.label :title %>< br >
<%= f.text_field :title %>
</ p >
< p >
<%= f.label : text %>< br >
<%= f.text_area : text %>
</ p >
< p >
<%= f.submit %>
</ p >
<% end %>
<%= link_to 'Back' , articles_path %>
app/controllers/articles_controller.rb
def update
@article = Article .find(params[:id ])
if @article .update(article_params)
redirect_to @article
else
render ' edit '
end
end
app/views/articles/index.html.erb
< table >
< tr >
< th > Title</ th >
< th > Text</ th >
< th colspan = "2" ></ th >
</ tr >
<% @articles.each do |article| %>
< tr >
< td ><%= article.title %></ td >
< td ><%= article.text %></ td >
< td ><%= link_to 'Show' , article_path(article) %></ td >
< td ><%= link_to 'Edit' , edit_article_path(article) %></ td >
</ tr >
<% end %>
</ table >
app/views/articles/show.html.erb
<%= link_to 'Edit' , edit_article_path(@article) %> |
<%= link_to 'Back' , articles_path %>
Using partials to clean up duplication in views
partialファイルを作成し、コードの重複を排除する。
partialファイルには慣例として、ファイル名の先頭に ‘_’ をつける。
app/views/articles/_form.html.erb
<%= form_for @article do |f| %>
<% if @article.errors.any? %>
< div id = "error_explanation" >
< h2 >
<%= pluralize(@article.errors.count, "error" ) %> prohibited
this article from being saved:
</ h2 >
< ul >
<% @article.errors.full_messages.each do |msg| %>
< li ><%= msg %></ li >
<% end %>
</ ul >
</ div >
<% end %>
< p >
<%= f.label :title %>< br >
<%= f.text_field :title %>
</ p >
< p >
<%= f.label : text %>< br >
<%= f.text_area : text %>
</ p >
< p >
<%= f.submit %>
</ p >
<% end %>
app/views/articles/new.html.erb ファイルを更新してみよう。
< h1 > New article</ h1 >
<%= render 'form' %>
<%= link_to 'Back' , articles_path %>
app/views/articles/edit.html.erb も同様に更新する
< h1 > Edit article</ h1 >
<%= render 'form' %>
<%= link_to 'Back' , articles_path %>
Deleting Articles
articleを削除するDELETEメソッドを作成する。
DELETE /articles/:id(.:format) articles#destroy
app/controllers/articles_controller.rb
def destroy
@article = Article .find(params[:id ])
@article .destroy
redirect_to articles_path
end
app/views/articles/index.html.erb
< h1 > Listing Articles</ h1 >
<%= link_to 'New article' , new_article_path %>
< table >
< tr >
< th > Title</ th >
< th > Text</ th >
< th colspan = "3" ></ th >
</ tr >
<% @articles.each do |article| %>
< tr >
< td ><%= article.title %></ td >
< td ><%= article.text %></ td >
< td ><%= link_to 'Show' , article_path(article) %></ td >
< td ><%= link_to 'Edit' , edit_article_path(article) %></ td >
< td ><%= link_to 'Destroy' , article_path(article),
method : :delete,
data : { confirm: 'Are you sure?' } %></ td >
</ tr >
<% end %>
</ table >
結果
score: 765
listening: 405 (+0)
reading: 360 (-5)
スコア推移
感想
あかn
次回受験
2017/09/10 第223回
Cybozu Garoon を社内で使っているんだけど、API が公開されていることをつい最近知った。
developer.cybozu.io
サイボウズ 上の当日の予定をAPI 経由で取得できるので、
毎朝チームのチャットグループに自分のスケジュールを自動投稿する、とか面白いんじゃないかな。
サイボウズ のGaroon API はSOAP 方式で実装されている。XML 辛い…
PHP でSOAP のリクエス トどう書けばいいのかわからんので、ヒアドキュメントに全部突っ込む形の使い捨てスクリプト を書いた。*1
上記スクリプト 内では、スケジュールのタイトルしか取得していないが、
当然スケジュールの時間、詳細情報、コメントなども取得できる。
サイボウズ 導入してる会社は多いと思うので何かの役に立てば。
#20 Bit Manipulation: Lonely Integer
www.hackerrank.com
入力される数は、1つの数を除いて、ペアになっている。
入力される数の中で、ペアになっていない数字を見つけて出力する問題。
solution
XOR(排他的論理和 )を使うことで、ペアになっていない数字を簡単に見つけられる。
以下ruby での解。
input = $stdin .read.split("\n" )
n = input.shift
nums = input.shift.split(" " ).map(&:to_i )
puts nums.inject {|result , num | result ^ num }
github.com
排他的論理和 - Wikipedia
感想
Cracking the Coding Interview Challenges 20題全てコンプリートした。
平日毎朝出社前に1題解くのを目標にゆっくり取り組んでいたので、20日程度。
やってみると、2,30分悩んでしまう問題もあったり、案外すんなり解けなかったりもした。
英語の出題分を理解するのもなかなか気合が要るので、これはよい復習になった。
なんでも良いんだけど、最近はこういうコツコツと日々積み上げていくことの大事さをひしひしと感じている。
#19 Recursion: Davis' Staircase
www.hackerrank.com
1 o 2 or 3段を一度に登れる人間が、n段の階段を登る際に、何通りの登り方が存在するか計算する問題。
以下のような入力が与えられる。
3
1
3
7
最初の行が階段の数。2行目以下は、階段のステップ数。
それぞれの階段について、何通りの登り方があるかを出力する。
上記入力の場合、出力は以下となる。
1
4
44
solution
再帰 関数を使って解く。これもメモ化をすることでテストケースをパスすることができた。
以下ruby での解。
#!/bin/ruby
class Solution
def initialize (n, stepsATime)
@steps , @stepsATime , @memo = n, stepsATime, []
end
def climbingWays (current = 0 )
return @memo [current] if @memo [current]
return 0 if current > @steps
return 1 if current == @steps
ways = 0
@stepsATime .each do |v |
ways += climbingWays(current + v)
end
return @memo [current] = ways
end
end
input = $stdin .read.split("\n" ).map(&:to_i )
input.shift.times do
puts Solution .new(input.shift, [1 ,2 ,3 ]).climbingWays
end
github.com
再帰 - Wikipedia
#18 Recursion: Fibonacci Numbers
www.hackerrank.com
入力される数値nに対して、n項のフィボナッチ数を求めて出力する問題。
solution
問題文の通りに実装すると以下のようになる。
def fib (n)
return n if n <= 1
return fib(n-1 )+fib(n-2 )
end
puts fib(gets.to_i)
これは正しいが、計算量が大きくなり、テストケースをパスできない。
今回はメモ化することでフィボナッチ計算を高速化する。
以下ruby での解答。
class Solution
def initialize
@memo = [0 , 1 ]
end
def fib (n)
return if n < 0
return @memo [n] if @memo [n]
return @memo [n] = self .fib(n - 1 ) + self .fib(n - 2 )
end
end
puts (Solution .new).fib(gets.to_i)
github.com
フィボナッチ数とは
フィボナッチ数 - Wikipedia
引用をストックしました
ストック一覧を見る
閉じる
引用するにはまずログインしてください
ログイン
閉じる
引用をストックできませんでした。再度お試しください
閉じる