静的型付け言語原理主義者によるRailsチュートリアル(第14章)

image

第14章 ユーザーをフォローする

  • 他のユーザーをフォロー/フォロー解除できるソーシャルな仕組みの追加と、フォローしているユーザーと投稿をステータスフィードに表示する機能を追加する

14.1 Relationship モデル

  • has_many の関連付けを用いて「1人のユーザーが複数のユーザーを has_many としてフォローし、1人のユーザーにフォロワーがいることを has_many で表す」という方法で実装はできそうだが、問題が発生する
    • has_many through で解決

14.1.1 データモデルの問題(および解決策)

  • followingfollowers の関係性をリレーションシップというモデルで表現する

    rails generate model Relationship follower_id:integer followed_id:integer
  • 今後 follower_idfollowed_id で頻繁に検索することになるので、それぞれのカラムにインデックスを追加する

    class CreateRelationships < ActiveRecord::Migration[5.0]
    def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id
    
      t.timestamps
    end
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    add_index :relationships, [:follower_id, :followed_id], unique: true
    end
    end
  • follower_idfollowed_id の組み合わせが必ずユニークであることを保証する仕組みである複合キーインデックスを使用している

    • ユーザーが同じユーザーを2回以上フォローすることを防ぐ
  • relationship テーブルを作成するためにいつもの通りマイグレーション

