if it does't challenge you, it can't change you

RubyのWebエンジニアやってます。主にRuby on Railsのことで勉強になったこと書いていきます。

Ruby on Rails一連の流れ

全体の流れ

f:id:shoheimoment:20171013004441p:plain

1.ブラウザからのリクエスト→ルーター

2. ルーター→コントローラー

3. コントローラー→モデル

4. モデル→DB

5. コントローラー→ビュー

 

1.ブラウザからのリクエスト→ルーター

ユーザーがブラウザからサーバーにリクエストを送る。リクエストにはURL(https://~)やHTTPメソッド(GET, POST, DELETEなど)やその他パラメーターなどが含まれている。

ブラウザ(UI: User Interface)からURLを元に行きついたサーバーでは、まずルーターがそのリクエストを受け取る。ルーター(routes.rb)はこれからの一連の処理の案内役である。

f:id:shoheimoment:20171012222136p:plain

 

 

2. ルーター→コントローラー

ルーターは受け取ったリクエストから指定されたコントローラーの指定されたメソッドを実行する。

f:id:shoheimoment:20171012222237p:plain

 

例:以降、「Blog.show」メソッドを例にして示す。
「/blogs/~」というURLがくれば「BlogsControlloer」というコントローラークラスへ渡す。(これはフレームワークであるrailsの規則。何も設定しなければ、URLに応じて、命名規則で決められたコントローラーへ渡す。)

app/controller/blogs_controller.rb

class BlogsController < ApplicationController

そして、「/blogs/:(id)」のようなURLと、同じくリクエストに含まれているHTTPメソッドがGETであれば、そのクラスのshowメソッドを実行する。

f:id:shoheimoment:20171012213541p:plain

 

3. コントローラー→モデル

そのメソッドは、大体の場合、DB(データベース:PostgreSQL, MySQLなど)のデータを取得したり、修正したりするもので、どういう処理をしたいかをモデルに伝える。

f:id:shoheimoment:20171012222351p:plain

 

例:
showメソッドが実行されるとまずBlog.find()が行われる。

app/controllers/blogs_controller.rb

class BlogsController < ApplicationController 
# 省略
def show
@blog = Blog.find(params[:id])
end
# 省略
end

 

これはモデルには「Blog」というクラスがあり、そのfind()メソッドを行うという意味である。

app/models/blog.rb 

class Blog < ApplicationRecord
end

 

4. モデル→DB

モデルはDBと一対になっていて、「Blog」というモデルクラスがあれば「blogs」というテーブルがDBに存在する。

f:id:shoheimoment:20171012220826p:plain

※モデルの中(モデルファイル名:blog.rb)にはfind()メソッドは記述されてはいないが、find()やnew,saveなどはテーブル操作において使えるActiveRecordのメソッドである。なので、Blog.find()はクラスBlogのインスタンスメソッドのfind()を実行してほしいと伝えている。

app/models/blog.rb 

class Blog < ApplicationRecord
end

 

例えるなら、モデルはDBという異国へ行く。DBは異国なので使われている言語が違う。なのでモデルはメソッドからの命令を翻訳して理解して、他言語が使われているDBでデータを探しデータを調達したり、改修したりする通訳者兼配達者みたいなもの。

f:id:shoheimoment:20171013000756p:plain

例:
これをActiveRecordで解釈したモデルは下記のようにSQLへ翻訳する。
モデルクラス「Blog」→DBのテーブル名「blogs」
インスタンスメソッド「Blog.find(2)」→SQLのメソッド「select * from blogs where id=2」  :id値が2のレコードを取得する。

 console

f:id:shoheimoment:20171013003150p:plain

上図から翻訳されているのがわかる。こうして取得したレコードをコントローラーへ渡す。

 

5. コントローラー→ビュー

コントローラーはモデルから受け取ったレコードをインスタンス変数に格納して、ビューへ渡す。

f:id:shoheimoment:20171013004131p:plain

例:
コントローラーのshowメソッドでは、モデルからDBから取ってきたレコードを@blogというインスタンス変数へ代入する。そしてそれをビュー(show.html.erb)へ渡してビューで表示できるようにする。(これはrails命名規則であり何も設定しなければ、実行したメソッドの名前に応じて、決められたコントローラーへ渡す。def show→show.html.erb。表示先を変えたければredirec_toやrenderで指示する。)

 

 

 

 

 

関数の中に余分の変数に余分な引数が格納される

関数judgementで仮引数pointsが設定されている。その関数に仮引数の個数以上の引数を渡すと、その関数内に違う変数があれば、余分な引数は自動でその変数に格納される。もし、関数内に余分な変数がなければエラーになる。

 

function judgement(points, args){
  console.log(points);
  console.log(args);
  console.log(arguments.length);            // 渡された引数の数 = 3が出力される
  console.log(arguments);
  console.log(arguments[0]);                  // 実引数のひとつ目の内容、[80,80,80,80]が出力される
  console.log(arguments[1]); 
    let achievement = get_achievement(points);
    let pass_or_failure = get_pass_or_failure(arguments[1]);
    return (`あなたの成績は${achievement}です。${pass_or_failure}です!`);
}

console.log(judgement(sample1,sample2,sample1));

$ node newjudgement02.js
[ 80, 80, 80, 80 ]
[ 40, 40, 40, 40 ]
3
{ '0': [ 80, 80, 80, 80 ],
  '1': [ 40, 40, 40, 40 ],
  '2': [ 80, 80, 80, 80 ] }
[ 80, 80, 80, 80 ]
[ 40, 40, 40, 40 ]
あなたの成績はAです。不合格です!

 

Rubyでは*argsを仮引数に設定しておくと同じことができる。

def hoge(hage, *args)
  p hage
  p args
end

sample1 = 1
sample2 = 2
sample3 = 3
hoge(sample1,sample2,sample3)

$ ruby test.rb
1
[2, 3]

Javascriptはメソッドの外の変数も読み込む

Javascriptはメソッドに引数を設定しないで、メソッドを呼び出してもメソッドの外の変数を読み込んで計算する。

メソッド(get_achievement)に引数を設定しないで、そのメソッドを呼び出しても、メソッドの外にある変数pointsを読み込み計算している。これを実行すると"A"を返す。

 

let points = [80,80,80,80];

function get_achievement(){
	let sum = 0;
	let number = points.length;
	let answer = "A";
	let full_score = 100
	for(let i=0;i<number;i++){
	    sum += points[i];
	}
	if (sum >= number*full_score*0.8){
		answer = "A";
	}else if(sum >= number*full_score*0.6){
		answer = "B";
	}else if(sum >= number*full_scores*0.4){
		answer = "C";
	}else{
		answer = "D";
	}
	return answer;
}

console.log(get_achievement());

 

rubyは下記のように、メソッド(sort_algo)で変数sample_listはメソッド内では読みこめない。下に実行結果は赤文字でエラーが出ている

 

sample_list = ["a","b","c"]

def sort_algo()
        count = 0
    for str_number in sample_list
        count += 1
    end
        sample_list[0],sample_list[count - 1] = sample_list[count - 1],sample_list[0]
        
        return sample_list
end

puts(sort_algo())

$ ruby algorithm_exercise3.rb
algorithm_exercise3.rb:5:in `sort_algo': undefined local variable or method `sample_list' for main:Object (NameError)
        from algorithm_exercise3.rb:14:in `<main>'