20220116のRubyに関する記事は12件です。

[Rails][devise]追加したカラムにストロングパラメーターを使えるようにしよう

備忘録として ユーザー管理機能を実装できるdevise デフォルトとして「Eメールアドレス」「パスワード」のカラムがすでに存在しており、ストロングパラメーターも使用できるが、自分で追加するカラム(ユーザー名など)にはストロングパラメーターは使えない状態なので、使えるようように記述する必要がある。 前提 deviseを導入済み→deviseの導入手順 マイグレーションファイルでカラムを追加している application_controller.rbファイル すべてのコントローラーが継承しているファイル。 ここに処理を記述しておくことで、すべてのコントローラーで共通となる処理を作ることができる。 deviseの処理を行うコントローラーはGem内に記述されているため編集することができないので、このapplication_controller.rbを編集していく。 devise_parameter_sanitizerメソッド deviseにおけるparamsのようなメソッド。deviseのUserモデルに関わる「ログイン」「新規登録」などのリクエストからパラメーターを取得できる。 このメソッドとpermitメソッドを組み合わせることにより、deviseに定義されているストロングパラメーターに対し、自分で新しく追加したカラムも指定して含めることができる。 普通のストロングパラメーターと同じく、新たに定義するPrivateメソッドの中で使用します。 application_controller.rb private def configure_permitted_parameters # メソッド名は慣習(自由につけても構わない) # deviseのUserモデルにパラメーターを許可 devise_parameter_sanitizer.permit(:deviseの処理名, keys: [:許可するキー])#追加したカラムを記述 end 第一引数の処理名には、deviseですでに設定されているsign_in, sign_up, account_updateが使用できる。 処理名 役割 :sign_in サインイン(ログイン)の処理を行うとき :sign_up サインアップ(新規登録)の処理を行うとき :account_update アカウント情報更新の処理を行うとき 実際に編集してみる application_controller.rb class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? private def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname]) end end 解説 2行目 before_actionのifというオプションを使用している点に注目。 これは、値にメソッド名を指定することで、その戻り値がtrueであったときにのみ処理を実行するよう設定している。 今回は:devise_controller? というdeviseのヘルパーメソッドを指定して、もしdeviseに関するコントローラーの処理であれば、そのときだけconfigure_permitted_parametersメソッドを実行するように設定してる。 まとめ 自身で追加したカラムでストロングパラメーターを使えるようにするには、特別な記述が必要 devise_parameter_sanitizerメソッドを使用する application_controller.rb内に記述する   ※補足等があればコメントいただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webの仕組みとHTTP通信について

ブラウザとサーバー ブラウザ:今表示されている画面 サーバー:様々なデータを保存している大きなPCのイメージ ブラウザではサーバーからファイルをダウンロードしてきて表示している。ファイルの中身にはHTML、CSS、JavaScriptなどの情報が格納されている。 (ブラウザ) ←←←←← (サーバー)        ファイル     (HTML、CSS、JS) HTTP通信について HTTPとはブラウザとサーバーのやりとりの方法 基本は、リクエストとレスポンス       リクエスト       →→→→→ (ブラウザ)     (サーバー)       ←←←←←       レスポンス リクエストで欲しい情報をサーバーに投げて、サーバーがその情報を返す。 このリクエストとレスポンスのやりとりのルールを作るのがサーバーサイド言語。 HTTPの基本のメソッド4つ ①GET データの取得 Webページを表示するときに使う      このページみたい       →→→→→ (ブラウザ)     (サーバー)       ←←←←←      はい、ページの情報 ②POST データの送信 フォームなどでデータを保存するときに使う      データ保存して       →→→→→ (ブラウザ)     (サーバー)       ←←←←←      はい、保存したよ ③PUT データの更新 既存データを書き換えるときに使う      データ変更して       →→→→→ (ブラウザ)     (サーバー)       ←←←←←      はい、変更したよ ④DELETE データの削除 既存データを削除するときに使う      データ削除して       →→→→→ (ブラウザ)     (サーバー)       ←←←←←      はい、削除したよ IPアドレスとドメイン IPアドレス:サーバー内でデータに割り振られている住所のようなもの。数字で管理されている。 ドメイン:「〜〜.com」の部分。 IPアドレスだと分かりにくいため、DNSがIPアドレスとドメインを紐付けている。 Webサイトが表示されるまで(例:Qiita)    qiita.comのIPアドレス教えて       →→→→→ (ブラウザ)     (DNS)       ←←←←←    はい、このIPアドレスだよ        ↓   DNSから取得したIPにGETリクエスト       →→→→→ (ブラウザ)     (DNS)       ←←←←←   はい、HTML、CSS、JSはこれだよ 最後に こんな感じでWebサイトは表示されている。Web開発を学ぶ上で最低限の知識なのでアウトプットしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

formatメソッド(Ruby)

Ruby3.1 Kernelモジュールformat sprintf(string print formatted)フォーマット formatの記述は『%指示子』が基本 指示子は、引数の型の解釈を示し、省略できない ・文字列を表す指示子:c,s,p ・整数を表す指示子:d,i,u,b,B,o,x,X ・浮動小数点数を表す指示子:f,g,e,E,G #『%d又は%i』引数の数値を10進表現の整数として出力する #整数でない場合はto_iと同規則で整数に変換する format("%d",3.5) #=> "3" format("%d","0b1010") #0b(2進数) #=> "10" #『%s』は文字列を出力する v = "moji" 5.times do |i| if i % 2 == 0 puts format("文字列%d(%s)", i, v) end end #=> "文字列0(moji)" "文字列2(moji)" "文字列4(moji)"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

return/break/nextの使い方(Ruby)

Ruby3.1 制御構造return 制御構造break 制御構造next return Rubyのようなオブジェクト指向の言語の関数をメソッドと呼ぶ breakは式の値を戻り値としてメソッドを終了する def ex 10.times do |i| if i == 7 return i end end end #メソッドexを実行します(戻り値はi) ex #=> 7 #戻り値を省略するとnilが返る def ex 10.times do |i| if i == 7 return end end end ex #=> nil break breakは一番内側のループを脱出する 10.times do |i| if i == 3 break end puts i end 0 1 2 next 一番内側のループの繰り返しにジャンプする 5.times do |i| if i % 2 == 0 next end puts i end 1 3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

論理演算子(&&, ||)を「かつ」「または」と覚えるのはもうやめよう