14.1.2 User/Relationship の関連付け

  • 1人のユーザーには has_many のリレーションシップがあり、このリレーションシップは2人のユーアー間の関係なので、フォローしているユーザーとフォロワーの両方に属する( belongs_to
  • 能動的関係に対して1対多( has_many )の関連付けを実装する

    class User < ApplicationRecord
    has_many :microposts, dependent: :destroy
    has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
    .
    .
    .
    end
  • リレーションシップ/フォロワーに対して belongs_to の関連付けを追加する

    class Relationship < ApplicationRecord
    belongs_to :follower, class_name: "User"
    belongs_to :followed, class_name: "User"
    end

14.1.3 Relationship のバリデーション

  • Relationship モデルのバリデーションをテストする

    require 'test_helper'
    
    class RelationshipTest < ActiveSupport::TestCase
    
    def setup
    @relationship = Relationship.new(follower_id: users(:michael).id,
                                     followed_id: users(:archer).id)
    end
    
    test "should be valid" do
    assert @relationship.valid?
    end
    
    test "should require a follower_id" do
    @relationship.follower_id = nil
    assert_not @relationship.valid?
    end
    
    test "should require a followed_id" do
    @relationship.followed_id = nil
    assert_not @relationship.valid?
    end
    end
  • Relationship モデルに対してバリデーションを追加する

    class Relationship < ApplicationRecord
    belongs_to :follower, class_name: "User"
    belongs_to :followed, class_name: "User"
    validates :follower_id, presence: true
    validates :followed_id, presence: true
    end
  • User 用の fixture ファイルと同様に、生成された Relationship 用の fixutre ではマイグレーションで成約させた一意性を満たすことができないため、現時点では生成された Relationship 用の fixutre は空にしておく

14.1.4 フォローしているユーザー

  • has_many through を使って User モデルに following の関連付けを追加する

    class User < ApplicationRecord
    has_many :microposts, dependent: :destroy
    has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
    has_many :following, through: :active_relationships, source: :followed
    .
    .
    .
    end
  • これによりフォローしているユーザーを following という配列のように扱えるようになる

  • TDD で followunfollow というメソッドを作る

    • following? メソッドであるユーザーを未フォローであることを確認
    • follow メソッドでそのユーザーをフォロー
    • following? メソッドでフォロー中になったことを確認
    • unfollow メソッドでフォロー解除を確認

      • という手順で following 関連のメソッドをテストする

        class UserTest < ActiveSupport::TestCase
        .
        .
        .
        test "should follow and unfollow a user" do
        michael = users(:michael)
        archer  = users(:archer)
        assert_not michael.following?(archer)
        michael.follow(archer)
        assert michael.following?(archer)
        michael.unfollow(archer)
        assert_not michael.following?(archer)
        end
        end
  • 上記テストを参考にして following 関連のメソッドを実装する

    class User < ApplicationRecord
    .
    .
    .
    def feed
    .
    .
    .
    end
    
    # ユーザーをフォローする
    def follow(other_user)
    following << other_user
    end
    
    # ユーザーをフォロー解除する
    def unfollow(other_user)
    active_relationships.find_by(followed_id: other_user.id).destroy
    end
    
    # 現在のユーザーがフォローしてたらtrueを返す
    def following?(other_user)
    following.include?(other_user)
    end
    
    private
    .
    .
    .
    end
  • これでテストが通る

14.1.5 フォロワー

  • user.following メソッドと対になる user.followers メソッドを追加する

    • active_relationship テーブルを再利用し、受動的関係を使って実装する

      class User < ApplicationRecord
      has_many :microposts, dependent: :destroy
      has_many :active_relationships,  class_name:  "Relationship",
                                 foreign_key: "follower_id",
                                 dependent:   :destroy
      has_many :passive_relationships, class_name:  "Relationship",
                                 foreign_key: "followed_id",
                                 dependent:   :destroy
      has_many :following, through: :active_relationships,  source: :followed
      has_many :followers, through: :passive_relationships, source: :follower
      .
      .
      .
      end
  • followers.include? メソッドを使って followers に対するテストを追加する

    require 'test_helper'
    
    class UserTest < ActiveSupport::TestCase
    .
    .
    .
    test "should follow and unfollow a user" do
    michael  = users(:michael)
    archer   = users(:archer)
    assert_not michael.following?(archer)
    michael.follow(archer)
    assert michael.following?(archer)
    assert archer.followers.include?(michael)
    michael.unfollow(archer)
    assert_not michael.following?(archer)
    end
    end

14.2 [Follow] の Web インターフェイス

  • フォロー/フォロー解除の基本的なインターフェイスを実装し、フォローしているユーザーと、フォロワーにそれぞれ表示用のページを作成する

14.2.1 フォローのサンプルデータ

  • サンプルデータを自動作成する rails db:seed を使って DB にサンプルデータを登録できると便利なので、サンプルデータに following/follower の関係性を追加する

    # ユーザー
    User.create!(name:  "Example User",
             email: "example@railstutorial.org",
             password:              "foobar",
             password_confirmation: "foobar",
             admin:     true,
             activated: true,
             activated_at: Time.zone.now)
    
    99.times do |n|
    name  = Faker::Name.name
    email = "example-#{n+1}@railstutorial.org"
    password = "password"
    User.create!(name:  name,
               email: email,
               password:              password,
               password_confirmation: password,
               activated: true,
               activated_at: Time.zone.now)
    end
    
    # マイクロポスト
    users = User.order(:created_at).take(6)
    50.times do
    content = Faker::Lorem.sentence(5)
    users.each { |user| user.microposts.create!(content: content) }
    end
    
    # リレーションシップ
    users = User.all
    user  = users.first
    following = users[2..50]
    followers = users[3..40]
    following.each { |followed| user.follow(followed) }
    followers.each { |follower| follower.follow(user) }
  • DB 上のサンプルデータを作り直して完了

14.2.2 統計と [Follow] フォーム

  • サンプルユーザーにフォローしているユーザーとフォロワーができたので、プロフィールページと Home ページを更新してこれを反映する
    • 最初にプロフィールページと Home ページにフォローしているユーザーとフォロワーの統計情報表示用のパーシャルを作成する
    • 次にフォロー用とフォロー解除用のフォームを作成する
    • 最後にフォローしているユーザーの一覧とフォロワーの一覧を表示するページを作成する
  • 統計情報の表示はリンクなっており、専用の表示ページに移動できる

    • Users コントローラに following アクションと followers アクションを追加してルーティングを実装する

      Rails.application.routes.draw do
      root   'static_pages#home'
      get    '/help',    to: 'static_pages#help'
      get    '/about',   to: 'static_pages#about'
      get    '/contact', to: 'static_pages#contact'
      get    '/signup',  to: 'users#new'
      get    '/login',   to: 'sessions#new'
      post   '/login',   to: 'sessions#create'
      delete '/logout',  to: 'sessions#destroy'
      resources :users do
      member do
      get :following, :followers
      end
      end
      resources :account_activations, only: [:edit]
      resources :password_resets,     only: [:new, :create, :edit, :update]
      resources :microposts,          only: [:create, :destroy]
      end
  • ルーティングを定義したので、フォロワーの統計情報を表示するパーシャルを実装する

    <% @user ||= current_user %>
    <div class="stats">
    <a href="<%= following_user_path(@user) %>">
    <strong id="following" class="stat">
      <%= @user.following.count %>
    </strong>
    following
    </a>
    <a href="<%= followers_user_path(@user) %>">
    <strong id="followers" class="stat">
      <%= @user.followers.count %>
    </strong>
    followers
    </a>
    </div>
  • 統計情報パーシャルができあがったので、 Home ページにフォロワーの統計情報を表示する

    <% if logged_in? %>
    <div class="row">
    <aside class="col-md-4">
      <section class="user_info">
        <%= render 'shared/user_info' %>
      </section>
      <section class="stats">
        <%= render 'shared/stats' %>
      </section>
      <section class="micropost_form">
        <%= render 'shared/micropost_form' %>
      </section>
    </aside>
    <div class="col-md-8">
      <h3>Micropost Feed</h3>
      <%= render 'shared/feed' %>
    </div>
    </div>
    <% else %>
    .
    .
    .
    <% end %>
  • SCSS を追加してスタイルを整えて完成

14.2.2 統計と [Follow] フォーム

  • サンプルユーザーにフォローしているユーザーとフォロワーができたので、プロフィールページと Home ページを更新してこれを反映する
    • 最初にプロフィールページと Home ページにフォローしているユーザーとフォロワーの統計情報表示用のパーシャルを作成する
    • 次にフォロー用とフォロー解除用のフォームを作成する
    • 最後にフォローしているユーザーの一覧とフォロワーの一覧を表示するページを作成する
  • 統計情報の表示はリンクなっており、専用の表示ページに移動できる

    • Users コントローラに following アクションと followers アクションを追加してルーティングを実装する

      Rails.application.routes.draw do
      root   'static_pages#home'
      get    '/help',    to: 'static_pages#help'
      get    '/about',   to: 'static_pages#about'
      get    '/contact', to: 'static_pages#contact'
      get    '/signup',  to: 'users#new'
      get    '/login',   to: 'sessions#new'
      post   '/login',   to: 'sessions#create'
      delete '/logout',  to: 'sessions#destroy'
      resources :users do
      member do
      get :following, :followers
      end
      end
      resources :account_activations, only: [:edit]
      resources :password_resets,     only: [:new, :create, :edit, :update]
      resources :microposts,          only: [:create, :destroy]
      end
  • ルーティングを定義したので、フォロワーの統計情報を表示するパーシャルを実装する

    <% @user ||= current_user %>
    <div class="stats">
    <a href="<%= following_user_path(@user) %>">
    <strong id="following" class="stat">
      <%= @user.following.count %>
    </strong>
    following
    </a>
    <a href="<%= followers_user_path(@user) %>">
    <strong id="followers" class="stat">
      <%= @user.followers.count %>
    </strong>
    followers
    </a>
    </div>
  • 統計情報パーシャルができあがったので、 Home ページにフォロワーの統計情報を表示する

    <% if logged_in? %>
    <div class="row">
    <aside class="col-md-4">
      <section class="user_info">
        <%= render 'shared/user_info' %>
      </section>
      <section class="stats">
        <%= render 'shared/stats' %>
      </section>
      <section class="micropost_form">
        <%= render 'shared/micropost_form' %>
      </section>
    </aside>
    <div class="col-md-8">
      <h3>Micropost Feed</h3>
      <%= render 'shared/feed' %>
    </div>
    </div>
    <% else %>
    .
    .
    .
    <% end %>
  • SCSS を追加してスタイルを整えて完成

  • フォロー/フォロー解除フォームのパーシャルも作成しておく

    <% unless current_user?(@user) %>
    <div id="follow_form">
    <% if current_user.following?(@user) %>
    <%= render 'unfollow' %>
    <% else %>
    <%= render 'follow' %>
    <% end %>
    </div>
    <% end %>
  • 上記コードは followunfollow のパーシャルに作業を振っているだけ

  • パーシャルでは Relationship リソース用の新しいルーティングが必要

    Rails.application.routes.draw do
    root                'static_pages#home'
    get    'help'    => 'static_pages#help'
    get    'about'   => 'static_pages#about'
    get    'contact' => 'static_pages#contact'
    get    'signup'  => 'users#new'
    get    'login'   => 'sessions#new'
    post   'login'   => 'sessions#create'
    delete 'logout'  => 'sessions#destroy'
    resources :users do
    member do
      get :following, :followers
    end
    end
    resources :account_activations, only: [:edit]
    resources :password_resets,     only: [:new, :create, :edit, :update]
    resources :microposts,          only: [:create, :destroy]
    resources :relationships,       only: [:create, :destroy]
    end
  • フォロー用のパーシャル(ユーザーをフォローするフォーム)

    <%= form_for(current_user.active_relationships.build) do |f| %>
    <div><%= hidden_field_tag :followed_id, @user.id %></div>
    <%= f.submit "Follow", class: "btn btn-primary" %>
    <% end %>
  • フォロー解除用のパーシャル(ユーザーをフォロー解除するフォーム)

    <%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
             html: { method: :delete }) do |f| %>
    <%= f.submit "Unfollow", class: "btn" %>
    <% end %>
  • 最後にプロフィールページにフォロー用フォームとフォロワーの統計情報を追加する

    <% provide(:title, @user.name) %>
    <div class="row">
    <aside class="col-md-4">
    <section class="user_info">
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
    </aside>
    <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
    </div>
    </div>

