Railsを触ってみた人の疑問にマジレスするよ
今年もDrecomさんのDrecom Award on Rails 2007が終わったりして初めてRailsに触れた、という人の声がちらほら出てきてますね。Railsが面白かったという人、分かりづらかったという人、いろんな感想があるみたいですが、やっぱり長いことRailsを触っている身としては、肯定的な感想を読むと嬉しいものですね。うん。
私がなんか貢献したわけじゃないですが。
ということで、目にした感想にマジレスしてみたいと思います。とりあえずこちらの体験記に。
http://coolsummer.typepad.com/kotori/2007/09/post-35.html
注意: 引用中の改行はもろはしによるものもあります。文の中身は書き換えていないはず。
2-2
※データベースと「Shemata」は同じ意味? 違うもの? 確認中。
ShemataはScheme(スキーマ)かな?データベースの構造を記述した言語(DDL?)というかなんというか。DBの構造をさしてSchemeと呼ぶことが多いです。一言で言うとなんなんだろ。
# しょっぱなから微妙な返答ww
2-2-1
※テーブル名は必ず複数形じゃないといけない? 確認中。基本はそうなはず。3−5−2にも同様の疑問あり。
複数形にしなくてもなんとかする方法はありますが、原則は複数形で。Rails用に新しくDBを作るようなときは複数形にした方がいいですよ。
2-2-2
※urlはデフォルトが空なのに「NOT NULL」にチェックを入れた。何故? 確認中。
NULLと空文字列は別物なんですよね。「空の文字列」が*ある*、ということと「何もない」ということの違いです。いやNOT NULLじゃなくてもいいですが、私もNOT NULLでデフォルト""というのを好んで使います。
2-2-2-1
必ず最初のカラムは「id」で、数字が順番に入り、Primary keyになってないといけない ※本当にそうかどうか確認中。基本はそうなはず。
Primary KeyをidにするのもRailsの規約の一つです。これも変えて変えられないことはないんですが、イバラの道度があがるのでidを使うことを強く推奨します。テーブル名の規約より重要だと思う。
3-4-2
※恐らく、「model名とtable名は基本的に一致していて、table名はmodel名の複数形 である必要がある。今回はテーブル名が「articles」なので、モデル名が「article」」。 で正しいと思うが、確認中。2−2−1にも同様の疑問あり。 ※もし「table名はmodel名の複数形の必要がある」のであれば、例えばtable名で「010203」 といったものは作れない(複数形にできないから)? 確認中
まず前者の質問は正しいです。table名はmodel名の複数形になるというのがRailsの規約です。
ただ、どうしても必要な場合は変えることもできます。参考に某書籍の原稿を一部公開します。分かりづらい表現や間違っている箇所があればご指摘くださいませ*1。
http://rails-recipebook.g.hatena.ne.jp/rrbk/20070930/1191117954
3-4-3-2
※modelを指定するときは、最初の1文字目を大文字にするのは、決まりごと? 何か理由が? ※そもそも、「Article」はモデル名? それとも別のもの? 確認中(以下はArticleをモデル名だと前提にして書く)。
- DBのテーブルに対応したモデルを、Rubyのクラスとして定義します
- app/models/article.rbでclass Articleとあるのはそういうことです
- articlesテーブルに対応するモデル(クラス)名がArticleになります。
- Rubyのクラス名は大文字で始まるので大文字になります
「Articleをモデル名だと前提に〜」してもほぼ問題ないかと思います。
3-4-3-5
※「hensu.save」の「.」以下のことをアトリビュートと呼ぶ? 確認中。
.saveは「メソッド」ですね。3-4-3-3の命令の結果で示しているのがattributesで、himitu.urlなどでattributesの中身を読み出すのを(アクセサ)「メソッド」の呼び出しといいます。
.saveは対象のモデルオブジェクトを保存するメソッド、.urlは"url"というattributesを読み取るためのメソッドです。ほぼ全部メソッド呼び出しです。
※そもそも、たとえば、「Article.new」の場合、「Article」と「new」と「Article.new」はそれぞれ何と呼ぶか? 確認中(「クラス」「メソッド」「モデル」「テーブル」「アクション」「アーティクル」などなどが頭のなかでごっちゃになっている…)
「Article」はクラス、「new」はメソッド、「Article.new」はメソッド呼び出し(ArticleクラスのClass Method "new"を呼び出している)というように呼べばOK。
とても乱暴にいうと、「クラス」と「メソッド」はオブジェクト指向言語の用語。今回はRubyですね。Rubyの用語です。
で、「モデル」というのはアプリの作り方の語彙です。アプリを画面(ビュー)と実際の処理(モデル)、両者の橋渡し(コントローラ)の三つを分ける考え方をMVC(Model View Controller)といいまして、Railsもこの考え方に沿ってます。で、今回は実際の処理(DBの読み書きとか)を行うArticleクラスの話をしてるのでモデルというんですわ。
「テーブル」はDB用語です。ここではMySQLの話ですね。あと「アーティクル」はご自分で作った名前ですよね。Railsの場合モデルとテーブルが同じ名前(の単複形)になるので、慣れるまでは混乱するかも。
※saveの他にはどんな種類のアトリビュートがあるのか、確認中 もしかして、http: //railsapi.masuidrive.jp/class/ActiveRecord%3A%3ABase の中の 「Public Class Methods」「Public Instance Methods」「Protected Class Methods」 「Protected Instance Methods」が書ける命令一覧? よく使うのは?)。
そうそう、そういうのです。よく使うのはいっぱいあるので追々。
4-2-2
※「:articles」はモデルの複数形ではなく、テーブル名を指している? それとも全然違う何かを指している? 確認中。もしテーブル名自体を指しているのであれば、さらなる疑問は、なぜ他の場所では「Article.うんたら」と いった形で、モデルを通してデータベースのデータを引っ張ってきているのに、ここだけ直接データベースの テーブルをしているような書き方になっているのか。いずれにしろ確認中。 (http://railsapi.masuidrive.jp/module/ActionController%3A%3APagination/paginate には「class_name」と書かれている。クラスって何を指す?)
ページネートは難しいですよね。処理の中身がなかなか見えずらい。そもそもどういった動きをしてるんでしたっけ?
- ページネートはあるDBのテーブル全件(a)からそのページ(x)の開始分 + n件を読み出す
- x = 2ページ目でn = 10件ずつ読み出すのであれば11〜20件目まで
- x = 5ページ目でn = 10件ずつ読み出すのであれば41〜50件目まで
- また全件数 a = 95の場合にx = 10ページ目でn = 10件ずつ読み出すのであれば91〜95件目まで、という
- つまり「対象となるテーブル」「1ページの件数(n)」「現在のページ番号(x)」「全件数(a)」がわかればよい
- まず対象となるテーブルに対応したモデルクラスを指定します。これが:articles。
- いろんなテーブルでも共通の処理でできるように、テーブル名を明示してるんですね。
- 内部で:articlesからArticleを取得する処理をしてます。
- 1ページの件数(n)が:per_pages => 10で指定しています。10件。
- 全件数(a)はテーブルが特定できればSQL文で求められので明示的な指定は不要。
- 現在のページ番号(x)はURLの?page=で指定しているものを見ています。
- paginate()関数を使う場合は明示する方法はなくもないけど大変です
これで必要なパラメータがそろうので、あとは内部でいろいろ処理している、と。でページに関する情報が@article_pagesに、実際のArtilceのリストが@articlesに代入されています。処理の中身までは省略。
※「@article_pages」の中に入っている情報が「全体が何ページになり、今何ページ目か」かは、ちょっと怪しい。確認中
@article_pagesの中身はそれでOK。
※.「@article_pages」の中に入っている「今何ページ目か」という情報は、どこから取って来ている? (urlの「?page=2」と書かれた部分を、pagenateという命令が@article_pagesに代入している?)
これは前述の通り。?page=2が巡り巡って@article_pagesの一部となります。
※括弧を省略しないで書くと、「(@article_pages, @articles) = paginate(:articles, :per_page => 10)」? それとも「@article_pages, @articles = paginate(:articles, :per_page => 10)」? 確認中
これも別の書き方があるんですが、それだけでお腹いっぱいになるボリュームなので省略。
※「@articles」の中に入っている情報が「テーブル「articles」の中の10行分のデータ」かはちょっと怪しい。確認中。
これもそれでおk。
※「@article_pages」の中のデータを見る方法、確認中 ※「@article」の中のデータを見る方法、確認中
それRSpecで(ryとかfunctional_testで(ryとかはあるんですが、too muchな気もするので。開発中にraise @article_pages.inspect()とすると見えます、一応。(本番環境でやっちゃダメですよ)
5-1-1
※「個々のアクション名とviewのhtmlファイルの名前は、1対1で対応している。だからcontrollerの中に「list」というアクションがあったら、何も指定しなければ、自動的にviewsのlist.rthmlを使う」はちょっと怪しい。確認中。
それでおk。
5-2-1
※「<%h= うんたら >」の説明はちょっと怪しい、確認中。
これもおK
5-2-2-3
※この説明だと、最初のカラムは「id」のはずなのに、実際「http://localhost:3006/vote/list/」で見ると、最初のカラムが「url」になっている。なんで? 確認中。
content_columnsにはidは出ないようになってます。idは特別なカラム(DB的な意味で)なので。
5-2-4
※「article.send(column.name)」ってのが判らない。特に「send」が。確認中。 僕の推測だと…「send(column.name)」は、この直前で変数「column」に代入している情報の「name」という アトリビュートを表している。たぶん、「Article.content_columns」という命令の中の「name」という項目は、 実際のデータベース「articles」のカラムのタイトル名。つまりforの1回転目は「send(column.name)」の中身は 「url(いや、1個目は「id」?)」で、2回転目は「good」、3回転目は「bad」? 確認中。一応consoleでは、以下のような実験結果が出た。
ナイス推測。おおよそそれでいいと思います。idが出ないのは前述の通り。
※「send」ってのがよく判らない。何用のコマンド? 例えばここで「article.(column.name)」とか「article.column.name」とか「article.[column.name]」と 言う書き方はできない? 確認中。
sendというのはRubyのメソッドで、引数で与えられた名前のメソッドを呼び出します。プログラム的にはメソッド呼び出しの句と引数(カッコ()の中身)はまったく別物なので、普通の手段では呼べません。article.(column.name)とかは無理なんですね。
article.url # => OK article.send("url") # => OK article."url" # => NG。構文的にアウト。 article["url"] # => OKなんですが、これは[]メソッドがあるからなんです。 article("url") # => NG。構文的にはOKだけどこれはarticles()という関数を呼んでることになるのでダメです。
とりあえず5までやって外出の時間になりました。反響があれば続きをやります。疲れますがけっこう楽しいですね。勝手に添削をしてるみたい。
ほかにRailsでわからないことがある、という人やRailsをよく触っている人から見て事実誤認なんかがあるようならご指摘ください。
*1:発売前にもレビューしていただきたい、というのが公開の意図ですので