※こちらの記事は初学者向け・丁寧に解説を心がけております。  その分、文章量も多いのでご了承ください。 プログラミングを学びたての頃、論理演算子の章で && を「かつ」 || を「または」 と覚えてしまった人も多いのではないでしょうか? 高校数学 A で習う「集合」のカリキュラムに登場する「A∩B」や「A∪B」の考え方に沿えば一番馴染みのある表現ではありますが、プログラムの振る舞いに着目すると厳密には異なります。 また、経験を積んでいくにつれて、&&を「かつ」、||を「または」と表現すると、説明がしづらいこと場面にも遭遇します。 この記事を読んで、「かつ」「または」という考え方から脱却していきましょう。 また、この記事では ブラウザですぐ実行できること 多くの初学者にも馴染みがある という点からJavaScriptを基に解説していきますが、一部挙動は異なるものの、Ruby や PHP などでも考え方は同じです。 用語解説 AND 演算子 &&のこと アンパサンド2つと書くのがめんどくさい。 OR 演算子 ||のこと パイプライン2つと書くのがめんどくさい。 オペランド 式を構成する要素だよ 演算子じゃない方だよ 数字とか変数とかだよ オペランド (operand)とは|「分かりそう」で「分からない」でも「分かった」気になれる IT 用語辞典 a || bであれば、aやbのことです。 正式名称ではないかもしれませんが、この記事ではaを左オペランド、bを右オペランドと言わせてください。 Boolean trueとfalse の2つの値を取るデータ型のこと。 先に結論 AND演算子&&は、左から順にfalseを探しにいき、 OR演算子||は、左から順にtrueを探しにいき、 見つかればその値を返す。 見つからなければ最後の値を返すよ。 true/falseでない値は、 trueに変換できるtruthyな値か、 falseに変換できるfalsyな値かに着目しよう。 よくある例題 初学者向け教材にはこんな例題が載っています。 [例題1] 数学と理科のテストの点数を変数に格納し、 どちらも 70 点以上であれば「合格」 そうでなければ「不合格」 と出力するプログラムを書いてみましょう。 test1.js const math = 80 const science = 65 if (math >= 70 && science >= 70) { console.log('合格!') } else { console.log('不合格…') } 頭の中で日本語に直すと if 文は ・もし (「math が 70 以上」かつ「science が 70 以上」)ならば という意味だな。 math は 80 で 70 以上だから true だけど、science が 65 で 70 以上ではないので false。 2つとも true じゃないから、「かつ」を満たさない。 よって、if 文全体の評価は false となり、else の方に進み、「不合格」が表示される。 こんな感じでしょうか。 この思考自体は間違っていません。この例題の回答としては十分クリアできています。 「かつ」「または」という考え方の弊害 しかし、AND 演算子&&を「かつ」と暗記していると、こんなイジワル問題に遭遇した時に、瞬時に答えられないかもしれません。 [例題2] 以下のコードを実行すると、 console にどのように出力されるでしょうか? test2.js const math = 80 const science = 65 if (math && science) { console.log('ifの中です') } else { console.log('elseの中です') } 変数を展開するとこうなりますが if (80 && 65) 80かつ65ってなんなんだ?と混乱してしまいます。 つまり、「かつ」「または」と覚えたことの弊害は、左右のオペランドが論理式(70 >= 80 のように、比較して true か false が返される式)の場合に理解が限定されてしまうことです。 >や==などが出てこない場合でも、JavaScript がどのように判断しているのか理解できるようになりましょう。 AND 演算子&& AND 演算子&&は、現代の JavaScript チュートリアルではこのように解説されています。 ① 左から右にオペランドを評価します。 ② それぞれのオペランドで、それを Boolean に変換します。 ③ もしも結果が false の場合、ストップしそのオペランドの本来の値を返します。 ④ もしもすべての他のオペランドが評価された場合(i.e. すべて 真 のとき), 最後のオペランドを返します。 順番に見ていきましょう。 ① 左から右にオペランドを評価する これはプログラミングの原則通りの向きなので問題ないでしょう。 「評価する」という表現がわかりにくければ、「1つ1つ見ていく」と変換しても構いません。 ② それぞれのオペランドで、それを Boolean に変換します。 Boolean という言葉が分かりにくければ、「それぞれのオペランドで、それを真か偽のどちらかに変換する」と言い換えることができます。 では「Boolean に変換する」とはどういうことでしょうか? truthy / falsy JavaScript には、 'リンゴ', ''(空文字)などの文字列 0, -15, 3.14などの数値 ['アメリカ', '日本', 'ドイツ']などの配列 { name: '鈴木', age: 20 }などのオブジェクト 他にも true, false, null, undefined など、様々な型の値が存在しますが、それらは全て true または false に変換することができます。 変換した時に true になるものをtruthy、false になるものをfalsyと言います。 JavaScript ではfalseそのものの他に、0, ''(空文字), null, undefinedなどは Boolean に変換するとfalseになることからfalsyな値です。 falsy な値以外は全て Boolean に変換するとtrueになることから、truthyな値です。 もっと詳しく知りたい方は以下の記事をご覧ください。 Truthy (真値) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN Falsy (偽値) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN (ちなみにRubyではnilとfalseの2つだけが falsyで、それ以外は全てtruthyになります。 数値の 0 が JavaScript では falsy でも、Ruby では truthy になります。 ポートフォリオ作りで両方同時に学ぶときには注意しましょう。) これを踏まえて、例題2の80 && 65をもう1度考えてみましょう。 80 は truthy な値なので true に、 65 も truthy な値なので true に変換されます。 if (80 && 65) ↓ if (true && true) ③ もしも結果が false の場合、ストップしそのオペランドの本来の値を返します。 80 も 65 もどちらも true に変換されたため、false がありません。 ③ はスキップします。 ④ もしもすべての他のオペランドが評価された場合(i.e. すべて 真 のとき), 最後のオペランドを返します。 ④ に該当するため、最後のオペランド、今回は 65 を返します。 つまり、80 && 65は評価されると65になるのです。 if (80 && 65) ↓ -- if (true && true)を経由 -- ↓ if (65) 論理演算子はなくなったものの、例題の答えにたどり着けていないので補足をすると、 if 文も AND 演算子のときと同様に、かっこの中の式を評価し、Boolean に変換した結果で、if の中に入るかどうかを決定します。 if (65) { //if文がtrueと評価されるのでこちらに進みます。 console.log("ifの中です"); } else { console.log("elseの中です"); } 先ほどと同様、65はtruthyな値なので、この if 文全体は true となり、例題の答えは「'ifの中です'と表示される」でした。 例題1を振り返る 改めて一般的な論理式が含まれた if 文で復習してみましょう。 test1.js const math = 80 const science = 65 if (math >= 70 && science >= 70) { console.log('合格!') } else { console.log('不合格…') } ① 左から右にオペランドを評価します。 ② それぞれのオペランドで、それを Boolean に変換します。 評価対象が元々論理式の場合は、Boolean に変換するというより、評価結果そのものが true か false なので、 math >= 70の評価結果はtrue science >= 70の評価結果はfalseです。 と言うべきでしょうか。 if (math >= 70 && science >= 70) ↓ if (true && false) ③ もしも結果が false の場合、ストップしそのオペランドの本来の値を返します。 左から順に見ていって、左オペランドはtrueですが、右オペランドはfalseなので右側でストップし、本来の値(今回は評価結果のfalse)が返されます。 if (math >= 70 && science >= 70) ↓ -- if (true && false)を経由 -- ↓ if (false) -------------------------------- if (false) { console.log('ifの中です'); } else { //if文がfalseなのでこちらに進みます console.log('elseの中です'); } いかがでしょうか? 当然「かつ」と読んでいたとしても結果は変わりませんが、この記事を読むまで AND 演算子&&を「かつ」と考えてきた人は、左右のどちらもtrueであることで式全体が「真」と評価されるように、trueの方に重きを置かれがちですが、③ で見てきた通り、プログラムはfalseを探すことに一生懸命になっていますね。 着眼点が異なりますね。 この違いに慣れるまでは少し大変かもしれませんが、慣れてしまえば自然と読めてくるようになります。 OR 演算子|| OR 演算子||は、AND 演算子&&の③④の太字部分を反転させたものです。 ① 左から右にオペランドを評価します。 ② それぞれのオペランドで、それを Boolean に変換します。 ③ もしも結果が true であれば、停止しオペランドの本来の値を返します。 ④ もしもすべての他のオペランドが評価された場合(i.e. すべて 偽 のとき), 最後のオペランドを返します。 例題を見ながら流れを確認していきましょう。 [例題3] 以下のコードを実行すると、 console にどのように出力されるでしょうか? test3.js if (0 || 0.1) { console.log('ifの中です'); } else { console.log('elseの中です'); } AND 演算子のときほど丁寧には解説しませんが、 0 は falsy な値なので false に、 0.1は truthy な値なのでtrueに変換されます。 左から順に評価し、trueを探しにいきます。 左オペランドはfalseですが、右オペランドがtrueなので、ここで処理がストップし、本来の値0.1が返されます。 test3.js if (0 || 0.1) ↓ -- if (false || true)を経由 -- ↓ if (0.1) -------------------------------- if (0.1) { //if文がtrueと評価されるのでこちらに進みます。 console.log('ifの中です'); } else { console.log('elseの中です'); } OR 演算子||は、1つ1つtrueを探すので、「または」のように「どちらかが」という文脈には沿っていますね。 役立つ場面 論理演算子を「かつ」「または」ではなく、プログラム本来の振る舞いで意識できると役立つ場面を紹介します。 React の条件付きレンダー React の JSX で使える書き方紹介の中に、AND 演算子&&が出てきます。 sample.jsx return ( <div> <h1>Hello!</h1> {unreadMessages.length > 0 && <h2> You have {unreadMessages.length} unread messages. </h2> } </div> ); これが動作するのは、JavaScript では true && expression は必ず expression と評価され、false && expression は必ず false と評価されるからです。 条件付きレンダー – React ここまで読んでくれた方であれば、上記解説の内容を既にご自分で理解できるようになっていると思いますが、 AND 演算子&&は左から順にfalseを探しにいきます。 左オペランドがtrueなら右オペランドを見にいきます。 右オペランドの HTML タグは truthy なので、最後の要素である右オペランドのHTMLタグが返される(=表示される) 左オペランドがfalseならそこで処理はストップし、falseを返すため、右オペランドのHTMLタグは表示されない という流れですね。 OR 演算子を用いた代入 a = b || cのような OR 演算子||を用いた代入はよく見かけます。 例えば、メモアプリの投稿フォームで、 タイトルを入力して投稿したらそのタイトルを タイトルを空欄のまま投稿したら現在日時に置き換えてデータベースに保存する このような処理を考えてみましょう。 memo.js const defaultTitle = dateTimeFunction(); // '20220116_235940'などの現在日時を返す関数とする const enteredTitle = formData.title; // ユーザーがメモ投稿フォームのタイトル欄に入力した内容 const title = enteredTitle || defaultTitle; 右オペランドが必ずtruthyになるように文字列を与えることで、 左オペランドのenteredTitleが何かしらの文字列なら、そこで処理はストップし、enteredTitleの中身を返す 左オペランドのenteredTitleが''(空文字)なら、右オペランドのdefaultTitleの中身を返す となります。 他にも、a = a || bのように、 aがtruthyならa aがfalsyならb を代入するものもあります。 (厳密には異なりますが、省略形の論理和代入||=なんてものもあったりしますが、滅多に出てきませんのであまり気にしないで大丈夫です。) まとめ 論理演算子の左右のオペランドは、どのような値でもtrueかfalseに評価できることから、必ずしも論理式である必要はありません。 ①〜④ のルールを覚えておくことで、&&や||の左右に複雑なものが含まれていても、コードリーティング等で不用意に臆することがなくなるでしょう。 少々アカデミックな堅苦しい内容となりましたが、皆様のプログラミング学習のお役に立てばこの上なく嬉しく思います。 参考文献 オペランド (operand)とは | 「分かりそう」で「分からない」でも「分かった」気になれる IT 用語辞典 論理演算子 | 現代の JavaScript チュートリアル 論理積 (&&) - JavaScript | MDN 論理和 (||) - JavaScript | MDN Truthy (真値) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN Falsy (偽値) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN 条件付きレンダー – React
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】条件分岐 if文 gets to_iメソッド

※初心者向け ※アウトプット練習の為 開発環境 rails 6.0.4.4 ruby 2.6.5 問題内容 ターミナルから数字を入力して、数字に応じて以下のように出力するプログラムを書いてください。 ・10以下なら10以下の数字です ・10より大きい数値なら10より大きい数字です ・10以下でかつ0以下なら0以下の数字です ソースコードは以下の雛形を使ってください。 input = gets.to_i # ここからソースコードを書いてください 解答 input = gets.to_i if input <= 0 puts "0以下の数字です" elsif input <= 10 puts "10以下の数字です" else puts "10より大きい数字です" end 解説 ①ターミナルから数値を入力する書き方 ②条件分岐の書き方 の2つに分けて解説します。 ①ターミナルから数値を入力する書き方 ターミナルから数値を入力するにはgetsというメソッドを使います。このgetsメソッドを使って入力した値は全て文字列になります。そのためターミナルでは数字を入力しても、プログラムで使うときには文字列に変換されてしまいます。 そこでgetsの値をto_iメソッドを使って数値に変換します。 input = gets.to_i ②条件分岐の書き方 条件分岐はif文を使います。今回は3つのパターンで条件を分けるため、elsifとelseも使います。 if 条件1 # 条件1のときの処理 elsif 条件2 # 条件2のときの処理 else # 条件3のときの処理 end 今回の条件は数値の比較です。比較には<や==などの比較演算子を使います。 今回は10以下や0以下という比較なので、<=を使います。 =を付けた場合は以下や以上という意味になります。 input <= 10 今回の問題で難しいのは、3つの条件のうちどの条件から記載するかということです。 if文は先に書いた条件から判断していきます。そのため上の条件に当てはまったら、たとえ下の条件に当てはまっても、下の条件の処理はスルーされます。 今回の問題で以下のように書くとどうなるか考えてみましょう。 if input <= 10 puts "10以下の数字です" elsif input <= 0 puts "0以下の数字です" end このとき、inputが-1だったとすると、最初の条件式にも当てはまってしまい、10以下の数字ですと出力されます。本来は0以下の数字ですと出力されなければいけません。 よって正解は条件式の順番を入れ替えた以下になります。 if input <= 0 puts "0以下の数字です" elsif input <= 10 puts "10以下の数字です" end 10以下でなければ10より大きいため、10より大きい数値の場合の条件はelseのあとに書きます。 if input <= 0 puts "0以下の数字です" elsif input <= 10 puts "10以下の数字です" else puts "10より大きい数字です" end 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

円の方程式/円周率/ルート/切り捨て/切り上げ(Ruby)

Ruby3.1 MathモジュールPI Mathモジュールsqrt Floatクラスfloor Floatクラスceil xy軸の座標で(0,0)を中心点とする 円の方程式  x² × y² = 半径² #円周率 p = Math::PI puts p # => 3.141592653589793 #平方根を求める方法:√2の場合 Math.sqrt(2) # => 1.4142135623730951 #小数点以下切り捨て p.floor # => 3 #小数点以下切り上げ p.ceil # => 4
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails5.2.6で複数モデルのDM機能(ActionCable)を実装

はじめに DM機能でActionCableを使ってみた。 ActionCableを使えばページをリロードしなくてもメッセージがリアルタイムに表示されるのでかっこいい。 お世話になった記事 ほとんど知識がなかったので下記のサイトを参考にさせていただきながら作成しました。 リアルタイムチャットは誰でもつくれる~Action CableでDM機能を作ろう~ [Rails5.2 ActionCable]シンプルなチャットアプリを作ってみた!! Rails 5 + ActionCableで作る!シンプルなチャットアプリ(DHH氏のデモ動画より) 開発環境 ruby 2.6.3 Rails 5.2.6 前提条件 DM機能を一から作っているので前半不要な方は読み飛ばしてください。 今回はユーザーIDを用いて「誰とチャットしているのか、誰が発言しているのか」を明確にするため、以下のようなER図で開発します。 *User・・・deviseを使用 *Room・・・トークルーム *Message・・・1対1でのやり取り *RoomUser・・・中間テーブル RoomとUserをつなげるイメージ。Userが2人入る。Room1つに対してRoomUserは2つできる感じ。 作成開始 rails new rails new ActionCable jqueryの導入 Gemfile gem 'jquery-rails' $ bundle install application.jsに下記2行を追加 app/assets/javascripts/application.js //= require rails-ujs //= require activestorage //= require turbolinks //= require jquery *追加* //= require jquery_ujs *追加* //= require_tree . ユーザー認証機能の導入 Gemfile gem 'devise' $ bundle install deviseの初期設定 $ rails g devise:install モデルの作成+カラム(name)の追加 $ rails g devise User name:string $ rails db:migrate nameカラムでログインできるようにする app/controllers/application_controller.rb class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) end end viewページの生成 今のままだと新規登録時にemailとpasswordを入力する項目しかないため。 ※http://localhost:3000/ $ rails g devise:views 新規登録画面の表示内容を編集 app/views/devise/registrations/new.html.erb : <!-- 追加 --> <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true %> </div> <!-- ここまで --> <div class="field"> <%= f.label :email %> : ログアウトボタンの表示 新規登録orログイン後はログアウトボタンがないと一生ログインしたままになるので、ログアウトボタンを表示させます。 app/views/layouts/application.html.erb : <body> <% if user_signed_in? %> <li> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> </li> <% else %> <li> <%= link_to "新規登録", new_user_registration_path %> </li> <li> <%= link_to "ログイン", new_user_session_path %> </li> <% end %> <%= yield %> </body> : これで、一度新規登録してみます。 Yay! You’re on Rails! が表示されればOKです。 必要モデルの作成 先ほどのER図を確認しながら、Roomモデル、RoomUserモデル、Messageモデルを作成していきます。必要なカラムも同時に追加。 (外部キーreference型で追加した方がいいのかと思いつつintegerで追加してしまった、、、 ?参考サイト Railsの外部キー制約とreference型について) $ rails g model Room name:string $ rails g model RoomUser user_id:integer room_id:integer $ rails g model Message user_id:integer room_id:integer text:string $ rails db:migrate モデルと必要カラムの作成が完了しました。 アソシエーションの設定 app/models/user.rb : has_many :messages, dependent: :destroy has_many :room_users, dependent: :destroy : app/models/room.rb class Room < ApplicationRecord has_many :messages, dependent: :destroy has_many :room_users, dependent: :destroy end app/models/room_user.rb class RoomUser < ApplicationRecord belongs_to :user belongs_to :room end app/models/message.rb class Message < ApplicationRecord belongs_to :user belongs_to :room end コントローラの作成 usersコントローラ・・・index,show roomsコントローラ・・・show $ rails g controller users index show $ rails g controller rooms show ルーティングの設定 config/routes.rb root to: 'users#index' devise_for :users resources :users, only: [:show] resources :rooms, only: [:show, :create] ユーザー関連のページを表示させる ユーザー一覧ページ ユーザーの一覧をまとめて表示させるページ。 ここから、ユーザー詳細ページに飛ぶ。 app/controllers/users_controller.rb def index @users = User.all end def show end app/views/users/index.html.erb <h1>ユーザー一覧ページ</h1> <% @users.each do |user| %> <%= link_to user.name, user_path(user.id) %> <% end %> ユーザー詳細画面を表示 ユーザー詳細画面から、トークを始められるようにする app/controllers/users_controller.rb : def index @users = User.all end def show @user = User.find(params[:id]) #RoomUserモデルから自分のものを検索 @current_user_room_user = RoomUser.where(user_id: current_user.id) #RoomUserモデルから今開いているページのユーザーのものを検索   @user_room_user = RoomUser.where(user_id: @user.id) #もし今開いてるユーザーページが自分のページじゃなかったら unless @user.id == current_user.id #自分が関係あるRoomUserをeachで引っ張り出してくる @current_user_room_user.each do |cu| #かつ、今開いているページのユーザーに関係あるRoomUserをeachで引っ張り出してくる @user_room_user.each do |u| #もし一致するものがあったら if cu.room_id == u.room_id then #すでに部屋があるということ @is_room = true #そのroomのid @room_id = cu.room_id end end end #一致する部屋がなかったら unless @is_room #新しく作る @room = Room.new @room_user = RoomUser.new end end end : app/views/users/show.html.erb <h1>ユーザー詳細ページ</h1> <h2>ユーザー名</h2> <%= @user.name %> <h2>トーク関連</h2> <% if @is_room == true %> <%= link_to "トークを始める", room_path(@room_id) %> <% else %> <!-- roomsテーブルに情報を送信 --> <%= form_with model: @room, local: true do |f|%> <!-- room_usersテーブルに情報を送信 --> <%= hidden_field_tag 'room_user[user_id]', @user.id %> <%= f.submit "チャットを始める", class: "send" %> <% end %> <% end %> すでにトークルームがある時=> @is_room = true  トークルームへのリンクへ飛ぶ 新しくトークを始める時=> form_with でルームを新しく作る。RoomUserも一緒に作る。 トークルームを作る トークルームとRoomUserを作る app/controllers/rooms_controller.rb class RoomsController < ApplicationController def create @room = Room.create # RoomUserを2つ作る # 自分のRoomUserを作る @join_current_user = RoomUser.create(user_id: current_user.id, room_id: @room.id) # 相手のRoomUserを作る @join_user = RoomUser.create(join_room_params) redirect_to room_path(@room) end def show @room = Room.find(params[:id]) end private def join_room_params params.require(:room_user).permit(:user_id, :room_id).merge(room_id: @room.id) end end 1つのRoomに2つのRoomUserが作られた状態ができた。2人のuserを呼び出す。 トークルームでメッセージを表示させる app/controllers/rooms_controller.rb : def show @room = Room.find(params[:id]) <!-- 追加 --> #roomに関するRoomUserが存在していれば if RoomUser.where(user_id: current_user.id, room_id: @room.id).present? @messages = @room.messages @message = Message.new @room_users = @room.room_users else redirect_back(fallback_location: root_path) end <!-- ここまで --> end : ビューページを作る app/views/rooms/show.html.erb <h1>ルーム詳細ページ</h1> <h2>参加者</h2> <!-- roomに入っているroom_userは2人いるのでeachで引っ張る --> <% @room_users.each do |e| %> <%= link_to e.user.name, user_path(e.user_id) %> <% end %> <h2>トーク</h2> <!-- 入力フォーム --> <!-- form_withだと余計なものが生成されるので<form>タグで実装 --> <form> <input type="text" data-behavior="room_speak"> </form> <% if @messages.present? %> <% @messages.each do |m| %> <div> <%= m.text %> <%= m.created_at.strftime("%Y-%m-%d %H:%M") %> </div> <% end %> <% end %> 部分テンプレで切り出し 先ほどのroom/show.html.erbから メッセージを表示させる部分だけ部分テンプレートとして切り出します。 app/views/rooms/show.html.erb : <% if @messages.present? %> <% @messages.each do |m| %> <!-- 削除 --> <div> <%= m.text %> <%= m.created_at.strftime("%Y-%m-%d %H:%M") %> </div> <!-- ここまで --> <% end %> <% end %> app/views/rooms/show.html.erb <% if @messages.present? %> <% @messages.each do |m| %> <!-- 追加 --> <%= render "messages/message" %> <!-- ここまで --> <% end %> <% end %> : viewsフォルダ直下に、messagesフォルダと_message.html.erbを作成します。 app/views/messages/_message.html.erb : <div> <%= m.text %> <%= m.created_at.strftime("%Y-%m-%d %H:%M") %> </div> : ここまででUserモデル、Roomモデル、RoomUserモデルの作成、定義と下準備が完了したので やっと、ActionCable導入へと移ります! チャネルを作成する $ rails g channel room speak speakはメソッド名です。 クライアントサイドの処理をするファイル app/assets/javascripts/channels/room.coffee app/assets/javascripts/cable.js サーバーサイドの処理をするファイル app/channels/room_channel.rb 以上3ファイルをいじりながら実装していきます。 設定 クライアント-サーバー間のやり取りを設定 app/channels/room_channel.rb class RoomChannel < ApplicationCable::Channel def subscribed #クライアントが受信するストリームを設定 stream_from "room_channel" #追加 end : app/assets/javascripts/channels/room.coffee : speak: (message) -> #performメソッドでブラウザから入力されたデータをサーバーサイドへ送信 @perform 'speak', message: message # 'keypress' キーが押された時発火する $(document).on 'keypress', '[data-behavior~=room_speak]', (event) -> # key13= returnキー if event.keyCode is 13 # event.target.valueは入力されたデータ App.room.speak event.target.value event.target.value = '' event.preventDefault() : returnキーを押したときに発火されサーバーサイドへデータが送信されるようにする。 受け取ったデータをアラートで表示してみる app/assets/javascripts/channels/room.coffee : received: (data) -> alert data['message'] # Called when there's incoming data on the websocket for this channel : フォームに入力したデータが、アラートで表示されました。 今度はブラウザ上に表示してみる app/assets/javascripts/channels/room.coffee : received: (data) -> alert data['message'] #削除 $('#messages_all').append data['message'] #追加 : ブラウザに表示されました。データベースに保存していないので、ページ更新すると消えてなくなります。 次にMessageモデルにデータを保存する処理を作っていきたいと思います。 データ保存&非同期処理 Active Jobというものを導入して、非同期処理できるようにする。 room_channel.rbのspeakアクションを書き換える app/channels/room_channel.rb def speak(data) # current_userは使えないので別途定義するか、rooms/showページからidを渡す # rooms/show.html.erbのdiv idからmessage,user_id,room_idを受け取る Message.create! text: data['message'], user_id: data['user_id'], room_id: data['room_id'] end Messageモデルにデータを保存するとき、messageの内容だけでなく、user_idとroom_idを受け取り生成する必要があります。 user_idとroom_idが渡るように記述を変更 app/views/messages/_message.html.erb <% if @messages.present? %> <% @messages.each do |m| %> <div> <%= m.text %> <%= m.user.name %> <!-- 追加 --> <%= m.created_at.strftime("%Y-%m-%d %H:%M") %> </div> <% end %> <% end %> app/views/rooms/show.html.erb : <h2>トーク</h2> <!-- 入力フォーム --> <div id="message" data-room_id="<%= params[:id] %>" data-user_id="<%= current_user.id %>">    <!-- form_withだと余計なものが生成されるので<form>タグで実装 -->    <form>      <input type="text" data-behavior="room_speak">    </form> </div> : app/assets/javascripts/channels/room.coffee : speak: (message) -> #performメソッドでブラウザから入力されたデータをサーバーサイドへ送信 @perform 'speak', { message: message, room_id: $('#message').data('room_id'), user_id: $('#message').data('user_id') } : ブロードキャスト処理の実行 rails g job MessageBroadcast 生成されたファイルを編集していきます。 app/models/message.rb #無記入投稿とエンター長押し連続投稿を防ぐ validates :text, presence: true #MessageBroadcastJobを走らせるタイミングはMessageがcreateされた後 after_create_commit {MessageBroadcastJob.perform_later self} Messageがクリエイトされた後、ブロードキャスト処理が走るように一文を記述します。 app/jobs/message_broadcast_job.rb class MessageBroadcastJob < ApplicationJob queue_as :default def perform(message) ActionCable.server.broadcast "room_channel", message: render_message(message) end private def render_message(message) ApplicationController.renderer.render partial: 'messages/message', locals: { message: message } end end 完成です 課題 current_userが渡らない問題 deviseを導入すると使えるcurrent_user、そのままActionCableに渡せない問題。 解決策は二つありそうです。 ①viewページからcurrent_userのIDを渡す 今回はこっちで実装しました ?参考にさせていただいたサイト Action Cableへのidの受け渡し ②ActionCableのconnection.rbで別途current_userを定義する ?参考にさせていただいたサイト Rails公式ドキュメント 【ActionCable】チャンネル接続/購読時にユーザ認証を行う ActionCableにおいてのcurrent_userについて読み解く|Rails デプロイするまで完成したかわからない 本当はブラウザを二つ開いてそれぞれ別のユーザーでログインして動作チェックをしたいんだけど、本番環境でないとできないので、ここで終わりです。 間違っている内容がありましたら、コメントでぜひ教えてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Elixir]RubyやRailsのメソッドは便利なものが多いので、それらをElixirでも使えるようにしたライブラリをリリースしました。

多言語を習得する際の困り事 「Rubyだと配列からnullを排除する時 compactで出来たけど、Elixirだとどう書くんだろう。。 あれ、Enum.select って無いのか Enum.filterを使えばいいのね!」 Elixirを学習中に、上記のような ちょっと調べればわかるけれども、ちょっと調べないといけないような事が、ちょくちょく発生しました。 RubyやRailsのEnumerable系メソッドをElixirでも使えるようにしました! RubyやRailsはその歴史の長さや、コミュニティの厚さにより、便利なmethodや直感的なaliasが多数定義されてます。 それらの資産を有効活用できないかと思い、REnumという、ElixirのmoduleをRuby/Rails風に拡張したライブラリをリリースしました。 なぜ、Enum(Enumerable)等に焦点を当てたかというと、Elixirの得意とするデータ変換にはEnum(Enumerable)等の拡張がもっとも有意に働くと思ったからです。 ElixirはRubyの文法の影響を大きく受けた言語でもあるので、Ruby => Elixirを学ぶ方はとても多いと感じております。そのような方の助けになりましたら幸いです。僕もそのうちの一人です。 機能紹介 RubyのEnumerableから移植してきたおすすめな関数達 compact(enumerable) 与えられたenumerableからnil以外のすべての要素を排除。 iex> [1, nil, 2, 3] iex> |> REnum.compact() [1, 2, 3] each_slice(enumerable, amount, func) amount毎に与えられたenumerableを分割し、各ブロックにfuncを適応してenumerableを返却。 iex> ["a", "b", "c", "d", "e"] iex> |> REnum.each_slice(2, &IO.inspect(&1)) # ["a", "b"] # ["c", "d"] # ["e"] ["a", "b", "c", "d", "e"] tally(enumerable) 等しい要素をkey, それらのカウントをvalueに持つマップを返却。 iex> ~w(a c d b c a) iex> |> REnum.tally() %{"a" => 2, "c" => 2, "d" => 1, "b" => 1} grep(enumerable, func_or_pattern) 与えられた関数やパターンに一致する要素を選んで返却。 iex> ["foo", "bar", "car", "moo"] iex> |> REnum.grep(~r/ar/) ["bar", "car"] iex> 1..10 iex> |> REnum.grep(3..8) [3, 4, 5, 6, 7, 8] Alias select(filterのalias) detect(findのalias) each_with_object(reduce/3のalias) inject(reduceのalias) include?(member?のalias) RailsのActiveSupportから移植してきたおすすめな関数達 exclude?(enumerable, element) Enum.member?の逆。elementがenumerableに含まれない場合にtrueを返却。 iex> REnum.exclude?([2], 1) true iex> REnum.exclude?([2], 2) false without(enumerable, elements) elements を除いて enumerable を返却。 iex> REnum.without(1..5, [1, 5]) [2, 3, 4] iex> REnum.without(%{foo: 1, bar: 2, baz: 3}, [:bar]) %{foo: 1, baz: 3} in_order_of(map_list, key, series) 元の map_list の要素のkeyに基づき、series で提供される順序に設定されたリストを返却。 iex> payments = [ ...> %Payment{dollars: 5, cents: 99}, ...> %Payment{dollars: 10, cents: 0}, ...> %Payment{dollars: 0, cents: 5} ...> ] iex> REnum.in_order_of(payments, :cents, [0, 5]) [ %Payment{cents: 0, dollars: 10}, %Payment{cents: 5, dollars: 0} ] pluck(map_list, keys_or_key) map_list から、与えられたkeysのvalueを返却。 iex> payments = [ ...> %Payment{dollars: 5, cents: 99}, ...> %Payment{dollars: 10, cents: 0}, ...> %Payment{dollars: 0, cents: 5} ...> ] iex> REnum.pluck(payments, [:dollars, :cents]) [[5, 99], [10, 0], [0, 5]] iex> REnum.pluck(payments, :dollars) [5, 10, 0] iex> REnum.pluck([], :dollars) [] blank?(any) any が空白、偽、空、または空白文字列である場合にtrueを返却。 例えば、nil, "", " ", [], {}, falseはtrueに該当する。 iex> REnum.Utils.blank?(%{}) true iex> REnum.Utils.blank?([1]) false iex> REnum.Utils.blank?(" ") true present?(any)はblank?の偽を示す。 その他、個人的に解せなかった部分を解消した関数達 find_index_with_index(enumerable, func) find_indexの際にfuncの第2引数としてcurrent_indexを渡せる用にした関数。 iex> REnum.find_index_with_index(1..3, fn el, index -> ...> IO.inspect(index) ...> el == 2 ...> end) # 0 # 1 1 list_and_not_keyword?(enumerable) keyword listとlistを区別する関数。 iex> REnum.list_and_not_keyword?([1, 2, 3]) true iex> REnum.list_and_not_keyword?([a: 1, b: 2]) false map_and_not_range?(enumerable) is_map(1..3) == trueなのが解せなくて作った関数。 iex> REnum.map_and_not_range?(%{}) true iex> REnum.map_and_not_range?(1..3) false REnumは既存のEnum関数もすべて滞りなく使えます。 REnumはメタプログラミングにより、,ElixirのEnumや対応するEnumerable系のfunctionsを全て移譲しています。 なので、以下動作も問題なく使うことが出来ます。 iex> list = [1, 2, 3] iex> REnum.find(list ,fn x -> rem(x, 2) == 1 end) == Enum.find(list ,fn x -> rem(x, 2) == 1 end) true iex> REnum.sort(list) == Enum.sort(list) true コード内のEnum.*をREnum.*に置き換えても問題なく動くはずです。 終わりに 実装に関しては手が空いたタイミングで少しずつ拡充していこうと思っています。現在はEnumerable系の実装が終わり、List系の実装を開始しております。 もしよろしければスター等頂けましたら幸いです。コントリビュートも大歓迎です。 ロードマップは以下通り。 - [x] 0.1.0 - REnum.Enumerable.Native - REnum.Enumerable.Ruby - REnum.Enumerable.Support - REnum.List.Native - REnum.Map.Native - REnum.Range.Native - REnum.Stream.Native - REnum.Utils - [x] 0.2.0 - REnum.Enumerable.ActiveSupport - [ ] 0.3.0 - REnum.List.Ruby - [ ] 0.4.0 - REnum.List.ActiveSupport - [ ] 0.5.0 - REnum.Map.Ruby - REnum.Map.ActiveSupport - [ ] 0.6.0 - REnum.Range.Ruby - REnum.Range.ActiveSupport - [ ] 0.7.0 - REnum.Stream.Ruby - REnum.Stream.ActiveSupport
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails newでコケたときの備忘 m1 mac macOS 12.1

書いた理由 備忘のため。 ググってもダイレクトに出てこなかったので、同じところで詰まっている人の参考になれば。 起こったこと rails new を叩いたら以下のメッセージでコケた /Users/hoge/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/bootsnap-1.9.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require': dlopen(/Users/hoge/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/bootsnap-1.9.4/lib/bootsnap/bootsnap.bundle, 0x0009): tried: '/Users/hoge/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/bootsnap-1.9.4/lib/bootsnap/bootsnap.bundle' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/local/lib/bootsnap.bundle' (no such file), '/usr/lib/bootsnap.bundle' (no such file) - /Users/hoge/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/bootsnap-1.9.4/lib/bootsnap/bootsnap.bundle (LoadError) 解決したこと railsのアップデート gem install rails 補足 rails tutorialを進めるにあたって、railsのバージョンを古いもので指定で入れていたので、 そのあたりがm1 macと折り合いが悪かったのではないかと推定。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

{Rails}uninitialized constant * (NameError)と出た場合の対処法

①やりたいこと rails cでレコードを確認&作成したいが、uninitialized constant User (NameError)と出てしまう。※Userはモデル名です。 ②エラー内容 % rails c Running via Spring preloader in process 18643 Loading development environment (Rails 6.1.4.4) irb(main):001:0> User.all (irb):1:in `<main>': uninitialized constant User (NameError) ③原因 uninitialized constant * (NameError)は、Rubyで「定数やclassが定義されていない」ことを意味しています。 ファイル名の記述間違いなどで、呼びたいクラス名を記述できていない場合などで発生します。 この場合はコントローラー名が間違っていたみたいです。 ④解決策 ターミナルを遡ってみると、コントローラーを作成しているところまで来たのですが、、 usersじゃなくて正しくはUsersでした。 % rails g controller users Running via Spring preloader in process 14608 create app/controllers/users_controller.rb invoke erb create app/views/users invoke test_unit create test/controllers/users_controller_test.rb invoke helper create app/helpers/users_helper.rb invoke test_unit invoke assets invoke scss create app/assets/stylesheets/users.scss なので、間違えて作成したコントローラーを消して、新しくコントローラーを作成し直す必要があります。 調べてみたら、% rails destroy controllerで消すことができるとのこと。 % rails destroy controller users Running via Spring preloader in process 19108 remove app/controllers/users_controller.rb invoke erb remove app/views/users invoke test_unit remove test/controllers/users_controller_test.rb invoke helper remove app/helpers/users_helper.rb invoke test_unit invoke assets invoke scss remove app/assets/stylesheets/users.scss が、ここで問題発生。ちゃんと消えたか確認するためにapp/controllersを開いてみると、users_controllerがまだ表示されていました。VScodeだとこの表示消えないのかな。。 ファイルの所で右クリックしてusers_controllerだけ削除してみました。 この状態で再度 % rails g controller Usersでコントローラーを作成しようとすると、作成自体はできますが下の方に The name 'UsersHelper' is either already used in your application or reserved by Ruby on Rails. と出ます。仕方ないので users_helperも右クリックして削除項目を選びます。その後% rails g controller Usersを実行して、controllerが作成されたのを確認してから、rails cコマンドを実行。その結果が下記です。 % rails c Running via Spring preloader in process 19669 Loading development environment (Rails 6.1.4.4) irb(main):001:0> User.all User Load (0.6ms) SELECT `users`.* FROM `users` => [#<User:0x00007fafca4c9538 id: 2, name: "you", email: nil, pass: nil, image: nil, created_at: Fri, 14 Jan 2022 04:40:49.121048000 UTC +00:00, updated_at: Fri, 14 Jan 2022 04:40:49.121048000 UTC +00:00>, #<User:0x00007fafce64c690 id: 3, name: "he", email: nil, pass: nil, image: nil, created_at: Fri, 14 Jan 2022 04:41:44.970457000 UTC +00:00, updated_at: Fri, 14 Jan 2022 04:41:44.970457000 UTC +00:00>] irb(main):002:0> 無事レコード一覧が出せました! あとがき:コントローラー名の誤りという見立ては間違ってないのですが、% rails destroy controllerでちゃんと削除できなかったのだけがなんとも。VScodeだと消えないんですかね〜。。 有識者の方ご意見くださると嬉しいです。 ただ目的としていたレコードの確認はできたので、結果オーライ?ではあります。 開発環境 mac OS バージョン11.6 Rails 6.1.4.4 Ruby 3.0.3 MYSQL 0.5 エディタ VScode
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング言語別のswitch文

変更履歴 2022/1/16 Rubyの「case in」追加 C言語の文字列比較あたりの記述修正 まとめの表にbreakの有無追加 初めに switch文に初めて触れたのは、業務改善でC言語を使った時です。 場合によってifの分岐より簡潔に記述できるswitch文は好きな処理です ライブラリが豊富で汎用性があるpythonを使っていて 「switch文なぜなんでないんだ・・・。」と、ずっと引っかかっていました。 そんなことを忘れかけていた中、twitterを見ている時に pythonのバージョン3.10.0にてswitchと同じ動作をする matchが追加されていることを、先日知りました。(リリースが2021年10月の様です) 今まで長文まとめるの時間かかるな、そんないい記事書けないなと アウトプットはすぐ投稿できるTwitterに逃げていましたが switch文でQiitaデビューしようと思いました、暖かい目でご覧ください 書くこと match関数とif関数の違い(python) プログラミング言語でのswitch文の違い(C言語・Ruby・VBA) 書かないこと 言語ごとの深掘り(数値の場合どうなるか等) コード内容 色で英語の文字列を日本語で出力 変数名:color colorが"red"の場合、出力は"赤" colorが"white"か"black"の場合、出力は"パンダの色"(複数条件) コード(GitHub) 動作環境 macOS Monterey 12.0.1 プログラミング言語のバージョンはそれぞれに記載 matchとifの違い(python3.10.0) pythonではmatchとなり、 変数colorの中身によって処理を切り替える。 下の処理はcolorが"black"なので"パンダの色"と出力する。 この様に一つの条件で複数の結果があるような処理を書きやすい match.py color = "black" match color: case "red": print("赤") case "blue": print("青") case "black" | "white": print("パンダの色") case _: print("その他") # 出力:"パンダの色" 特徴 matchやcaseの後ろに:(コロン)をつける endや breakのように終了を明記しない 「match > case > 処理 」にインデントが必要(つけないとエラーになる) caseが複数ある場合はバーチカルライン|でつなぐ matchをifで書くと if1.py color = "black" if color=="red": print("赤") elif color=="blue": print("青") elif color=="black" or color=="white": print("パンダの色") else: print("その他") # 出力:"パンダの色" ifは毎度、条件式(変数名と式)を記述する必要があります。 matchの様に1つの値に複数の判定・処理がある場合、記述が増えます。 ただしifにもメリットがあります。 if2.py color = "red" val = 50 if color == "red" and val <= 20: print("色は赤で値が20以下です") elif color == "blue" or val > 20: print("色は青であるか値が20を超えています") else: print("その他") # 出力:"色は青であるか値が20を超えています" 毎回条件式を記述するのでandやorを使うことで 複数の値・条件を指定して判定を組むことができます 以下で別言語のswitch文と特徴を記載します C言語(gcc13.0.0) switch文 switch→case 一番最初に使ったswitch文 ターミナルでgcc switch.cでコンパイル後、./a.outで実行 switch.c #include <stdio.h> enum color { red, blue, black, white, }; int main(void){ enum color color; color = black; switch(color){ case red: printf("赤"); break; case blue: printf("青"); break; case black: case white: printf("パンダの色"); break; default: printf("他の色"); } return 0; } // 出力:"パンダの色" 特徴 文字列の比較、他の言語の様にできない caseの後は数値 enumで"black"は2のように文字列を数値をして扱う感じ break;を入れないとcaseが一致していない処理も実行される 複数条件はcaseを重ねる Ruby 【case when】 (2.6.5) RubyはCase文(case→when) ruby color = "white" case color when "red" print("赤") when "blue" print("青") when "black", "white" print("パンダの色") else print("その他") end # 出力:"パンダの色" 特徴 endで終了を書く必要がある インデントなしでも処理できる 複数条件はカンマ(,) Ruby 【case in】 (3.0.0) 2.7で導入 簡単な使い方ではcase whenとほぼ同じ case_in.rb color = "black" case color in "red" then print "赤" in "blue" then print "青" in "black" | "white" then print "パンダの色" else print ("その他") end # 出力:パンダの色 特徴 thenをつけると1行で記述可能(whenも) 複数条件はバーチカルライン(|) VBA(Excel for Mac 16.56) Select Case文(Select Case → Case) Rangeを使ってエクセルのA1から値を取得 右隣のB1に出力 VBA Dim color As String color = Range("A1") Select Case color Case "red" Range("B1") = "赤" Case "bule" Range("B1") = "青" Case "white", "black" Range("B1") = "パンダの色です" Case Else Range("B1") = "その他" End Select ' 出力:"パンダの色" 特徴 End Selectで閉じる インデントはなしでも動作する 複数条件はカンマ(,) まとめ 言語ごとの書き方・動作 言語 開始 条件 break 終了 インデント 複数条件記述 python match color: case なし なし 必要 バーチカルライン(|)でつなぐ C switch(color){ case あり 必要(}) 不要 caseを複数行で記述 Ruby case color when なし 必要(end) 不要 カンマ(,)でつなぐ Ruby case color in なし 必要(end) 不要 バーチカルライン(|)でつなぐ VBA Selece Case Case なし 必要(End Select) 不要 カンマ(,)でつなぐ 思ったこと 改めて言語によって記述方法、できることに違いがあるということがわかった 新たにC言語をPCで動作させることができる様になった コメントで不足してるところを補ってもらえた 言語化してまとめるのは難しい(言語をまたぐと特に) 最後に 記事にするのは大変だけど、記事にするために動かすだけでなく どうしてこうなるのかとか、他に方法がないかなど調べることで 知識の幅を増やすことができました またQiita投稿しようと思います!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む