14.2.3 [Following] と [Followers] ページ

  • フォローしているユーザーを表示するページとフォロワーを表示するページは、いずれもプロフィールページとユーザー一覧ページを合わせたような作りになるという点で似ている
  • まずはフォローしているユーザーのリンクとフォロワーのリンクを動くようにする

    • どちらのページでもログインを要求する
    • まずはテストから

      require 'test_helper'
      
      class UsersControllerTest < ActionDispatch::IntegrationTest
      
      def setup
      @user = users(:michael)
      @other_user = users(:archer)
      end
      .
      .
      .
      test "should redirect following when not logged in" do
      get following_user_path(@user)
      assert_redirected_to login_url
      end
      
      test "should redirect followers when not logged in" do
      get followers_user_path(@user)
      assert_redirected_to login_url
      end
      end
  • Users コントローラに2つの新しいアクションを追加する必要がある

    • ルーティングに基づいた following 及び followers アクション

      class UsersController < ApplicationController
      before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
                                      :following, :followers]
      .
      .
      .
      def following
      @title = "Following"
      @user  = User.find(params[:id])
      @users = @user.following.paginate(page: params[:page])
      render 'show_follow'
      end
      
      def followers
      @title = "Followers"
      @user  = User.find(params[:id])
      @users = @user.followers.paginate(page: params[:page])
      render 'show_follow'
      end
      
      private
      .
      .
      .
      end
  • フォローしているユーザーとフォロワーの両方を表示する show_follow ビューを作成する

    <% provide(:title, @title) %>
    <div class="row">
    <aside class="col-md-4">
    <section class="user_info">
      <%= gravatar_for @user %>
      <h1><%= @user.name %></h1>
      <span><%= link_to "view my profile", @user %></span>
      <span><b>Microposts:</b> <%= @user.microposts.count %></span>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
      <% if @users.any? %>
        <div class="user_avatars">
          <% @users.each do |user| %>
            <%= link_to gravatar_for(user, size: 30), user %>
          <% end %>
        </div>
      <% end %>
    </section>
    </aside>
    <div class="col-md-8">
    <h3><%= @title %></h3>
    <% if @users.any? %>
      <ul class="users follow">
        <%= render @users %>
      </ul>
      <%= will_paginate %>
    <% end %>
    </div>
    </div>
  • show_follow の描画結果を確認するための統合テストを書いていく

  • Relationship 用の fixture にテストデータを追加し、following/follower ページをテストする

    require 'test_helper'
    
    class FollowingTest < ActionDispatch::IntegrationTest
    
    def setup
    @user = users(:michael)
    log_in_as(@user)
    end
    
    test "following page" do
    get following_user_path(@user)
    assert_not @user.following.empty?
    assert_match @user.following.count.to_s, response.body
    @user.following.each do |user|
      assert_select "a[href=?]", user_path(user)
    end
    end
    
    test "followers page" do
    get followers_user_path(@user)
    assert_not @user.followers.empty?
    assert_match @user.followers.count.to_s, response.body
    @user.followers.each do |user|
      assert_select "a[href=?]", user_path(user)
    end
    end
    end

14.2.4 [Follow] ボタン (基本編)

  • [Follow]/[Unfollow] ボタンを動作させるため、まずは Relationship コントローラを作成する
  • まずはリレーションシップの基本的なアクセス制御に対するテストを書く

    require 'test_helper'
    
    class RelationshipsControllerTest < ActionDispatch::IntegrationTest
    
    test "create should require logged-in user" do
    assert_no_difference 'Relationship.count' do
      post relationships_path
    end
    assert_redirected_to login_url
    end
    
    test "destroy should require logged-in user" do
    assert_no_difference 'Relationship.count' do
      delete relationship_path(relationships(:one))
    end
    assert_redirected_to login_url
    end
    end
  • 次に logged_in_user フィルターを Relationships コントローラのアクションに対して追加し、リレーションシップのアクセス制御を行う

  • [Follow]/[Unfollow] ボタンを動作させるには、フォームから送信されたパラメータを使って followed_id に対応するユーザーを見つけてくる必要がある

    • その後見つけてきたユーザーに対して follow / unfollow メソッドを使う

      class RelationshipsController < ApplicationController
      before_action :logged_in_user
      
      def create
      user = User.find(params[:followed_id])
      current_user.follow(user)
      redirect_to user
      end
      
      def destroy
      user = Relationship.find(params[:id]).followed
      current_user.unfollow(user)
      redirect_to user
      end
      end

