質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.02%

Railsにおいての用語というか、よく見かける単語などについての質問です

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 1,261

teruwa

score 47

『モデルオブジェクト」ってなんのことですか?
@news_send = NewsSend.new(message_params)
例えばこういう記述がされたコントローラーがあった場合、
この「@news_send」の部分がモデルオブジェクトだと聞きました
ですが命名規則?のようなものから考えると、「NewsSend」も最初の文字が大文字で単数系なのですからモデルの名前ですよね?
これらモデルオブジェクト名とモデル名は違うものなのですか?

あと
ビュー上に

<%= form_for(@news_send,url: news_index_path) do |f| %>
題名:<br />
<%= f.text_field :news_title %><br />

とあったのですが「@news_send」の部分はフォームに入力された情報を送る先という認識はあっていますか?
となるとこれはユーザーが勝手に定義して「@news_send」と命名した変数(送り先)ということですか?
「:news_title」というのはカラムを指定しているというのはなんとなくわかるのですが、そのカラムがあるテーブルはどこで指定しているのでしょうか?

最後に、
コントローラー上に
def index
@news_send = NewsSend.new
end

def create
@news_send = NewsSend.new(message_params)
@news_send.save
redirect_to root_path , notice: '投稿完了です'
end
とあったのですが、
最初のdef indexの部分でNewsSendモデルのオブジェクトの初期化を行っていると聞いたのですが、
なぜ初期化しないとまずいのでしょうか?
def createのほうにも@news_send = NewsSend.newと似た記述があると思うのですがこれとは違うのですか?(こっちはmessage_paramsとついてはいますが、、、)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+3

 ❀良い質問ですね❀

この疑問はRailsから入門した方が直面する、通過儀礼のようなものだと思ってください。
ただし、あなたにはコードに対して疑問を持つ、プログラマーとしての才能があるようです。

Railsとは、Ruby on Railsの略ですが、つまりRubyを前提としています。
クラス・インスタンス・インスタンス変数・ローカル変数
この辺の理解をすることでRailsをより深く、本質的に、また将来迷うことなく学んでいけるようになるでしょう。

もしくは、形式的なルールに従っても、Railsはある程度書くことができ、またそこそこに都合よく動きます。
しかし、あなたがもしこれからRubyを使って数年単位で何かをやろうとしているのであれば、
間違いなくRubyの正しい習得から始めることをおすすめします。


 名称   意味・働き 
 モデル/クラス   Railsが採用している、ActiveRecord::Baseのクラスの一種。データベースにある同じ名前のテーブル構造と対応する。 
 モデルオブジェクト/インスタンス   正式名称ではないですが、恐らくモデルのインスタンスのこと 
 @news_send   いま書いてるコントローラと、ビューで利用できる、任意のインスタンス変数のこと。実は名前はなんでもよい 
 NewsSend.new(message_params)   NewsSendというモデルから、newメソッドを通してモデルオブジェクト(インスタンス)を生成している 
 ビューの中の@news_send   コントローラでたくさん変数を使いますが、そのうちビューで利用するものを特別にインスタンス変数に代入している。これも名前は自分できめてよい 
 インスタンス変数   クラスから生成したインスタンスの中で利用できる変数で、メソッドをまたいで利用できる。 
 ローカル変数   アクション中でしか利用できない変数のことです。ビューにも渡せませんが、ビューで必要ないデータはローカル変数で書くと、利用範囲が明確になって便利です。 
 コントローラ   実はあなたはアクション(index, createなど)に入った時点で、ナントカControllerが予めnewを通してインスタンス化されたものを見ています。 

ややこしいのですが、モデルというのはRails用語になります。
Rubyで言う所のクラスが、Railsによって機能が付け加えられ、モデルという名前を付けられています。

同様にモデルオブジェクトは、この特別にモデルと名前のついたクラスの、インスタンスのことを指します。
なので、クラスとインスタンスという言葉をベースに考えていただければ、世の中の情報的にも理解しやすいです。

 これらを踏まえて、回答

 1つめ

この「@news_send」の部分がモデルオブジェクトだと聞きました 
ですが命名規則?のようなものから考えると、「NewsSend」も最初の文字が大文字で単数系なのですからモデルの名前ですよね? 
これらモデルオブジェクト名とモデル名は違うものなのですか?

上の表の通り、@news_sendに代入されたオブジェクトは、NewsSendモデル(クラス)のインスタンスとなります。
@news_send = NewsSend.new(略) とセットで書かれているようですが、この左側と右側に特に脈絡はありません。

