LoginSignup
9
4

More than 3 years have passed since last update.

RubyonRailsを勉強していてずっとわかっていなかったこと

Last updated at Posted at 2020-01-18

このQiitaはRubyを勉強している中で
私が「ずっと理解できていなかったこと」と「その理由」と「勉強して理解したこと」をまとめたものです。

まだまだ間違っている部分もあるかもしれないのと
私自身まだわからないところ( :question: の部分 )もあるため
その点踏まえてみてください :bow:

ずっと理解できていなかったこと

MVCモデルについての理解

※以下、私の昔の理解なのでところどころ間違ってます!
iOS の画像.jpg
・ルーティング…リクエストに対して適切な場所に移動させる役割。
ブラウザからリクエストが来る。リクエストに対してルーティングで送り先を、コントローラとアクションを指定。

・コントローラー…実装したい機能を決める場所。
・実装したい機能に対して適切なアクションを設定。その際にはRailsで決められてる7つのアクションのどれかに沿って決める。
【Rails】7つのアクションとそれぞれの役割
・そのアクションの中にDBからデータを持って来るために変数を定義しないといけない。それは@からはじまる。
・変数を定義するためにはrailsであらかじめ定められたメソッドで定義できるっぽい。

・ビュー…DBから送られてきたデータを表示する場所
・HTMLの中で <% %> とか <%= %> で囲むとコントローラーで定義した変数を使えるっぽい。そこは動的になる。
・それ以外は普通のHTMLとCSSを書いていくと静的になる。

・モデル…コントローラーからDBへの橋渡し役。DB設計に何か命令する役目?
・テーブル作成と同時にrails g modelをしなければいけない。
・modelを作成した後は特に編集とかは要らないっぽい。

・マイグレーションファイル…DB設計を記述するところ。

その他理解できなかったこと

・なぜクラスとインスタンスが存在するのか?
・MVCモデルにおいてクラスはどれをさしているのか?
・クラスからインスタンスが生成されるというのはMVCにおけるどの部分をさしているのか?
・controllerのアクションの中には何を定義するのか?
・引数はなんで使うのか?

なぜ理解をしていなかったか

Rubyでは、 すべてのデータがオブジェクトとして扱われ、オブジェクトごとに性質や使えるメソッドを持つ という概念を理解していなかった。

(もちろんRubyを習い始めた時に、「オブジェクト指向」についての説明は出てきたが、その概念が初めてで理解できなかったし、そんなに大事なものだと思っていなかった。)

勉強して理解したいこと

勉強して理解ことを「User model」と「Tweet model」の2つをもつツイートアプリの例とともに説明。

モデルについて

モデルの存在意義

・データベースの設計図。そのデータベースに定義したいメソッドを書く場所。(アソシエーション、バリデーション、そのモデル独自のメソッドなど)
・そのためモデルはDB設計が必要なものしかつくらない。静的なサイトであればモデルはいらない。

user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable #ユーザーのログイン機能に関する記述
  has_many :tweets #tweet modelに対するアソシエーション

  validates :nickname, presence: true, length: { maximum: 6 } #バリデーション
end
tweet.rb
class Tweet < ApplicationRecord
  belongs_to :user #user modelに対するアソシエーション
end

Railsで定義されているメソッドの存在

・上記のようにモデルに記述がされていなくても、もともとrailsで定義されているメソッドがある。

①テーブルのカラム名

例えば、tweets tableを以下のように定義している場合

migrationfile
class CreateTweets < ActiveRecord::Migration[5.2]
  def change
    create_table :tweets do |t|
      t.string      :name
      t.text        :text
      t.text        :image
      t.timestamps null: true
    end
  end
end

tweet modelには記述されていないが以下のようなメソッドが定義されている。

tweet.rb
class Tweet < ApplicationRecord
  belongs_to :user #user modelに対するアソシエーション

  #以下、記述はされていないが使えるメソッド
  def name
    @name 
  end

  def text
    @text 
  end

  def image
    @image 
  end
end
②Application Recordクラスのメソッド(クラスの継承)

rails g modelコマンドで生成されるモデルクラスは全てApplicationRecordというクラスを継承している。

