frontendmemo

このサイトは、「html、css、js、ruby,ツールなどについて、自分が覚えたこと、またはいつも忘れて調べることを書き溜め、それが結果といて勉強したての初心者の方や自分と同じような技術レベルの人の助けになることを目的とするWebログ」、略してブログです。挨拶→http://frontendmemo.hatenablog.com/entry/2016/06/25/115845

【初心者向け】Ruby on Railsでブログ作成手順をわかりやすくまとめてみた

スポンサードリンク


スポンサードリンク


まず基本的な作り方ですがルーター、コントローラー、ビューの順番で作成していきます。
自分のような初心者は何から触っていいかわからなくなると思います。
そんな時は心の中でルーター、コントローラー、ビュー。ルーター、コントローラー、ビューと唱えましょう。
そしてテーブルを作成する時はモデルです。

では早速作っていきましょう。
(間違ってるところはこっそり教えてください。。)

一覧画面の作成

ルーター

/config/routes.rb

get '/' => 'blogs#index' # 一覧画面

point
遷移はget
/はトップページ
blogsはコントローラー名
Indexはアクション名

コントローラー

ターミナルからコントローラーの作成

$ rails g controller blogs

/app/controllers/blogs_controller.rb

def index

end
まだ何も書きません。

ビュー

/app/views/blogs/index.html.erb

<p>Hello world</p>

確認

パス「/」でindex.html.erbの内容がエラーなくHello worldが表示される

モデルの作成

ターミナル

$rails g model article

マイグレーションファイル

マイグレーションファイルにカラムの追加
db/migrate/201XXXXXXXXXXXXX_create_tweets.rb

class CreateArticles < ActiveRecord::Migration
  def change
    create_table :articles do |t|
      t.text  :title
      t.text  :image
      t.text  :content
      t.timestamps
    end
  end
end

ターミナルでマイグレーションファイルの実行

$ rake db:migrate

確認

Phpmyadminにテーブルが追加されてる

投稿画面

ルーター

get '/new' => 'blogs#new' # 投稿画面

コントローラー

def new
        
end

ビュー

/app/views/blogs/new.html.erb

<div class="contents row">
  <a href="/">一覧にもどる</a>
  <%= form_tag('/complete', method: :post) do %>
    <h3>
      投稿する
    </h3>
    <p><input type="text" name="title" placeholder="タイトル"></p>
    <p><input type="text" name="image" placeholder="Image Url"></p>
    <textarea name="content" placeholder="記事を書いてください" rows="10" cols="50"></textarea>
    <p><input type="submit" value="投稿"></p>
  <% end %>
</div>

確認

/newで投稿画面が表示される

投稿機能

ルーター

  post '/complete' => 'blogs#create' # 投稿機能

コントローラー

    def create
        Article.create(blog_params)
    end
    private
    def blog_params
        params.permit(:title, :image, :content)
    end

point
テーブルにレコードを保存するためにはcreateメソッドを利用する
Articleテーブルからdataを取得するためにparamsの:title, :image, :content(カラム)をpermit(ストロングパラメーター)にして渡す
paramsはこのcreateアクションの中で使うことができるハッシュのようなものでbinding.pryすると投稿のキーと値が入っていることがわかる

ビュー

/app/views/blogs/create.html.erb
<div class="contents row">
  <div class="success">
    <h3>
      投稿が完了しました。
    </h3>
    <a class="btn" href="/">投稿一覧へ戻る</a>
  </div>
</div>

確認

実際に投稿したらパス投稿完了画面が表示
/completeでcreate.html.erbの内容が表示される
Phpmyadminにレコードが追加されてる

一覧画面に投稿を表示

ビュー

<ul class="list_article">
  <% @article.each do |article| %>
  <li>
    <h2><%= article.title %></h2>
    <% if article.image != "" %>
      <p><img src="<%= article.image %>"></p>
    <% end %>
    <p><%= article.content %></p>
    <p><%= article.created_at %></p>
  </li>
  <% end %>
</ul>

確認

一覧画面に投稿記事が表示

ログイン機能

Gemfile

gem 'devise'

ターミナル

$ bundle install

サーバーの再起動

rails s -p $PORT -b $IP

deviseの設定ファイルを作成

$ rails g devise:install

deviseでモデルを作成

$ rails g devise user
$ rake db:migrate

確認

Phpmyadminにuserテーブルが出来ているか確認

ターミナルでニックネームカラムの追加

$ rails g migration AddNicknameToUsers nickname:string
$ rake db:migrate

確認

ニックネームカラムが追加されてるか確認

ルーター

 post '/login' => 'blogs#login' # ログイン画面

コントローラ

リダイレクト

index ページを除いてログインしていなければindexページにリダイレクトさせる

class BlogsController < ApplicationController
  before_action :move_to_index, except: :index
private
    def move_to_index
      redirect_to action: :index unless user_signed_in?
    end

point
他から呼び出したくないメソッドはprivateにする

ログイン画面

ターミナル

$ rails g devise:views

ビュー

/app/views/devise/sessions/new.html.erb

<h2>ログイン</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%= f.label :メールアドレス %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>
  <div class="field">
    <%= f.label :パスワード %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>
  <% if devise_mapping.rememberable? -%>
    <div class="field">
      <%= f.check_box :remember_me %>
      <%= f.label :remember_me %>
    </div>
  <% end -%>
  <div class="actions">
    <%= f.submit "ログイン" %>
  </div>