NewsSend.newが返す値の代入先は、@hoge でも、@huga でも構いません。
これは主にビューに渡すとき、またビューから見た時にあなたが扱いやすい、好きな名前を決めてあげてください。

一般的には、名前が自由すぎるとあとで忘れて使いづらいので、モデルの名前をスネークケースで単数形を表現します。
NewsSend(キャメルケース)をスネークケースで表現すると、news_sendとなります。

さらに、インスタンス変数は @ほにゃらら と書くため、
これをインスタンスう変数で扱いたい場合は @news_send という形で書きます。

このインスタンス変数に代入することによって、ビューから呼び出せるようになります。
(試しに@を外してビューから利用する形で実行してみてください。)


 2つめ

ビュー上に

<%= form_for(@news_send,url: news_index_path) do |f| %> 
  題名:<br /> 
  <%= f.text_field :news_title %><br />
<% end %>


とあったのですが「@news_send」の部分はフォームに入力された情報を送る先という認識はあっていますか? 

鋭いですね。
概ね、合っています。
が、@news_sendはNewsSendのインスタンスでしかありません。

これは追々、Railsの学習を進めていくことで理解が深まると思いますが、
form_forは@news_sendに入っているNewsSendのインスタンスの、
DBへの保存状態によってリクエストする先が変わるというカラクリをもっています。

@news_sendがまだNewsSend.newしたててで、saveをしていない時、こちらはcreateアクションに飛ばすように便宜を図ります。
一方、@news_sendがsave済みの場合、updateアクションに飛ばすようになります。

また、オプションにてリクエスト先は自由に変更できますが、
一般的にはこのRailsの仕組みをうまく使って書く内容を減らしながら作っていきます。

なお、NewsSendからwhereや、find_by(find)をした時は、save済みなのでupdateに飛びます。

蛇足ですが、@hoge = NewsSend.newとした場合、当然form_for(@hoge, ..略..)となります。


 3つめ

最初のdef indexの部分でNewsSendモデルのオブジェクトの初期化を行っていると聞いたのですが、 
なぜ初期化しないとまずいのでしょうか? 

初期化に関してはもうお分かりかもしれませんが、@news_sendは任意のインスタンス変数ですので、
ただ@news_sendと書いた所で、中身は自動的にnilになります。

その上で、新しいレコード( モデルオブジェクト/モデル(クラス)  のインスタンス)を作成するので、
newを使った初期化が必要になります。

話が少し前後しますが、NewsSendというモデルはテーブル全体を表しています。
一方で、NewsSendのインスタンスは、テーブル内の各レコードを表しています。

User

 id   name   保存 
 1   hoge   されてる 
 2   huga   されてる 

このようなテーブルがあったとき、Userは表そのものを表しますが、
User.find_by(id: 1)は id: 1, name: 'hoge'のレコードを指します。

ここに、新しいレコードを追加しようとしたとき、

User

 id   name   保存 
 1   hoge   されてる 
 2   huga   されてる 
 nil   piyo   されてない 

最後尾のname: 'piyo'のものをUser.newを通して作成します。

具体的には以下のように。

user = User.new(name: 'piyo')
user.save

このuser.save が呼び出されタイミングで、

User

 id   name   保存 
 1   hoge   されてる 
 2   huga   されてる 
 3   piyo   されてる 

自動的にidが振られ、晴れてデータベースに保存されるようになります。

なお、

def createのほうにも@news_send = NewsSend.newと似た記述があると思うのですがこれとは違うのですか?(こっちはmessage_paramsとついてはいますが、、、)

一つのリクエストに対して一つのコントローラのインスタンスが新たに生成されますので、
indexを受け付けた時と、createを受け付けた時とで異なるインスタンスの中にいます。

そのため、同様に見えますがindexでnewしたものはレスポンスを返すと同時にメモリから開放されてしまい、
その後を追いかけることはできません。
WEBサーバーですから、indexのリクエストの後に、createに来るユーザーが同一人物だとは限らないわけです。

そのため、indexでは空のレコードを使い、フォームのHTMLを生成するために利用し、
createでは実際に飛んできた値をNewsSendのカラムとして扱うことで保存できるようにしています。

複数の側面があるため、一概に同じ見た目でも全く同じ機能性というわけではないので、各所で注意が必要です。

(Rubyのクラスでそのままブラウザとやり取りできたらみんなハッピーなんですけど、
残念ながらサーバーとブラウザがやり取りしているのはただの平ったい文字列なんです...。)


非常に長くなってしまって恐縮ですが、
Railsのテキストなどはこの辺をすっ飛ばして解説することが多いために躓く人を多く見てきました。
この長文が何かのお役に立てば幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.02%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる