【未経験プログラミング】twitterクローン【34日】
Gravatar
ブログやコメントを投稿する際に名前の側に表示される画像です
app/helpers/users_helper.rb
メソッドを定義する
module UsersHelper
def gravatar_url(user, options = {size: 80})
gravatar_id = Digest::MD5::hexdigest(user.email.downcase)
size = options[:size]
"https://secure.gravatar.com/avatar/#{gravatar_id}?s=#{size}"
end
end
users#show
contorller
app/controllers/users_controller.rbにメソッドを作成
id を
def show
@user = User.find(params[:id])
end
id
が指定されているので、 User.find(params[:id])
によって1つだけ取得します。そのため、 @user
変数も単数形の命名にしています。GETメソッドやPOSTメソッドなどや、URL のパラメータやデータは全て params
に代入されて受け取れます。
app/views/users/show.html.erb
<!--両端揃えタブ・メニューの場合は、ul要素のclass属性にnav nav-tabs nav-justifiedを指定する。-->bootstrap3日本語リファレンスより↓
http://bootstrap3.cyberlab.info/components/navs.html
7.5app/views/users/new.html.erb
users#new
def new
@user = User.new
end
class="text-center" textを真ん中に。
calss="row" 1列のカラム全部
class="form-group"
http://bootstrap3.cyberlab.info/css/forms.html
class="form-control" 幅がwidth: 100%;になる。
form部分はemail,password,nameの3箇所分作成
最後に投稿部分作成
<%= f.submit 'Sign up', class* 'btn btn-primary btn-block' %>
<% end %>
7users#create
Contoroller
redirect_to と render の違い
redirect_to @user
は、 処理を users#show のアクションへと強制的に移動させるもので、create アクション実行後に更に show アクションが実行され、show.html.erb が呼ばれます。render :new
は、単にmessages/new.html.erb を表示するだけです(messages#newのアクションは実行しない)。
createの部分はストロングパラメーターを使う必要がある。(セキュア)
params
params.require
params.require.permit
view
save成功時にはredirect_to_ @userに行き駄目ならrender :newに行く。
createに対応するviewはいらないが、エラーメッセージは実装する必要がある。
<%= render 'layoutes/error_messages', model: f.object %>
トップページにユーザーリンク登録
sign up now というボタンをつける。
app/views/toppages/index.html.erb
class center jumbotron 幅100%にする
class text-center
class btn btn-lg btn-primary ボタン設置 ボタン大 ボタンの色プライマリー(青)
ログイン機能
HTTPはステートレス通信
ステート(状態)レス(無い)
ログイン情報はブラウザ内部とサーバ(rails)に保存される。
ブラウザがサーバにアクセスするたびに毎回HTTPで送受信している。
ブラウザがもっている情報はCookieとして保存
rails側はSessionとして保存している。 =Cookieとサーバーのsessionはお互いに称号している。
Router
config/routes.rb
railsが用意しているsessionシステムを使う。
get 'login', to: 'sessions#new'
post 'login', to: 'sessions#create'
delete 'logout', to: 'sessions#destroy'
rails g controller sessions new create destroy
[def new def create def destroy]
ログインフォームを作る。
対応するModelが無いのでコードの追加はなし
def new
end
app/views/sessions/new.html.erb
ログインの為アドレスとパスワードでログイン
ナビバーにログインリンクを追加する。
<li><%= link_to 'Login', login_path %><li>
sessions#create
sessions#create が実質的にログイン処理を担当するアクションになります。
session[:user_id]にログインユーザーのidが代入された時点でログイン完了となる。
controller
app/controllers/sessions_controller.rb
def create
form_for(:session, ...
とした場合でも Model のインスタンスを指定したときと同様に、 params
にフォームデータは代入されています
取り出すときはparams[:session][:email]
のように二段階で指定して取得できます。
これを利用してemail = params[:session][:email].downcase
フォームデータを小文字で受け取る、
次にlogin(email,password ログイン可能なメソッドが定義されている、
このメソッドはログイン成否でtrue、faleseを返す仕様。
次
userのpasswordがあっているか@user.authenticate(password)
で確認している。
if @user && @user.authenticate(password)
はemail,passwordの組み合わせが間違っていた場合にログインできないよう仕様になっている。
session[:user_id] = @user.id
によってブラウザにはCookieとしてサーバーにはSessionとしてログイン状態が保持される。
view
ログイン後のトップページ
app/views/toppages/index.html.erb
login_in? current_userは仮のメソッド
ログイン後のナビバー
app/views/layouts/_navbar.html.erb
ここの書き方勉強する。
8.5
ログイン後のナビバー
class="collapse navbar-collapse" id="bs-example-navbar-collapse-1
class="dropdown' プルダウンみたいなやつ
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><%= current_user.name %> <span class="caret"></span></a>
dropdown-toggleクラスを使いdata-toggle="dropdown"属性のボタンまたはリンクを使用する。
Helper
rails g helper sessions で作成
app/helpers/sessions_helper.rb
@current_user ||= User.find_by(id: session[:user_id])
!!current_user
||=
という代入演算子を使っている。
if @current_user.nil?
@current_user = User.find_by(id: session[:user_id])
else
@current_user
end
と同じ意味になる。
current_userメソッド:サインインしているユーザーか取得する。
user_sessionメソッド:ユーザーのセッション情報にアクセスする
user_signed_in?メソッド:ユーザーがサインイン済かどうか判定する。
find(id)とfind_by(id)の違い
ユーザーが見つからなかった時のエラーが発生するか
/users/100000000
nilだけを返すか、エラーページが表示されログインができなくなる。
ログアウトの実装
Controller
def destroy
session[:user_id] = nil
flash[:success] = 'ログアウトしました'
redirect_to_root_url
end
ログイン要求処理
indexshowはログインしていないユーザーに見せたくない、users#index, users#show のアクションには必ず事前にログイン認証を確認するような処理を追加します。
app/controllers/application_controller.rb
def require_user_logged_in
unless logged_in?
redirect_to_root_url
end
また、ここで Helper に定義していた logged_in?
を使用していますが、実は Controller から Helper のメソッドを使うことはデフォルトではできません。そのため、ApplicationController
に include SessionsHelper
を追加します。
before_action :require_user_logged_in, only: [:index, :show]
before_actionではonly:で指定されたアクションに対して事前処理を設定できる。
今回は index
, show
において、事前に require_user_logged_in
が実行されるようになります
require_user_logged_in
はログイン状態を確認し、ログインしていれば何もせず、ログインしていなければログインページへ強制的にリダイレクトさせます。
これで会員制のサービスを開発することができる。
投稿機能
Model
ユーザーの投稿をMicropost モデル名で作成していく。
UserとMicropostは一対多
rails g model Micropost content:string user:references
rails db:migrate
Micropost Model
app/models/micropost.rb
class Micropost < ApplicationRecord
belongs_to :user
end
既に belongs_to :user
が書かれています。これは、User と Micropost の一対多を表現しています。このコードのおかげで、micropost.user
とすると、この micropost
インスタンスを持っている User を取得することができます。
【未経験プログラミング】twitterクローン【32日】
TOPページ作成
ユーザー登録機能作成
Model データベースで永久保存する必要がある。
必要なのはユーザー名、メールアドレス、ログイン認証の為のユーザーパス(暗号化される)
それぞれ name mail password_digest
暗号化された文字をダイジェストと言う。
モデルとマイグレーションファイルを作成。
rails g model User name:string email:string password_digest:string
db/migrateファイル確認。3箇所カラム問題なしであればマイグレーション
rails db:migrate
has_secure_passwordを記入でパスワードが有効
あまり深く考える必要はありません。password_digest
カラムを用意し、モデルファイルに has_secure_password
を記述すれば、ログイン認証のための準備を良しなにはからってくれると覚えておきましょう。
gemファイル
bcryptをインストール →パスワードダイジェストが有効になった。
各カラムのバリテーションを行う
name
validates :name, presence: true, length: { maximum: 50 }
email
validates :email, presence: true, length: { maximum: 255 },
format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i },
uniqueness: { case_sensitive: false }
case_sensitive: false 大文字小文字 区別しない
before_save { self.email.downcase! } 保存後は小文字で保存されている。
7.2
Router
get 'signup', to: 'users#new'
resources :users, only: [:index, :show, :new, :create]
また、既に resources
で users#new
は設定されているのに、 get 'signup', to: 'users#new'
をわざわざルーティングに追加したのは、ユーザの新規登録 URL を /signup
にしたかったからです。 resources :users
で生成される URL である /users/new
は少し格好悪く思えます。そんなときには get 'signup'
のように個別に設定することで解決します。また、 resources
に :new
も追加しているので /users/new
でも新規登録ページが表示されます。それが嫌な場合には only
内の :new
は削除します。
.7.3users#index
UsersContoroller作成:rails g controller users index show new create
app/views/users/create.html.erb は不要の為削除
View フォロー/フォロワーの表示にusers/_users.html.erb使用するので先にパーシャルをしている。
<%= render 'users', users: @users %>
app/views/users/_users.html.erb
gravatar_urlは画像表示を変更するメソッド
定義されていない為Helper実装までここはエラーがでる。
・rails g helper users →app/helpers/users_helper.rb
【未経験プログラミング】bootstrap【28日-29日】
viewport ありなしで表示の縮小しないようになる。<モバイル
<meta name="viewport" content="width=device-width, initial-scale=1">
グリッド
横幅いっぱいを12カラム
隙間をあける場合
"col-sm-offset-2 col-sm-5"
メディアエクリ
特定の表示環境に対してだけCSSを適用させることができる。
表示幅500px未満では黒(#000)、表示幅500pxでは赤(#f00)
background-color: #000;
@media (min-width: 500px) {body {background-color:#f00;} }
フォーム <input type="text" class="form-control">
のようにinputに class="form-control"を追加すると青い枠が適用される。
【未経験プログラミング】Controlloer【27日】
cdapp/controllers/messages_controller.rにRESTfulなルーティングを書く。
def index ~end
def show ~end・・・・・・def destroy end
Controller 内でルーティングと同じ名前のメソッド名として定義すれば、対応させられます
Viewの構成
Viewは基本HTMLを記述する。
HTMLを書くと共通部分が出てくる。共通としてまとめないと毎回色々なファイルを修正する必要がでてくる。
app/views/layouts/application.html.erbに共通部分記載
yield … 各Actionに対するViewを生成します
例えば/messages とルーティングにブラウザでアクセスするとmessagecontrollerのindexアクションが呼び出され→app/views/layouts/application.html.erbが呼び出される
messages#indexに7つのルーティングを実装する。
Rails では ActiveRecord と呼ばれるライブラリを利用することで、SQL を一切書かずにレコードの CRUD 操作を行うことができます
モデルレコードはCRUD操作をする。
all 全てのレコードを取得する
new 新規レコードのためのモデルインスタンスを作成する
find idを指定して検索
find_by id以外でも指定して検索
where 検索条件を文字列、配列、ハッシュのいずれかの方法で与えることができる
first 最初のレコードを1件だけ取得する
save レコードの作成
update, save データの更新
destroy データの削除
indexをコーディング
indexアクションの役割はMessageモデルのレコード表示です。
一覧表示をするので Message.all コーディング→ @messages = Message.all
@messagesはview側(index.html.erb)で使うことでControllerからViewへ変数を渡す事ができる。
【未経験プログラミング】ModelからRoutes【27日】
メッセージボード
・ HTTPメソッドは8つ:GET,POST,PUT,DELETE,HEAD,OPTIONS,TRANCE,CONNECT
そのうちCRUD:
CREATE:post(あらたらしいURLの作成)/put 子リソースの作成、データの追加、
READ:get リソースの取得
UPDATE:put リソースの更新、追加
DELETE:delete リソース削除
ローカルPCのファイルシステムで考えるとわかりやすく、
POSTは「新しいファイルを生成」。
PUTはファイルの置き換え(存在しなければそのまま配置される)。
PATCHはファイルを開いて中身を更新。
DELETEはファイルを削除。
・リソースとはWEB上で表示されるものすべて。
・WebアプリケーションはURLに対してHTTPリクエストメソッドを送りリソースを操作する。
Webアプリケーションフレイムワークとは Web開発における共通処理をまとめあげたものがWebアプリケーションフレイムワーク。
・ライブラリとフレイムワーク:
HTTPメソッド→Rails(Router→controller→model→DB→model→controller→view→Webブラウザ
Router
は、URLのルーティングを一元管理してるController
は、HTTPリクエストの処理を担っているView
は、HTTPレスポンスとして返されるWebページ
上記3つはModelと違い関係性が高い
- Model(リソースであり操作対象である。)
- Router
- ルーティング毎に
1.1. Controller
1.2. View
all(全レコードを取得)
new(新規レコードの為のモデルインスタンスを作成)
find(idを指定して検索)
find_by id以外でも指定して検索、
where 検索条件を文字列、配列、ハッシュのいずれかの方法で与えることができる、first 最初のレコードを1件だけ取得する、
saveレコードの作成
updateレコードのi更新
dstroyデータ削除
コードでデータベースを操作できる事をORMという。ActiveRecordはORMをサポートしている。messe
Routes.rb → messages_controller.rb →messagesフォルダ
ソースに対する CRUD のための4つのルーティング
Web アプリケーションは、ユーザが HTTP リクエストの4つの CRUD メソッド(POST, GET, PUT, DELETE)を使って、Web上のリソースを操作できるアプリケーションでした。
リソース1つのCRUDに対応するHTTPリクエストはGET POST PUT DELETEです。
get 'messages/:id', to: 'messages#show'
post 'messages', to: 'messages#create'
put 'messages/:id', to: 'messages#update'
delete 'messages/:id', to: 'messages#destroy'
:idはURLのmessages/1 の/1部分に対してのCRUDが実行できる。`POSTは新規URL作成の為書いてない。特定の何々にアクセスする(show)or更新する(put)or削除する(delete)
うえ4つは一覧ページ(index)がないため詳細ページにたどり着けない。
もちろんURL直接打てばいける。その為補助が必要
showには→:get 'messages', to: 'messages#index' 詳細ページの前のindex
createには→:get 'messages/new', to: 'messages#new 新規作成用のフォームpg
updateには→:get 'messages/:id/edit', to: 'messages#edit' データを渡す必要
上記7個をを省略
resources :messages
#RESTful なルーティングと呼ばれる=CRUD操作に必要な7種類のアクションです。(index, show, new, create, edit, update, destroy)#
root to: 'messages#index'
root
メソッドを使用することで、Railsがルート'/'
とすべき場所を指定できます。
そのため→root GET / messages#index が追加される。
【未経験プログラミング】Railsのタスクアプリを作成する。【24日~26日】
エラーメッセージを表示
バリデーション
フォームはnew、editにある。
validates :status, presence: true, length: { maximum: 10 }
ページネーション:HPの2ページ目にいくやつ
gemをインストールする:gemfilを開き 最下段に gem 'いれたいgem名'
ターミナルでbundle install
def index
@tasks = Task.all .page(params[:page]) ←追加TOPページに表示するって意味かと .per(25)がデフォルト 数字を変えられる。
<h1>タスク一覧</h1>
<ul>
<% @tasks.each do |task| %>
<li><%= link_to task.id, task %> : <%= task.status %>> <%= task.content %></li>
<% end %>
</ul>
<%= paginate @tasks %> bodyの下段にnextやlastが表示される。