ApplicationRecordというクラスには テーブルにアクセスして情報を取得するためのメソッドが定義されており 、モデルクラスはそれを継承し利用することでテーブルから情報を取得している。

記述されていないがtweet modelには以下のようなメソッドが定義されている。

tweet.rb
class Tweet < ApplicationRecord
  belongs_to :user #user modelに対するアソシエーション

  #以下、記述はされていないが使えるメソッド
  def all
    # ここの記述がわかんない
  end

  def new
    # ここの記述がわかんない
  end

  def save
    # ここの記述がわかんない
  end

  def create
    # ここの記述がわかんない
  end
end

:question: それぞれの中に書いてある記述

コントローラーについて

コントローラーの存在意義

モデルに定義してあるメソッドを使う役割。

users_controller.rb
class UsersController < ApplicationController
  def show
    user = User.find(params[:id]) # User modelで最初から定義されているfindメソッドを用いてidを引数にuserを見つけて来る
    @nickname = user.nickname # User modelで最初から定義されているnicknameをメソッド使って、user tableからnicknameを見つけてくる
    @tweets = user.tweets.page(params[:page]).per(5).order("created_at DESC")
  end
end
tweets_controller.rb
class TweetsController < ApplicationController
  before_action :move_to_index, except: :index

  def index
    @tweets = Tweet.includes(:user).page(params[:page]).per(5).order("created_at DESC")
  end

  def new
  end

  def create
    Tweet.create(image: tweet_params[:image], text: tweet_params[:text], user_id: current_user.id)
  end

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

  def edit
    @tweet = Tweet.find(params[:id])
  end

  def update
    tweet = Tweet.find(params[:id])
    if tweet.user_id == current_user.id
      tweet.update(tweet_params)
    end
  end

  def show
    @tweet = Tweet.find(params[:id])
  end

  def search
    @tweets = Tweet.search(params[:keyword])
    respond_to do |format|
      format.html
      format.json
    end
  end

  private
  def tweet_params
    params.permit(:image, :text)
  end

  def move_to_index
    redirect_to action: :index unless user_signed_in?
  end
end

:question: アクション内の記述方法

Q.controllerのアクションの中には何を定義するのか?

AかBのいづれか。

A.モデルに定義してあるメソッドを使って、データを引き出す
B.モデルに定義してあるメソッドを使って、データを引き出しインスタンス変数を定義してビューに渡す

その際にUser ControllerではUser modelで定義されているメソッドもつかえるし、tweet modelで定義されているメソッドも使える。

クラスとインスタンス

Q.なぜクラスとインスタンスが存在するのか?

・Rubyでは、すべてのデータがオブジェクトとして扱われ、オブジェクトごとに性質や使えるメソッドを持つ
・オブジェクトを効率的に生成・管理するために、クラスとインスタンスという概念が存在する
・オブジェクト同士の共通の属性・メソッドをまとめて定義したものがクラスである
・クラスに基いて生成されたオブジェクトがインスタンス

例)Userモデルにはクラスとしてログイン機能をつけたり、ニックネームの登録の際のバリデーションをつけておく。
そこから実際に登録されたユーザー1人1人がインスタンス。

Q.MVCモデルにおいてクラスはどれをさしているのか?

・Controller
・Model
・table
(オブジェクトに共通の属性・メソッドを
まとめて定義したものはすべてクラス。)

Q.クラスからインスタンスが生成されるというのはMVCにおけるどの部分をさしているのか?

(Controllerで)Modelのメソッドを使うとき。
必ずインスタンスが生成される。

:question: modelのメソッドを使うのはcontrollerだけでまちがいないか?

引数について

Q.引数はなぜ使うのか

メソッドを異なる条件によって使うため。

tweets_controller.rb
  #このままだと毎回idが1のツイートしか編集できない
  def edit
    @tweet = Tweet.find(1)
  end

  #引数をわたすことによって様々なidのツイートの編集ができるようになる
  def edit
    @tweet = Tweet.find(params[:id])
  end

以上。
間違っているところがあればご指摘ください。

9
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4