静的型付け言語原理主義者による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