<% end %>


/app/views/devise/registrations/new.html.erb

<h2>新規登録</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>
  <div class="field">
    <%= f.label :ニックネーム %> <em></em><br />
    <%= f.text_field :nickname, autofocus: true %>
  </div>
  <div class="field">
    <%= f.label :メールアドレス %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>
  <div class="field">
    <%= f.label :パスワード %>
    <% if @minimum_password_length %>
    <em>(最小<%= @minimum_password_length %>文字)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>
  <div class="field">
    <%= f.label :パスワード確認用 %><br />
    <%= f.password_field :password_confirmation, autocomplete: "off" %>
  </div>
  <div class="actions">
    <%= f.submit "登録" %>
  </div>
<% end %>

/app/views/devise/sessions/new.html.erb

<h2>ログイン</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%= f.label :メールアドレス %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :パスワード %><br />
    <%= f.password_field :password, autocomplete: "off" %>
  </div>

  <% if devise_mapping.rememberable? -%>
    <div class="field">
      <%= f.check_box :remember_me %>
      <%= f.label :remember_me %>
    </div>
  <% end -%>

  <div class="actions">
    <%= f.submit "ログイン" %>
  </div>
<% end %>
<div class="box_title"><span>point</span></div><div class="box">registrationsは新規登録
sessionsはログイン</div>

コントローラー

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
end

point
追加のパラメーターを許可したい場合は、application_controllerにおいてbefore_actionにconfigure_permitted_parametersメソッドを設定します。
devise_parameter_sanitizer.permit(:ストロングパラメーターを追加したいアクション名, keys: [:追加するキー])

モデル

/app/models/article.rb

class Article < ActiveRecord::Base
    belongs_to :user
end
<div class="box_title"><span>point</span></div><div class="box">記事は必ずユーザーと紐づいているのでbelongs_to :user</div>

/app/models/user.rb

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
         has_many :articles
end

point
一つのuserに対して記事は複数のためhas_many :articles(1対多)

ビュー

/app/views/layouts/application.html

<body>
  <% if user_signed_in? %>
  <p class="name">ユーザー:<%= current_user.nickname %>さん</p>
  <ul class="nav">
    <li><a href="/new">新規投稿</a></li>
    <li><%= link_to "ログアウト", destroy_user_session_path, method: :delete %></li>
  </ul>
  <% else %>
  <ul class="nav">
    <li><%= link_to "ログイン", new_user_session_path, class: 'post' %></li>
    <li><%= link_to "新規登録", new_user_registration_path, class: 'post' %></li>
  </ul>
  <% end %>
<%= yield %>

point
ログインで分岐
destroy_user_session_pathはルーティングのパスが入る変数のこと。コントローラやビューなどで呼び出すことで、prefixに入っているパスやURL情報を取得できるようになる。
deviseでは、current_userというヘルパーメソッドを使用することができる。
ログイン中のユーザーの情報として登録されている各カラムの値を取得することができる。

ターミナル

Articleテーブルにuser_idを追加

$ rails g migration AddUserIdToArticles user_id:integer
$ rake db:migrate

確認

phpmyadminにUserIdが追加されてる

phpmyadmin

phpmyadminのuser_idがNULLになっていれば1などを入力する

表示順を変える

コントローラー

    def index
        @article = Article.all.order("id DESC")
    end

削除画面

ルーター

delete '/:id' => 'blogs#destroy' #削除機能

コントローラー

    def destroy
        article = Article.find(params[:id])
        article.destroy if article.user_id === current_user.id
    end

ビュー

index.html.erb

    <% if user_signed_in? %>
      <ul>
        <li><%= link_to '削除', "/#{article.id}", method: :delete %></li>
      </ul>
    <% end %>

destroy.html.erb

<p>削除しました</p>
<%= link_to '一覧へ戻る/', "/" %>

編集画面

ルーター

get '/:id/edit' => 'blogs#edit' #編集画面 

コントローラー

    def edit
        @article = Article.find(params[:id])
    end

ビュー

    <% if user_signed_in? %>
      <ul>
        <li><%= link_to '編集', "/#{article.id}/edit", method: :get %></li>
        <li><%= link_to '削除', "/#{article.id}", method: :delete %></li>
      </ul>
    <% end %>

edit.html.erb

<div class="contents row">
  <a href="/">一覧にもどる</a>
  <%= form_tag("/#{@article.id}", method: :patch) do %>
    <h3>
      編集する
    </h3>
    <p><input type="text" name="title" placeholder="タイトル" value="<%= @article.title %>"></p>
    <p><input type="text" name="image" placeholder="Image Url" value="<%= @article.image %>"></p>
    <textarea name="content" placeholder="記事を編集してください" rows="10" cols="50"><%= @article.content %></textarea>
    <p><input type="submit" value="投稿"></p>
  <% end %>
</div>

編集機能

ルーター

  patch '/:id' => 'blogs#update' #編集機能 
<div class="box_title"><span>point</span></div><div class="box">
patchを使用する</div>

コントローラー

   def update
        article = Article.find(params[:id])
        article.update(blog_params) if article.user_id == current_user.id
    end

ビュー

update.html.erb

<p>更新しました</p>
<%= link_to '一覧へ戻る/', "/" %>

あとはcssを適宜調整して以上で完成するはずです!

f:id:funclur:20180703113922p:plain

お疲れ様でした!