動作環境はMacです。
##Ruby on Railsとは?##
webアプリケーションを作るためのwebアプリケーションフレームワーク。
フレームワークとは、開発者が1から用意しなくても、必要なライブラリや、機能を自動で用意してくれるもの。
Rubyで書かれており、オープンソース(誰でも使用可能)
Railsと呼ばれたりR on Rと略されて呼ばれることもある。
作者 デイビット・ハイネマイヤー・ハンソン氏
歴史
2004年7月に最初のバージョンがリリース。
RailsのコンセプトはPHPフレームワークのcakePHPやSymfonyになどに影響を与えている。
Ruby Gems
- gemというライブラリの形式が採用。
- よく使う機能がgemで公開されているので、開発工数を削減できる。
- RubyGemsはライブラリの作成やインストールを助けるシステム。
##Railsプロジェクトの作成##
ターミナル
$ cd ~/フォルダ名/ #任意のフォルダへ移動
$ cd rails_projects #ここではrails_projectsというフォルダを作成し移動
$ rails _5.2.2_new hello #rails projectsの新規作成コマンド ここではバージョンを指定している
rails newコマンドでアプリケーション作成に必要なフォルダを自動的に生成してくれる。
動作確認
下記コマンドでrailsの動作確認が可能
$rails s #railsサーバーの立ち上げ
railsはwebサーバーを持っており、web上で閲覧が可能になる。
rails sを起動し、割り当てられらURLにアクセスすると、welcome画面が表示される。
URLを知っていれば第三者から閲覧が可能になる。
$rails c #railsサーバーの終了
上記コマンドでURLにアクセスしてもwelcome画面が表示されなくなる。
コントローラーの作成
ブラウザに表示するには、最低でもコントローラーが必要になる。
$ rails g controller users index
rails g controllerで必要なコントローラーのファイル群を作成。
コントローラー名は複数形が基本。(データベースに紐づかない場合は単数形になる場合も)
indexはコントローラーに記述されるアクション(メソッド)。
class UsersController < ApplicationController #Userscontrollerはappricationコントローラーを継承している。
def index #これがアクション(メソッドと同義)
render plain: "Hello!,World!" #renderはブラウザに表示 plainは平語のテキストの意味
end
end
これでブラウザ上に表示されるようになる。
ルーティング
URLとマッチするアクションに振り分けるための機能
下記コマンドでURLとコントローラー、アクションの結びつきを確認することが可能。
$rails routes
Prefix Verb URI Pattern Controller#Action
users_index GET /users/index(.:format) users#index
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
prefixはパスの指定で使用可能。
VerbはHTTPメソッドのこと。GETはデータ取得 POSTはデータ送信 DELETEはデータ削除など。
URI Pattern はざっくりURLと同義。
Controller#Actionはコントーラーのどのアクションと結びついているかを示すもの
現在下記の通りURLにusers/indexが指定された時にコントローラーのindexアクションが呼ばれる仕様になっている。
Rails.application.routes.draw do
#get 'users/index'
get 'users/index', to: "users#index" #上の記述と同じ意味。
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
これをusers/のURLが指定された時にindexアクションがよばれるように書き換えてみる。
Rails.application.routes.draw do
#get 'users/index'
get 'users/', to: "users#index" #users/indexからusers/に書き換え
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
上記に書き換えるとusers/のURL指定でUsersコントローラーのindexアクションが呼ばれる。users/indexに指定すると、Routing Errorrとなる。
routesで確認してみる。
rails routes
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
viewの作成
現在、コントローラーのみをしようして、画面にレンダリング(描写)しているが、RailsのMVC思想に基づくと不自然なので、viewを作成しそこに記述を指定していく。
class UsersController < ApplicationController
def index
#render plain: "Hello!,World!"
end
end
上のコントローラのindexアクションにひもづくviewはrails gコマンドの時に自動的に作成されているので、開発者が指定する必要はない。
app/views/controller/index.htmlに記述する
app/views/コントローラー名/アクション名.html.erb
自動的に生成されている。
<p> Hello! World.</p>
このファイルへの記述でUsersコントローラーのindexアクションと紐付くviewがレンダリングされる。
ERB
viewにrubyの機能を埋め込む技術
<p> Hello! World.</p>
<p>
<%= 10 + 1 %> #<%= %>の内側がrubyのプログラム
</p>
<%= %>はレンダリングをしたい時の記述
<% %>とイコールを外すと、レンダリングされない
if文など表示する必要がない場合は=は外す。
ControllerからViewに値を渡す
Viewへの記述はなるべくレンダリング作業のみにしたいので、プログラミムの処理などはControllerやModelなどに記述するようにする。
class UsersController < ApplicationController
def index
#render plain: "Hello!,World!"
@num = 10 + 1 #viewのプログラムをControllerに記述
end
end
<p> Hello! World.</p>
<p>
<%= 10 + 1 %>
</p>
<p>
<%= @num %> #viewへは渡されたインスタンス変数を記述
</p>
ローカル変数numとした場合はviewへの描写はできないので注意。
Modelの作成
コマンド
$rails g model モデル名 カラム名:データ型
主なデータ型
integer 整数
float 小数点
string 文字列
text 長い文字列
boolean 真偽値
どのデータベース製品でも適用できる。
userモデルを作成
$ rails g model user name:string age:integer
上記コマンドで必要なファイル群が作成される。
/db/migrateフォルダの中に、migrateファイルが作成されている。
これは、テーブルの構造の変更をする際に必要なファイル。
class CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name
t.integer :age
t.timestamps #自動で作成される。レコードの作成や、編集の日付を管理するカラム
end
end
end
ターミナルで下記のコマンドを実行しmigrateを実行
rails db:migrate
== 20190306031934 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0020s
== 20190306031934 CreateUsers: migrated (0.0021s) =====================
データベース構造の確認
下記コマンドでデータベースをコマンドで確認することができるようになる。
$rails dbconsole
sqlite> .tables #テーブルを確認
ar_internal_metadata schema_migrations users
sqlite> .schema users #usersテーブルの中身の確認
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "age" integer, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL); #migrateファイルに記述したtimestampがcreated_atと updated_atのカラムを自動的に生成してくれている。
標準ではsqliteと呼ばれる軽量のデータを扱う製品が用意されている。mysqlなどの他のデータベース製品をしようすることもできる。
.quitか.qで抜ける。
データベースの操作
下記のコマンドでデータベースの操作をすることが可能
rubyでいうirbみたいなもの。
$rails c #consoleの略
irb(main):002:0> User.all #Userテーブルのデータを取得
User Load (0.7ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
irb(main):003:0> user = User.new #Userクラスのインスタンスを作成
=> #<User id: nil, name: nil, age: nil, created_at: nil, updated_at: nil>
irb(main):004:0> user.name = "Kiyosiro Imawano" #インスタンスに名前を代入
=> "Kiyosiro Imawano"
irb(main):005:0> user.age = 40 #インスタンスに年齢を代入
=> 40
irb(main):006:0> user.save #テーブルにデータを保存
(0.1ms) begin transaction
User Create (0.6ms) INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Kiyosiro Imawano"], ["age", 40], ["created_at", "2019-03-06 03:58:57.264789"], ["updated_at", "2019-03-06 03:58:57.264789"]]
(7.0ms) commit transaction
=> true
irb(main):007:0> User.all #Userテーブルのデータを取得
User Load (0.2ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Kiyosiro Imawano", age: 40, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 03:58:57">]>
IDのデータを取得
irb(main):013:0> User.find(1)
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Kiyosiro Imawano", age: 40, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 03:58:57">
データの更新
IDが1のデータを書き換える。
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Kiyosiro Imawano", age: 40, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 03:58:57">
irb(main):020:0> user.name = "Kensiro Kaneko"
=> "Kensiro Kaneko"
irb(main):021:0> user.age = 23
=> 23
irb(main):022:0> user.save
(0.1ms) begin transaction
User Update (0.5ms) UPDATE "users" SET "name" = ?, "age" = ?, "updated_at" = ? WHERE "users"."id" = ? [["name", "Kensiro Kaneko"], ["age", 23], ["updated_at", "2019-03-06 04:11:34.304540"], ["id", 1]]
(6.8ms) commit transaction
=> true
irb(main):023:0> User.all
User Load (0.2ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "Kensiro Kaneko", age: 23, created_at: "2019-03-06 03:58:57", updated_at: "2019-03-06 04:11:34">, #<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">]>
#書き換わった!!
Userテーブルのデータを削除
irb(main):030:0> User.all
User Load (5.3ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">]>
irb(main):031:0> user = User.find(2)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
=> #<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">
irb(main):032:0> user.destroy
(0.6ms) begin transaction
User Destroy (0.4ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 2]]
(1.0ms) commit transaction
=> #<User id: 2, name: "21", age: nil, created_at: "2019-03-06 04:02:37", updated_at: "2019-03-06 04:02:37">
irb(main):033:0> User.all
User Load (0.2ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation []>
ロードと削除を一緒に行うには
User.find(id).destroyとする。
Webページにデータを反映させる
データベースの作成
irb(main):051:0> sato = User.new(name: "Aki Sato", age: 25)
=> #<User id: nil, name: "Aki Sato", age: 25, created_at: nil, updated_at: nil>
irb(main):052:0> sato.save
(0.1ms) begin transaction
User Create (1.0ms) INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Aki Sato"], ["age", 25], ["created_at", "2019-03-06 12:48:00.277643"], ["updated_at", "2019-03-06 12:48:00.277643"]]
(6.6ms) commit transaction
=> true
irb(main):053:0> kaneki = User.new(name: "Ken Kaneki", age: 32)
=> #<User id: nil, name: "Ken Kaneki", age: 32, created_at: nil, updated_at: nil>
irb(main):054:0> kaneki.save
(0.1ms) begin transaction
User Create (1.1ms) INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Ken Kaneki"], ["age", 32], ["created_at", "2019-03-06 12:48:55.171055"], ["updated_at", "2019-03-06 12:48:55.171055"]]
(6.5ms) commit transaction
irb(main):004:0> imawano = User.new(name: "Kiyosiro Imawano", age: 50)
=> #<User id: nil, name: "Kiyosiro Imawano", age: 50, created_at: nil, updated_at: nil>
irb(main):005:0> imawano.save
(0.1ms) begin transaction
User Create (0.8ms) INSERT INTO "users" ("name", "age", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Kiyosiro Imawano"], ["age", 50], ["created_at", "2019-03-06 12:58:05.599302"], ["updated_at", "2019-03-06 12:58:05.599302"]]
(6.3ms) commit transaction
=> true
irb(main):006:0> User.all
User Load (1.0ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 4, name: "Aki Sato", age: 25, created_at: "2019-03-06 12:48:00", updated_at: "2019-03-06 12:48:00">, #<User id: 5, name: "Ken Kaneki", age: 32, created_at: "2019-03-06 12:48:55", updated_at: "2019-03-06 12:48:55">, #<User
class UsersController < ApplicationController
def index
#render plain: "Hello!,World!"
@num = 10 + 1
@users = User.all #作成したデータをインスタンス変数に代入
end
end
<p> Hello! World.</p>
<p>
<%= 10 + 1 %>
</p>
<p>
<%= @num %>
</p>
<ul>
<% @users.each do |user| %>
<li> <%= user.id%>, <%= user.name%>, <%= user.age %> </li>
<% end %>
#この記述で、ブラウザにデータベースの内容を反映させることができる。
</ul>