❀良い質問ですね❀
この疑問は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
を通して作成します。
具体的には以下のように。
ruby
1user = User.new(name: 'piyo')
2user.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のテキストなどはこの辺をすっ飛ばして解説することが多いために躓く人を多く見てきました。
この長文が何かのお役に立てば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。