14.2.5 [Follow] ボタン (Ajax編)

  • ユーザーをフォローした後、ページから離れて元のページに戻る仕様が微妙
    • Ajax で解決できる
      • Web ページからサーバーに非同期でページを移動することなくリクエストを送信可能
  • フォローフォームを Ajax 使用に変更する

    <%= form_for(current_user.active_relationships.build, remote: true) do |f| %>
    <div><%= hidden_field_tag :followed_id, @user.id %></div>
    <%= f.submit "Follow", class: "btn btn-primary" %>
    <% end %>
  • フォロー解除フォームを Ajax 使用に変更する

    <%= form_for(current_user.active_relationships.find_by(followed_id: @user.id),
             html: { method: :delete },
             remote: true) do |f| %>
    <%= f.submit "Unfollow", class: "btn" %>
    <% end %>
  • フォームの更新が終わったので、これに対応する Relationship コントローラを Ajax リクエストに対応できるようにする

    class RelationshipsController < ApplicationController
    before_action :logged_in_user
    
    def create
    @user = User.find(params[:followed_id])
    current_user.follow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
    end
    
    def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
    end
    end
  • ブラウザ側で JavaScript が無効になっていた場合も動作するようにする

    require File.expand_path('../boot', __FILE__)
    .
    .
    .
    module SampleApp
    class Application < Rails::Application
    .
    .
    .
    # 認証トークンをremoteフォームに埋め込む
    config.action_view.embed_authenticity_token_in_remote_forms = true
    end
    end
  • プロフィールページを更新させずにフォローできるようにする

    • JavaScript と埋め込み Ruby を使ってフォローの関係性を作成する
    • create.js.erbdestroy.js.erb を更新

