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

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

アコーディオン機能の三角がくるっと回るやつの設定方法

html

<dt><p><img src="./images/triangle.png" class="arrow">&emsp;学歴</p></dt>
<dd><p>長岡技術科学大学 環境工学課程卒業</p></dd>
<dt><p><img src="./images/triangle.png" class="arrow">&emsp;実績</p></dt>
<dd><p>オーストラリアワーキングホリデー<br>6,000kmヒッチハイク旅制覇</p></dd>
<dt><p><img src="./images/triangle.png" class="arrow">&emsp;SNS</p></dt>

1. クリックファンクションを設定

2. クリックした要素の三角の画像を取り出す$('img', this)

3. アコーディオンを開くと同時に2で取り出した要素にcssのスタイルを設定.toggleClass('dropdown_toggle')

$(function(){
  $('.side_menu dd').hide();
  $('.side_menu dt').click(function(e){
    // toggleClassは開くときにクラスを当てる
    // thisの子孫要素である'img'を取り出す
    $('img', this).toggleClass('dropdown_toggle');
    $(this).next('dd').slideToggle()
  });
})

4. 3で設定される、三角を回転させるためのスタイルを設定

.dropdown_toggle {
    -webkit-transform: rotate(90deg);
            transform: rotate(90deg);
}

バリデーションの日本語表示の仕方

1. 辞書ファイルをダウンロード

まずプロジェクトのトップで下記コマンドを実行して、辞書ファイルをダウンロード。プロジェクトのトップとはアプリ名がsampleであれば「:~/workspace/sample (master) $  」のようにディレクトリを移動してからという意味

# 日本語のテンプレートをDL
wget https://raw.github.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml -P config/locales/

 

2.モデル用の辞書ファイルを分割して作成

そうするとconfig/locales/に「ja.yml」というファイルが作成されているのがわかる。
このファイルは長いので管理が大変になるため、モデル用のファイルはconfig/locales/下に別で作成する。

 

ファイル構成例

config/locales
         ├── en.yml
         ├── ja.yml
         └── model.ja.yml

 

3. ファイルに辞書を記載していく。

---
ja: activerecord: models: contact: お問い合わせ attributes: contact: name: お名前 email: メールアドレス content: お問い合わせ内容

※このときインデントが少しずれているだけで読み込まれないので注意。
上記だとモデルcontactの属性値の辞書を記している。

 

4. しっかり読み込ませる

辞書が完成したら、このファイルは自動では読み込まれないので、config/application.rb に下記を追加して、起動時に読み込まれるようにしておく。

config.i18n.default_locale = :ja

 

これで Rails を起動し直すと、validates とかのエラーメッセージが日本語化されている

Rails5 バリデーションの書き方

バージョン

Rails 5.1.4

 

対象

下図のようなお問い合わせフォームのバリデーションを作成していく。

f:id:shoheimoment:20171014161429p:plain

 

文法

 

validates シンボル1,シンボル2, シンボル3,・・・, バリデーションの種類: {オプション: true} 


※カラムのシンボル名は→「:」+「カラム名
※「バリデーションの種類:」の後スペースが必要。presence:trueのようにスペースがないと:trueをシンボルだと認識してしまう。

バリデーションの種類やそのオプションはガイドを参考に

 ※ガイドに書いてある「%{value}」はコントローラーから送られてくる変数ではなく、バリデーションの種類とそのオプションに応じて使える変数である。too_longの%{count}も同じ

 

こんな感じ・・・

Rails5でバリデーション

 2行目は名前の欄に記入された文字へのバリデーション。
presence: は空欄の場合、エラーを発生させるバリデーションの種類。
length: は文字数設定。
maximum: や too_long: はlengthのオプション。
8行目の
format: は設定したパターンと同じでないときエラーを返すもの
message: はformatのオプション。エラーが発生したときに
「・(カラム名)  (メッサージ)」の形でエラー文を表示
formatだけでなく色んなバリデーションへつけられる。

エラー結果↓↓↓

f:id:shoheimoment:20171015200312p:plain

 

ただ、上記だけでは上のようにモデルの属性値は日本語になりません。

モデルの属性値の日本語化はこちらにまとめました↓↓↓

shoohei.hatenablog.com

 

 フレキシブルなメソッドでの書き方

メソッドであればより柔軟にバリデーションを設定できる。下のコードは上のコードとほぼ同じ結果になる。メソッドを使うことで日本語翻訳設定をしなくても日本語でエラー文を表示できる。

Rails5 バリデーション メソッド形式


メソッドにするときは「validates」ではなく「validate」と単数形で「:メソッド名」
引数の渡し方は不明。
とりあえず「validate :メソッド」にすればバリデーションするためのパラメーターが渡される。
name, email, contentのようにカラム名を引数のような形で扱う。

 

バリデーションを書いているときに・・・

バリデーションのコードを書いていて試したいときにはrails cが使える。
rails cで仮にエラーが出るように登録してみる

f:id:shoheimoment:20171014164838p:plain


・変数.vaild? →検証できてるかどうか

f:id:shoheimoment:20171014164900p:plain

 

・変数.errors.full_messages →エラー内容が確認できる

f:id:shoheimoment:20171014164928p:plain

 

・変数.errors →エラー発生時どんな内容のエラーか確認できる。

f:id:shoheimoment:20171014164946p:plain

 

・変数.errors.count →エラーの数

f:id:shoheimoment:20171014165000p:plain

 

・変数.errors.full_messages →エラーのメッセージ。

f:id:shoheimoment:20171014165016p:plain

 

また、複数のターミナルを開いて、このターミナルではサーバーを起動。こちらのターミナルではrails cを起動。などにしておくと、いちいちサーバーを落としたりしなくてもいい。

 

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>'