14.2.6 フォローをテストする

  • フォローボタンが動くようになったので、テストを書いていく

    require 'test_helper'
    
    class FollowingTest < ActionDispatch::IntegrationTest
    
    def setup
    @user  = users(:michael)
    @other = users(:archer)
    log_in_as(@user)
    end
    .
    .
    .
    test "should follow a user the standard way" do
    assert_difference '@user.following.count', 1 do
      post relationships_path, params: { followed_id: @other.id }
    end
    end
    
    test "should follow a user with Ajax" do
    assert_difference '@user.following.count', 1 do
      post relationships_path, xhr: true, params: { followed_id: @other.id }
    end
    end
    
    test "should unfollow a user the standard way" do
    @user.follow(@other)
    relationship = @user.active_relationships.find_by(followed_id: @other.id)
    assert_difference '@user.following.count', -1 do
      delete relationship_path(relationship)
    end
    end
    
    test "should unfollow a user with Ajax" do
    @user.follow(@other)
    relationship = @user.active_relationships.find_by(followed_id: @other.id)
    assert_difference '@user.following.count', -1 do
      delete relationship_path(relationship), xhr: true
    end
    end
    end

14.3 ステータスフィード

  • 現在のユーザーにフォローされているユーザーのマイクロポストの配列を作成し、現在のユーザー自身のマイクロポストと合わせて表示する

14.3.1 動機と計画

  • 現在のユーザーによってフォローされているユーザーに対応するユーザー id を持つマイクロポストを取り出し、同時に現在のユーザー自身のマイクロポストも一緒に取り出すことが目的
  • 以下の条件を満たすテストを書いていく

    • フォローしているユーザーのマイクロポストがフィードに含まれていること
    • 自分自身のマイクロポストもフィードに含まれていること
    • フォローしていないユーザーのマイクロポストがフィードに含まれていないこと

      require 'test_helper'
      
      class UserTest < ActiveSupport::TestCase
      .
      .
      .
      test "feed should have the right posts" do
      michael = users(:michael)
      archer  = users(:archer)
      lana    = users(:lana)
      # フォローしているユーザーの投稿を確認
      lana.microposts.each do |post_following|
      assert michael.feed.include?(post_following)
      end
      # 自分自身の投稿を確認
      michael.microposts.each do |post_self|
      assert michael.feed.include?(post_self)
      end
      # フォローしていないユーザーの投稿を確認
      archer.microposts.each do |post_unfollowed|
      assert_not michael.feed.include?(post_unfollowed)
      end
      end
      end

14.3.2 フィードを初めて実装する

  • ここでは microposts テーブルからあるユーザーがフォローしているユーザーに対する id を持つマイクロポストをすべて選択するクエリが必要

    class User < ApplicationRecord
    .
    .
    .
    # パスワード再設定の期限が切れている場合はtrueを返す
    def password_reset_expired?
    reset_sent_at < 2.hours.ago
    end
    
    # ユーザーのステータスフィードを返す
    def feed
    Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
    end
    
    # ユーザーをフォローする
    def follow(other_user)
    following << other_user
    end
    .
    .
    .
    end

14.3.3 サブセレクト

  • 今のつくりだとユーザーが5000人程度になると Web サービス全体が遅くなる可能性があるので、改善していく
  • where メソッド内の変数にキーと値のペアを使い、DB への問い合わせ数を減らす

    class User < ApplicationRecord
    .
    .
    .
    # ユーザーのステータスフィードを返す
    def feed
    Micropost.where("user_id IN (:following_ids) OR user_id = :user_id",
     following_ids: following_ids, user_id: id)
    end
    .
    .
    .
    end
  • ここからさらに following_ids を SQLに置き換えて最終的な実装とする

    class User < ApplicationRecord
    .
    .
    .
    # ユーザーのステータスフィードを返す
    def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
    end
    .
    .
    .
    end
  • サンプルアプリケーションの完成!

14.4 最後に

  • 完成したよ!!

所感

チマチマと進めていた Rails チュートリアルもようやく終わった。最後はちょっと飽きてきていたものの、とりあえず完走できたので良かった。

Rails に対する悪評はよく耳にしていたが、用法用量を守って Rails の機能を使わないと振り回されてしまう点や、密に結合したMVCのアーキテクチャと継続的に変更を加えていくプロダクト開発との相性が悪そうな点が、その悪評の根底にあるのかなと本チュートリアルを通して認識できた。Rails が悪いのではなく、Rails を正しく使えない自分が悪い、という話なのだと思う。

元々は自社のプロダクトコードをより理解したいという動機で始めた本チュートリアルだったので、これから戦場に飛び込んでみよう。いざ参らん。


5326 Words

2020-05-20 11:42 +0000