20210509のRubyに関する記事は23件です。

【Ruby】任意の3つの数値の合計を出力するメソッドを作成せよ。 ただし、同じ数が含まれている場合は 合計にカウントしない。

def lone_sum(ary) # 配列から、重複しない要素のみ取り出す uniq_nums = [] ary.each do |num| count = 0 ary.each do |i| if num == i count += 1 end end if count < 2 uniq_nums << num end end # uniq_nums配列内の合計 sum = 0 uniq_nums.each do |unique_num| sum += unique_num end puts sum end lone_sum([3, 2, 3]) # 出力結果→2 lone_sum([3, 2, 1]) # 出力結果→6 3〜14行目で重複しない値のみ取り出す処理を、 17〜20行目で重複しない値のみになった配列内の合計を求める処理を行っている。 たとえば、lone_sum([3, 2, 3])でメソッドを呼び出した場合を考えてみて!。 この場合、4行目で最初にnum=3となる。その後6行目でi=3, 2, 3となり、 それぞれに対してnum=iとなったとき、つまり重複したときにcountが増えるようになる。 そして11行目で重複した値が1つのときだけuniq_nums配列に値を追加している。 num=3のときはcount=2となるのでuniq_nums配列に値は追加されない。 これを後2回繰り返した結果、uniq_nums配列には2だけが追加される。 そして18行目以下でuniq_nums配列内の合計を求める。 この場合、sum = sum + 2、つまりsum = 0 + 2となります。最終的に合計は2と出力される。 ※↓別のやり方 def lone_sum(numbers) numbers .tally .filter_map { |number, count| number if count == 1 } .sum end lone_sum([3, 2, 3]) #=> 2 lone_sum([3, 2, 1]) #=> 6
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyの条件分岐について

Rubyの条件分岐はifで表し構文は次のようになります。 if 条件1 #条件1が真の場合に実行したい処理 elsif 条件2 #条件2が真の場合に実行したい処理 elsif 条件3 #条件3が真の場合に実行したい処理 else #それ以外の処理 end elsifは任意の数だけ書くことができます。 elsifやelseは不要な場合は省略することができます。 例として テストの点数scoreによって、通知表の成績をターミナルに出力するプログラムを書きます。 90点以上 A 80点以上 B 60点以上 C 60点未満 D と出力されるようにします。 score = 90 if score >= 90 puts 'A' elsif score >= 80 puts 'B' elsif score >= 60 puts 'C' else puts 'D' end これをターミナルで実行すると testoMacBook-Air:~ test$ ruby if.rb A scoreは90なのでAが出力されました。 もしscore=59などにした場合は60点未満なのでDが出力されます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

正規表現が苦手な人、お集まりください。

はじめに あなたは正規表現は得意ですか?? 「はい、得意です!」と答える人は、そんなに多くないのかな?と思います。 自分は特に苦手で嫌いでした。。 このままではダメだと思い、正規表現の壁に立ち向かいました。 自分がもがいて手に入れた情報で、皆さんに少しでもいい情報を届けたれたら幸いです!! ※一番下に、正規表現に用いる記号一覧を載せてあるので参考にしてください! 正規表現とは 文字列とのパターンマッチを行うための小さな言語のことです。 正規表現を用いることで、ある文字列があるパターンに該当する文字列を含んでいるかを確認したり、パターンに該当する部分を検索できます。 パターンマッチ Regexp#=~ 正規表現にマッチした位置を返すときは、=~を使用する # マッチしたら、その位置を返す /[0-9]/ =~ 'ruby6' #=> 4 # マッチしない場合はnilを返す /[0-9]/ === 'ruby' #=> nil Regexp#=== あるパターンにマッチするかを調べるには、===を使用する # 0〜9の数字を含んでいるか /[0-9]/ === 'ruby' #=> false /[0-9]/ === 'ruby6' #=> true Regexp#match マッチすればMatchDataオブジェクトを返し、しなければ「nilを返す str = 'ruby6' if matched = /[0-9]/.match(str) p matched #=> "#<MatchData \"6"\>" end MatchDataから得られる情報は以下の通りです。 MatchData 変数 得られる値 MatchData#[0] $& 直前にマッチした文字列 MatchData#[1] $1 直前にマッチした正規表現の中の、最初の括弧にマッチした文字列 MatchData#pre_match $` 直前にマッチした文字列より前の文字列 MatchData#post_match $' 直前にマッチした文字列より後の文字列 式展開時の注意点 正規表現で、式展開を用いる際は必要に応じてエスケープしましょう! # エスケープする必要のある文字列 part = Regexp.escape('(incomplete)') /[^.]+#{part}\.txt/ #=> /[^.]+\(incomplete\)\.txt/ # 括弧がエスケープされる 文字クラス []で囲むことで文字クラスの指定が可能です。 [a-z] #=> aからzまでの文字 [\w] #=> 英数字a(A)〜z(Z)、0〜9 量指定子 直前パターンの繰り返しをします。 # 郵便番号の正規表現の場合 post_num = /\d{3}-\d{4}/ post_num === '123-4567' #=> true 先頭と末尾 先頭には\A、末尾には\zとして表現する。 # 携帯電話番号の正規表現の場合 phone_num = /\A\d{3}-\d{4}-\d{4}\z/ phone_num === '012-3456-7890' #=> true 指定位置からの正規表現 指定された文字列 str に対して 位置 pos から自身が表す正規表現によるマッチ /R.../.match?("Ruby") #=> true /R.../.match?("Ruby", 1) #=> false $& #=> nil グルービングと後方参照 ()によりグルービングをすることが可能。 後で、\1や\2のように参照することを後方参照と言います。 # 基本的な後方参照 /(text)\ to\ \1/ === 'text to text' #=> true # ラベル付きグルービングでの後方参照 /(?<num>[0-9+])[a-c\-]+\k<num>/ === '123-abc-123' #=> true 部分式呼び出し 後方参照と似ているが、グルーピングを再利用できる部分式呼び出しという参照方法がある。 # 部分式呼び出しの「\g<1>」は最初のグルーピングの式「[0-9+]」で置換される /([0-9+])-\g<1>-\g<1>/ === '012-3456-7890' #=> true 先読みと後読み 先読みとは、(?<=sample)は「"sample"という文字列と一致する箇所の直後」を表します。 また、後読みはその逆で直前になります。 また、否定文に関しては、文字通り肯定先(後)読みと逆の動作をします。 # 肯定先読み 'sampleApp'.scan(/sample(?=App)/) #=> ["sample"] # 肯定後読み 'sampleApp'.scan(/(?<=sample)App/) #=> ["App"] バックトラックの抑止 (?>)で正規表現を囲むことで、そこにマッチした部分でバックトラックを抑止できる。 /(?>\w+)[0-9]/ === 'ruby6' #=> false オプションの指定 以下の表を用いて、オプションを指定することでパターンマッチの挙動を変化させることが出来ます。 オプション 意味 i 大文字、小文字の区別をしない o 世紀表現リテラルが最初に評価された際に、一度だけ式展開を行う x 正規表現中の「#」を無視して、コメントとみなす m 「.」に改行もマッチさせる、複数行モード u 正規表現をUTF-8として解釈 s 正規表現をShift-JISとして解釈 e 正規表現をEUC-JPとして解釈 n 正規表現をASXIIとして解釈 # オプション無し %w(foo bar).map { |str| /#{str}/ } #=> [/foo/, /bar/] # オプション有り %w(foo bar).map { |str| /#{str}/o } #=> [/foo/, /foo/] 終わりに 正規表現は必ずと言っていいほど、最初はハマります。。 暗号のように見えてきて気が狂いそうですが、この記事を機に慣れていってくれることを願っています。! 参考(正規表現に用いる記号一覧) 1 2 ^ 行頭、改行文字の直後にマッチ $ 行末、改行文字の直前にマッチ \A 文字列の先頭にマッチ \Z 文字列の末尾にマッチ、改行文字なら改行の直前 \z 文字列の末尾にマッチ、改行でも常に末尾にマッチ \w 英数字[0-9A-Za-z_]にマッチ \W 英数字[0-9A-Za-z_]以外にマッチ \s 空白文字[\t\r\n\f]にマッチ \S 空白文字[\t\r\n\f]以外にマッチ \d 数字[0-9]にマッチ \D 数字[0-9]以外にマッチ \h 16進数に使われる文字[0-9A-Fa-f]にマッチ \b []の外では単語の境界、中ではバックスペースにマッチ \B 単語の境界以外にマッチ \G 直前にマッチした箇所の直後にマッチ . 改行を除く任意の1文字にマッチ [] 文字クラスの指定 [0-9] すべての数字にマッチ [^0-9] すべての数字以外にマッチ * 直前の正規表現の0回以上の反復、できるだけ長くマッチ + 直前の正規表現の1回以上の反復、できるだけ長くマッチ *? 直前の正規表現の0回以上の反復、より短くマッチ +? 直前の正規表現の1回以上の反復、より短くマッチ ? 直前の正規表現の0〜1回の反復 ?? 直前の正規表現の0〜1回の反復、より短くマッチ {m} 直前の正規表現のm回の反復 {m}? 直前の正規表現のm回の反復、より短くマッチ {m,} 直前の正規表現のm回以上の反復 {m,}? 直前の正規表現のm回以上の反復、より短くマッチ {m,n} 直前の正規表現のm〜n回の反復 {m,n}? 直前の正規表現のm〜n回の反復、より短くマッチ () グループ化 \n 後方参照、正規表現のn番目のグループにマッチした文字列にマッチ \k< label name > 後方参照、ラベルでマッチ (?:) グループ化、後から参照出来ない (?< label name >) ラベル付きグループ化 (?#) コメント (?=) 先読み (?!) 否定先読み (?<=) 後読み (?<!) 否定後読み (?>) バックトラック抑止 (?ixm-ixm) オプションのon/off (?ixm-ixm:) 括弧内のオプションのon/off 「 a | b 」 → aもしくはbにマッチ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

経験が浅いエンジニアがコードを書くときに意識していること

概要 2020/10からRailsエンジニアとして働き始めたのですが、日々のコードレビューでいただいた指摘や書籍などで学んだ内容をもとに、経験が浅いからこそコードを書くときに意識的に気をつけていることを書いてみました。 思いついた範囲で書いていったので、言葉足らずなところがあったらすみません。 意識していること 命名 処理内容を推測できるような名前にする。(DB更新があるメソッドならupdate_~など) どうしてもその英単語しか当てはまらないとき以外は、なるべくみんなが聞き馴染みのある英単語を使う。 正しい英文法にこだわりすぎず、他人が読んで理解できることを重視する。 カスタムvalidation用のメソッド名は、must_beやcannotなどのprefixをつける。 可読性 ifの中身が深くなったり、if-elseを使用して処理が複雑になりそうな場合は、ガード節(アーリーリターン)を用いる。 ボイラープレート気味な処理になったら、RubyやRailsの便利メソッドに置き換えられないか考える。 コメントは最小限にする。 コメントを多く書いてしまった場合、そもそもの処理がわかりにくいということなので、リファクタリングできる場合はリファクタリングする。 メソッドの引数が2つ以上の場合は、キーワード引数にする。 保守性 オブジェクト指向らしく(依存が少ない、変更のしやすさ、単一責任、などと)なっているか。 メソッドの引数にオブジェクトで渡せるものはオブジェクトで渡す。 呼び出しメソッド内でそのオブジェクトのidとかしか使ってなくても、将来的に別の情報も使いたくなったときに、引数を変えなくていいため。 追加したコードが既存コードとたまたま同じような処理になったとしても、無理にDRYにしない。 DRYにすることで、呼び出し元によって処理が分岐して複雑になるようならDRYにしないほうがいい。 プロダクトに既に導入しているgemの機能が使いたいとなった場合でも、該当gemの更新が止まっている場合はできれば使用を避ける。 更新が長らく止まっているgemだと、将来的に該当gemを取り除きたいとなる可能性があるため。 パフォーマンス N+1が発生していないか。 ActiveRecordで無駄なSQLが発行されていたり、実行されるSQLのコストが高かったりしないか。 何回も同じインスタンスを生成するようなところがあれば、メモ化(||=)して不要なインスタンス生成を防ぐ。 セキュリティ SQLインジェクション対策ができているか。 Modelの情報をJSONでフロントに渡すときに、Hoge.allみたいにそのまま渡さず、Hoge.all.map { |h| h.slice(:id, :name) }みたいにして、必要なカラムに絞ってから渡す。 テスト DRYにすることよりも、可読性を意識する。 スタブやモックを適宜利用して、他の処理が壊れていても自処理のテストに影響しないようにする。 テストの実行速度も意識する。 TDDを取り入れてなくても、後でテストが書きやすいようになることを意識した実装にする。 その他 処理が失敗しても、ちゃんとロールバックしてデータの整合性が保てているか。 ドメインモデル貧血症になっていないか。(安易にサービスクラスを使っていないか) 余裕があればボーイスカウト・ルールを意識する。 最後に わざわざ書くほどでもないなと思ったことや、この記事を書くときに頭から抜けていたことは書けていません。 なので他にも意識していることはありますが、ここに書いた内容を見返したら全然少なかったので、まだまだ未熟だなと改めて思いました。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初学者向けエラーとの戦い方

はじめに ここ最近、何度もエラーと遭遇するうちにエラーとの向き合い方が非常に良くなってきたなと感じることが多くなってきました。エラーとの向き合い方を改めて自分の中で整理したくこの記事をまとめました。 エラーとの向き合い方(気持ち面) エラーがでたとき、皆さんはどう思いますか? 「げっ、エラーだ」、「は〜まじか」、そんなふうに声が出てしまうかもしれません。 私も学生時代に始めてプログラミングを学んだときは、発狂しそうな場面に何度も遭遇しました。(笑)でも、社会人になって、転職目的でまた勉強しはじめてわかったことがあります。 それは、、、、、 「エラーは失敗する方法が判明した成功」であるということです。 まず大前提にエラーは実はとてもありがたい存在であることを認識すべきです。もしエラーなき不具合があったとして、気付けずにリリースすれば、お客様に損害を与えてしまうことだってありえます。エラーが発生することは、そうしたさらなる事故を防ぐという超ありがたい存在なのです。 とはいえ、初学者さんでリリースを想定してアプリを作られる方はあまりいないかと思います。なのでなかなか想像しづらいですよね、、(私もそうです)。でも、エラーって初学者の方が成長するための、とても優秀な教材なんです!!!! エラーが発生したら、まずその原因を調べますよね?その過程で、今まで書いた文法が正しいかどうか再復習できますし、自分のエラーパターンを把握することができますし、もしかしするとエラーによって新しい知識を得ることができるかもしれません。 結局のところ、エラーは実は敵ではない!って言うことなんです! でもいくら敵ではなくともエラーは解消したい、そんな気持ちはきっとあるはず。 そこに関しては次の章で解説します。 エラーの倒し方(気持ち+技術編) 気持ち編 エラーの倒すにあたって、絶対に必要なマインドがあります。それは、、、、 「俺なら絶対にできる」と考えることです!!! うさんくせ〜〜〜〜と思うかもしれません。でも、恐ろしいまでにこの気持ちの有無で結果は大きく変わるのです。私の場合、よくぶつぶつと「できる、絶対できる、どうだ!(エンターポチっ、エラー)」を繰り返し作業すると、だいたいエラーを倒せます。 なぜこの気持ちを持つとエラーを倒せるのか、それはナチュラルに「できるはずのことができない」と脳が錯覚し、「ということは、できるまでやるか」となるからです。最初からできないと思うと、脳が効率を求めて「できないならやっても無駄!」と考え、結局挫折するか、サボってしまいます。 けれど、「できるはず」と錯覚した脳は、できるまであらゆる仮説を立てて、実行に移そうとします。 ちなみに科学的根拠は全然知りませんが、効果は抜群です(笑) 技術編 技術については、私もプロではないゆえ、偉そうなことは言えませんが私なりの考えをまとめていきます まず、エラー原因は全てログの中に答えがあるということです。 これはおそらく真理だと思います(笑)絶対にログをみれば答えは書いてあるはずです。(あるいはまんま、画面にエラーがでているかもしれませんが) わかりませんと言う前にログを見て、怪しい部分をググって、情報を追っていくだけで、8割のことはわかります。もちろん、残りの2割のどうしても分からない部分は、プロのエンジニアに聞くなり頼ってもいいかもしれませんね。でも、まずはログを見て、情報を集めて、なんとなくあたりをつける、、、とやっていくだけでだいぶ違うかな〜と思います。 ちなみに、分からないままずーーと作業するのも効率悪いので、完全に手が止まって15分したら、誰かに聞くといいかもしれません! おわりに 初心者が偉そうにエラーについて語りました。ただ上記のことを実践した結果、プロエンジニアの方にも自走力が高いですねとお褒めの言葉も頂けたりしたので、決して間違ってはいないかな〜なんて思います! 是非試してみてください 皆さんのエラー向き合い論もぜひ知りたいのでどしどしコメントください!!!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby]Class毎のよく使う操作をまとめたので見てくれ!!

Class一覧 Numeric 数値クラス(Integer等)のトップクラスです。 # ゼロかどうか 0.zero? #=> true # ゼロの場合はnil、それ以外はselfを返す 0.nonzero? #=> nil 3.nonzero? #=> 3 # 数値クラスの確認 100.integer? #=> true 3.real? #=> false # 四則演算 1 + 1 #=> 2 2-1 #=> 1 2 * 2 #=> 4 10 / 2 #=> 5 # 余り 10 % 3 #=> 1 # べき乗 10 ** 2 #=> 100 # 比較演算 1 == 1 #=> true(等しい) 1 != 1 #=> false(等しくない) 10 > 1 #=> true(右辺より左辺が大きい) 10 >= 1 #=> true(右辺より左辺が大きい、または等しい) 10 < 1 #=> false(右辺より左辺が小さい) 10 <= 1 #=> false(右辺より左辺が小さい、または等しい) # スペースシップ(左辺が右辺よりも小さければ負の値、大きければ正の値、等しければ0) 1 <=> 2 #=> -1 1 <=> 1 #=> 0 2 <=> 1 #=> 1 # 四捨五入 1.4.round #=> 1 # 切り捨て 1.4.floor #=> 1 # 切り上げ 1.4.ceil #=> 2 # 繰り返し ## ○〜×まで繰り返す 1.step 3 do |num| puts num end #=> 1,2,3 ## n回繰り返す 1.upto 3 do |num| puts num end #=> 1,2,3 3.time do |num| puts num end #=> 0,1,2,3 # 奇数か 1.odd? #=> true # 偶数か 2.even? #=> true # 次の値 1.next #=> 2 1.succ #=> 2 # 前の値 3.pred #=> 2 # 整数を文字列に変換 100.to_s #=> '100' # 有理数の表現(分数) r = Rational(1, 3) #=> (1/3) ## 分母を取得 r.denominator #=> 3 ## 分子を取得 r.numerator #=> 1 # 有理数に変換 100.to_r #=> (100/1) # 複素数(2乗したら0未満になる数) c = Complex(2, 3) ## 実部を取得 c.real #=> 2 ## 虚部を取得 c.imaginary #=> 3 String 文字列を表すクラス。 # 空文字か ''.empty? #=> true # 長さを測定 'あいうえお'.length #=> 5 'あいうえお'.size #=> 5 # バイト数を測定 'ほげほげ'.bytesize #=> 12 # 指定した文字列を含んでいるか 'あいうえお'.include?('あ') #=> true # 指定した文字列から始まるか 'あいうえお'.start_with?('あ') #=> true # 文字列の連結 'おは' + 'よう' #=> 'おはよう' # 文字列をn回繰り返し 'おはよう' * 3 #=> 'おはようおはようおはよう' # 任意の位置の文字列を取得 ## 位置を指定 'あいうえお'.slice(0) #=> 'あ' ## 取得位置からn文字数分取得 'あいうえお'.slice(0, 2) #=> 'あいう' ## 範囲を指定 'あいうえお'.slice(0..2) #=> 'あいう' # 空白文字を削除 'あいうえお '.strip #=> 'あいうえお' # 末尾を削除 'あいうえお '.chop #=> 'あいうえ' # 重複部分を削除 'あああああいうえお'.squeeze #=> 'あいうえお' # 小文字に変換 'ABC'.downcase #=> 'abc' # 大文字に変換 'abc'.upcase #=> 'ABC' # 大文字、小文字を入れ替える 'AbC'.swapcase #=>'aBc' # 先頭のみ大文字にする 'nAme'.capitalize #=> 'Title' # 最初にマッチした文字列を置換 '24-1-365'.sub(/[0-9]+/, 'x') #=> 'x4-1-365' # マッチした文字列全てを置換 '24-1-365'.gsub(/[0-9]+/, 'x') #=> 'x-x-x' # マッチした文字列全てを処理してから置換 '24-1-365'.sub(/[0-9]+/) { |str| str.to_i.next } #=> '25-2-366' # 特定の文字をセパレータとして配列へ変換 'あいうえお, アイウエオ, aiueo'.split(',') #=> ['あいうえお', 'アイウエオ', 'aiueo'] # 文字列の反転 'あいうえお'.reverse #=> 'おえういあ' # 文字ごとの繰り返し 'あいうえお'.each_char { |c| print "#{c}ー" } #=> 'あーいーうーえーおー' # エンコーディング 'あいうえお'.encoding #=> #<Encoding:UTF-8> Enumerable オブジェクトの集まりを自在に操るクラス。 # 繰り返し処理 ## インクリメントされる値と一緒に繰り返す %w(ABC abc).each_with_index do |name, index| puts "#{index}: #{name}" end #=> '0: ABC', '1: abc' ## 末尾から逆に繰り返す (1..3).reverse_each do |val| puts val end #=> '3', '2', '1' ## 要素をn個ずつ区切って繰り返す (1..5).each_slice(2) do |a, b| p [a, b] end #=> '[1, 2]', '[3. 4]', '[5, nil]' ## n個の連続した要素を1つずつずらしながら繰り返す (1..4).each_cons(2) do |a, b| p [1, b] end #=> '[1, 2]', '[2, 3]', '[3, 4]' ## 要素を先頭から末尾まで永遠に繰り返す (1..3).cycle do |n| puts n end #=> '1', '2', '3'.... # 各要素に処理してから配列を作成 ['ruby', 'rails'].map {|str| str.upcase } #=> ['RUBY', 'RAILS'] # 全ての要素が真ならtrue、偽ならfalse [true, true].all? #=> true # 全ての要素が偽ならtrue、真ならfalse [false, false].none? #=> true # 1つでも真があればtrueを返す [true, false].any? #=> true # 1つだけ真があればtrueを返す [true, false, false].any? #=> true [true, true, false].any? #=> false # 正規表現にマッチする要素を取得 %w(Rails ruby php).grep(/r/i) #=> ['Rails', 'ruby'] ['a', 'b', 1, 2].grep(String) #=> ['a', 'b'] # 戻り値が最初に真になった値を返す [4, 2, 3].detect {|v| v.even? } #=> 4 [4, 2, 3].find {|v| v.even? } #=> 4 # 戻り値が真となる全ての値を返す [4, 2, 3].select {|v| v.even? } #=> [4, 2] [4, 2, 3].find_all {|v| v.even? } #=> [4, 2] # 戻り値が偽となる全ての値を返す [4, 2, 3].reject {|v| v.even? } #=> [3] # 先頭から任意の数の要素を返す [1, 2, 3, 4].take(2) #=> [1, 2] # 先頭から任意の数をスキップした残りの要素を返す [1, 2, 3, 4].drop(2) #=> [3, 4] # 最初に偽を返すまでの要素を返す [1, 2, 3, 4].take_while {|n| n < 3 } #=> [1, 2] # 最初に偽を返した後の要素を返す [1, 2, 3, 4].drop_while {|n| n < 3 } #=> [3, 4] # 畳み込み演算 [4, 4, 2, 3].inject(1) do |result, num| result + num end #=> 14 # 要素を繰り返しながら1つのオブジェクトを更新する %w('rails', 'ruby', 'php').each_with_index({}) do |name, result| result[name] = name.length end #=> { rails: 5, ruby: 4, php: 3 } # 要素のグルーピング [1, 2.0, 3.0, 4].group_by {|n| n.class } #=> { Fixnum: [1, 4], Float: [2.0, 3.0] } # 真偽に応じて2つのグループに分ける [1, 2, 3, 4].partition {|n| n.even? } #=> [[2, 4], [1, 3]] # 最大値の取得 (1..10).max #=> 10 # 最小値の取得 (1..10).min #=> 1 # 最小値と最大値の取得 (1..10).minmax #=> [1, 10] # 条件値の最大値の取得 %w(Rails ruby php).max_by {|s| s.size } #=> 'Rails' # 条件値の最小値の取得 %w(Rails ruby php).min_by {|s| s.size } #=> 'php' # 条件値の最小値と最大値の取得 %w(Rails ruby php).minmax_by {|s| s.size } #=> ['Rails', 'php'] # ソート %w(ruby php C++).sort #=> ['C++', 'php', 'ruby'] # 条件付きソート %w(Rails ruby php).sort_by {|name| name.size } #=> [ 'php', 'ruby', 'Rails'] Array 配列のこと。[]や%記法、Array.newで生成出来る # 要素数を調べる [4, 2, 3, 5].length #=> 4 [4, 2, 3, 5].size #=> 4 # 空かどうか調べる [4, 2, 3, 5].empty? #=> false # 引数に与えたオブジェクトが含まれているか [4, 2, 3, 5].include?(4) #=> true # 配列の連結 [1, 3] + [4, 2] #=> [1, 3, 4, 2] # 要素を取り除く [1, 3, 5, 4, 2] - [4, 2] #=> [1, 3, 5] # 共通の要素を取得する [1, 2, 3] + [1, 4, 2] #=> [1, 2] # n回繰り返す [1, 2, 3] * 2 #=> [1, 2, 3, 1, 2, 3] # 添字参照 [1, 2, 3][0] #=> 1 [1, 2, 3][0, 1] #=> [1, 2] # 複数の添字の要素を配列で返す [1, 2, 3].values_at(1, 2) #=> [2, 3] # 先頭の要素を取得 [1, 2, 3].first #=> 1 ## 先頭からn個の要素を取得 [1, 2, 3].first(2) #=> [1, 2] # 末尾の要素を取得 [1, 2, 3].last #=> 3 ## 先頭からn個の要素を取得 [1, 2, 3].last(2) #=> [2, 3] # 要素をランダムに返す [1, 2, 3].sample #=> 2 ## 要素をn個ランダムに返す [1, 2, 3].sample(2) #=> [2, 3] # 特定のキーを持つ要素を返す [[:foo, 3], [:bar, 4], [:baz, 5]].assoc(:bar) #=> [:bar, 4] # 要素を追加 [1, 2, 3] << 4 #=> [1, 2, 3, 4] [1, 2, 3].push(4) #=> [1, 2, 3, 4] # 末尾の要素を取得 [1, 2, 3].pop #=> 3 # 先頭に要素を追加 [1, 2, 3].unshift(9) #=> [9, 1, 2, 3] # 先頭の要素を取得 [1, 2, 3].shift #=> 1 # 結果が真になった要素以外を取り除く [1, 2, 3, 4].select! {|v| v.even? } #=> [2, 4] # 結果が偽になった要素以外を取り除く [1, 2, 3, 4].reject! {|v| v.even? } #=> [1, 3] # レシーバが更新されなかった場合にレシーバを返す [1, 2, 3, 4].select! {|v| false } #=> nil [1, 2, 3, 4].delete_if {|v| false } #=> [1, 2, 3, 4] [1, 2, 3, 4].reject! {|v| true } #=> nil [1, 2, 3, 4].keep_if {|v| true } #=> [1, 2, 3, 4] # 指定した値を削除 [1, 2, 3, 4].delete(4) #=> [1, 2, 3] # 指定した添字の要素を削除 [1, 2, 3, 4].delete_at(2) #=> [1, 2, 4] # nilを取り除く [1, nil, 2, 4, ''].compact #=> [1, 2, 4, ''] [1, nil, 2, 4, ''].compact! #=> [1, 2, 4, ''] # 重複をした値を削除 [1, 1, 2, 4, 1.0].uniq #=> [1, 2, 4, 1.0] [1, 1, 2, 4, 1.0].uniq! #=> [1, 2, 4, 1.0] # 順序を逆にする [1, 2, 4].reverse #=> [4, 2, 1] [1, 2, 4].reverse! #=> [4, 2, 1] # 配列の配列を平らにして新しい配列を返す [2, 3, [5, 6]].flatten #=> [2, 3, 5, 6] [2, 3, [5, 6]].flatten! #=> [2, 3, 5, 6] # ソート [4, 2, 3, 9].sort! #=> [2, 3, 4, 9] # 条件付きソート ['abc', 'ruby', '12'].sort_by! {|v| v.size } #=> ['12', 'abc', 'ruby'] # それぞれの要素に処理して配列を更新する ['abc', 'ruby', 'rails'].map! {|v| v.upcase } #=> ['ABC', 'RUBY', 'RAILS'] # 配列を行列に見立てて、行と列を入れ替える [['a', 'b', 'c'], [1, 2, 3]].transpose #=> [[a: 1], [b: 2], [c: 3]] # 引数に渡された配列から配列の配列を作成 [1, 'a'].zip([2, 'b']) #=> [[1, 2], ['a', 'b']] # 検索対象範囲を指定して最初の値を取得(二分探索) [1, 3, 5, 7, 9].bsearch {|n| n > 6 } #=> 7 # 要素の連結 [22, 33, 44].join #=> '223344' [22, 33, 44].join('-') #=> '22-33-44' Hash 任意のオブジェクトをキーとして、他のオブジェクトを対応付けた、オブジェクトの集まり。 # 繰り返し処理 { one: 1, two: 2 }.each do |key, val| puts "#{key}: #{val}" end #=> 'one: 1', 'two: 2' ## キーのみ繰り返す { one: 1, two: 2 }.each_key do |key| puts "#{key}" end #=> 'one', 'two' ## バリューのみ繰り返す { one: 1, two: 2 }.each_value do |val| puts "#{val}" end #=> '1', '2' # 値の追加 hash = {} hash[:foo] = 'bar' hash #=> { foo: 'bar' } # 値の削除 hash = { foo: 'bar' } hash.delete[:foo] #=> 'bar' hash #=> {} # 条件に合うもののみ残す hash = { foo: 1, bar: 2, baz: 3 } hash.select! {|key, val| val.odd? } hash #=> { foo: 1, baz: 3 } # 条件に合うものを除外する hash = { foo: 1, bar: 2, baz: 3 } hash.select! {|key, val| val.odd? } hash #=> { bar: 2 } # ハッシュをまとめて新しいハッシュを返す hash = { a: 1, b: nil } hash.merge({ b: 2, c: 3 }) hash #=> { a:1, b:2, c:3 } hash = { a: 1, b: nil } hash.merge!({ b: 2, c: 3 }) #=> { a:1, b:2, c:3 } # キーとバリュー入れ替える hash = { foo: 1, bar: 2, baz: 3 } hash.invert #=> { 1: foo, 2: bar, baz: 3 } # 指定したキーが存在しているか hash = { foo: 1, bar: 2, baz: 3 } hash.has_key?(:foo) #=> true hash.key?(:foo) #=> true hash.member?(:foo) #=> true hash.include?(:foo) #=> true # 指定したバリューが存在しているか hash = { foo: 1, bar: 2, baz: 3 } hash.has_value?(1) #=> true hash.value?(1) #=> true # すべてのキーの取得 hash = { foo: 1, bar: 2, baz: 3 } hash.keys #=> [:foo, :bar, :baz] # 特定のキーを取得 hash = { foo: 1, bar: 2, baz: 3 } hash.key(1) #=> :foo # すべてのバリューの取得 hash = { foo: 1, bar: 2, baz: 3 } hash.values #=> [1, 2, 3] # 特定のキーを取得 hash = { foo: 1, bar: 2, baz: 3 } hash.values_at(:foo) #=> 1 # ハッシュの値を参照 hash = { foo: 1, bar: 2, baz: 3 } hash.fetch(:foo) #=> 1 # ハッシュの値を参照し、無い場合は第2引数を返す hash = { foo: 1, bar: 2, baz: 3 } hash.fetch(:test, '該当なし') #=> '該当なし' # ハッシュを配列に変換 hash = { foo: 1, bar: 2, baz: 3 } hash.to_a #=> [[:foo, 1], [:bar, 2], [:baz, 3]] # ハッシュから配列を作成 array = ['key1', 'val1', 'key2', 'val2'] Hash[*array] #=> { key1: 'val1', key2: 'val2' } Time オペレーティングシステムが提供するシステムの時刻機能をRubyから使用するためのクラスです。 # 現在時刻を取得 Time.now #=> 2021-05-10 18:09:10.651842 +0900 # 自身のタイムゾーンの現在時刻を取得 Time.zone.now #=> Mon, 10 May 2021 18:09:47 JST +09:00 # 年月日、時分秒を取得 time = TIme.zone.now #=> Mon, 10 May 2021 18:09:47 JST +09:00 time.year #=> 2021 time.month #=> 5 time.day #=> 10 time.hour #=> 18 time.min #=> 9 time.sec #=> 47 # 曜日を日曜(0)から土曜(6)までの整数で返す Time.zone.now.wday #=> 1 # 年を通して経過日数を返す Time.zone.now.yday # 夏時間かどうか返す Time.zone.now.dst? #=> false # 任意の曜日かどうかを返す Time.zone.now.sunday? #=> true Time.zone.now.monday? #=> false Time.zone.now.tuesday? #=> false Time.zone.now.wednesday? #=> false Time.zone.now.thursday? #=> false Time.zone.now.friday? #=> false Time.zone.now.saturday? #=> false # 任意のフォーマットで返す Time.zone.now.strftime('%Y/%m/%d') #=> '2021/05/10' Time#strftimeに使用できるフォーマット文字列 文字列 意味 %A 曜日の名前(Sunday, Monday...) %a 曜日の略称(Sun, Mon...) %B 月の名前(January, February) %b 月の略称(Jan, Feb) %C 世紀(年の上2桁) %c 日付と時刻(Mon, 10 May 2021 18:09:47 JST +09:00の形式) %D 日付(%Y/%m/%dの形式) %d 日、1桁の場合は0埋めされる %e 日、1桁の場合は半角スペース埋めされる %F '%Y-%m-%d'と同じ %H 時、24時間表示で1桁の場合は0埋めされる %I 時、12時間表示で1桁の場合は0埋めされる %j その年の通算日数、1,2桁の場合は0埋めされる %k 時、24時間表示で1桁の場合は半角スペース埋めされる %L ミリ秒(000-999) %l 時、12時間表示で1桁の場合は半角スペース埋めされる %M 分、1桁の場合は0埋めされる %m 月、1桁の場合は0埋めされる %N 秒の小数点以下 %P amまたはpm %p AMまたはPM %R '%H:%M'と同じ %r '%I:%M:%S %p'と同じ %S 秒、1桁の場合は0埋めされる %s UNIXエポックからの経過秒数 %T '%H:%M:%S'と同じ %U 週、1桁の場合は0埋めされる %u 曜日、月曜日(1)〜日曜日(7) %v VMS形式の日付 %V 週、1桁の場合は0埋めされる、ISO8601形式の暦週 %W 週、1桁の場合は0埋めされる、最初の月曜日が第1週の始まり %w 曜日、日曜日(0)〜土曜日(6) %X '%H:%M:%S'と同じ %x '%m/%d/%y'と同じ %Y 年、西暦を表す4桁の数字 %y 年、西暦を表す下2桁の数字 %Z タイムゾーン(UTC, JSTなど) %z タイムゾーン(+0000, +0900など) %n 改行文字 %t タブ文字 %% %自身 IO・File Dir
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

例外処理に強くなるにはこちらから。

はじめに 開発する上で、避けたいけど避けられない。エラー。。 どんな優秀なエンジニアもエラーには何度も遭遇します。 例外処理を記述しておくことで、デバッグや想定外のエラーにも対応できたりとメリットがたくさんあります。 例外処理を書けるようにしておくと良いでしょう! 例外処理について まず、「例外」とはなんらかの異常が発生したことを表すオブジェクトです。 例外が発生すると、例外はコールスタックまで遡り、トップレベルまで伝播して行きます。 メソッド②で例外発生 ↓ メソッド①呼び出し ↓ トップレベル呼び出し 例外オブジェクトは、Exceptionまたはそのサブクラスのインスタンスです。 (出典: Ruby Exceptions) 例外の制御 例外を発生させる Kernel#raiseを使用する。 # 第一引数に文字列を指定すると、RuntimeErrorが発生 raise 'error!' #=> RuntimeError: error! # 第一引数に例外クラスを指定出来る raise StandardError, 'error!' #=> StandardError: error! 例外を捕捉する 例外の発生する可能性のある式はbegin〜endに記述する。 begin do_process rescue => e # 例外オブジェクトを変数eに代入 puts "puts #{e.class}" end # 例外を指定すると、指定したクラスとそのサブクラスの例外が捕捉される begin do_process rescue Exeption => e # 例外オブジェクトを変数eに代入 puts "puts #{e.class}" ensure # 最後に必ず実行する処理 puts 'ここまでで処理は終了しました' end 例外オブジェクトの主な操作は以下の通りです。 # クラス名 e.class #=> StandardError # エラーメッセージ e.message #=> "error!" # コールスタック e.backtrace #=> ["sample.rb:9:in 'maaain'", "sample.rb:11:in '<main>'" 終わりに 開発において例外処理をすることは、かなり重要になってきます。 ここを怠ると、自分で発見出来ていないバグによって、サービス利用者に迷惑をかけたりすることもあるので、意識して記述して行きましょう!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

バックスラッシュ記法早見表

主なバックスラッシュ記法 表記 意味 \t                タブ                  \n                改行                  \r               キャリッジターン                  \f                次ページ                  \b               バックスペース                  \a                ベル                   \e                エスケープ                  \s                空白                  \nnn               8進数表記(n=0〜7)                  \xnn               8進数表記(n=0〜9、a〜f)             \cx               コントロール文字                    \unnnn             Unicodeエスケープ(n=0〜9、a〜f)          
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby]モジュールを使いこなしてみた。

はじめに 現場の開発においてモジュールはかなり使う技術だと思います! よく使うだからこそ、細かい使い方まで知っていることが開発スピードの向上や、他の人のコードの読解にも役立ちます。 モジュールについて 簡単に説明すると、「インスタンス化出来ないクラスのようなもの」です。 モジュール定義の中に、別のモジュールやクラスを定義したり出来るので、名前空間として利用できます。 module FooModule class FooClass ... end end FooModule::FooClass #=> FooModule::FooClass 特徴 インスタンスを生成出来ない 継承する事は出来ない 名前空間を作ることが出来る モジュールのメソッドを、、 あるクラスのインスタンスメソッドとして取り込む あるオブジェクトの特異メソッドとして取り込む モジュール関数を定義して使う クラスにモジュールを取り込む モジュールに定義されたメソッドを、クラスのインスタンスメソッドとして取り込むことをMix-in(ミックスイン)と言います。 module Hello def foo puts 'hello! foo!' end end class Sample include Hello end sample = Sample.new sample.foo #=> 'hello! foo!' モジュールに定義されたメソッドを、オブジェクトの特異メソッドとして取り込むこともできる。 extendにより、そのオブジェクトにだけ特定の振る舞いを与えることができます。 module Greet def greet(name) puts "hello! #{name}" end end class Sample extend Greet end sample = Sample.new sample.greet('World') #=> 'hello! World' モジュール関数 privateなインスタンスメソッドであると同時に、モジュールの特異メソッドであるメソッドのこと。 # 定義方法 module SampleModule def hello(name) puts "Hello #{name}" end module_function :hello #helloメソッドをモジュール関数とする。 end # まとめて定義する方法 module SampleModule module_function #これ以下にメソッドを定義することでモジュール関数となる def hello(name) puts "Hello #{name}" end def greet(name) puts "Good Morning #{name}" end end モジュール関数の呼び出し方 #直接的にモジュールから呼び出す。 SampleModule.hello('Tanaka') #=> Hello Tanaka #includeする。 include SampleModule hello('Tanaka') #=> Hello Tanaka 終わりに モジュールは奥が深いけど、確実に自分の武器になるので扱えるようになりたいものですね! 少しずつ頑張りましょう。。!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

継承について理解したい!

はじめに 皆さんは、「継承」を使いこなせていますでしょうか? 開発において使わないことはないのですはないか、というくらいに頻繁に利用します。 確実に抑えておきたい技術です! 継承について Rubyは単一継承をサポートしています。 継承された方のクラスをスーパークラス、した方をサブクラスと言います。 サブクラスには、スーパークラスのメソッドが継承されます。 class Parent def parent puts 'hello parent!' end end class Child < Parent def child puts 'hello child!' end end child = Child.new child.parent #=>'hello parent!' child.child #=>'hello child!' オーバーライド スーパークラスに定義済みのメソッドを、サブクラスで定義することをオーバーライドという。 オーバーライドすることで、スーパークラスを引き継ぎながら追加で新たな処理を追加できる。 class Parent def hello puts 'hello parent!' end end class Child < Parent def hello super #=> Parent#helloが呼び出される puts 'hello child!' end end child = Child.new child.hello #=> 'hello parent!' 'hello child!' スーパークラスを調べるには、クラス名.superclassで取得できる。 Child.superclass #=> Parent 継承されるもの サブクラスは、スーパークラスのインスタンスメソッド、クラスメソッド、定数を継承します。 class Parent PARENAT = 'PARENT' def initialize @foo = 'foo' end end class Child < Parent end Parent.new #=> #<Parent...@foo="foo"> Child.new #=> #<Child...@foo="foo"> Child::PARENT #=> "PARENT" 終わりに 継承をすることで、リファクタリングにもつながるので正しく利用しましょう!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby]変数の違いを理解していますか??

はじめに Rubyにはいくつもの変数の種類があります。 理解して使いこなすことが、開発レベルやコードの綺麗さが向上します。 スコープによって、いくつかの種類に分けられていますので、使いこなせるようにしましょう! ローカル変数 最もスコープの狭い種類の変数。 スコープの範囲は、、、 ・ブロック ・メソッド定義 ・クラス、モジュール定義 ・トップレベル foo = 'foo' def puts_foo puts foo #=> NameError end puts foo #=> 'foo'と表示 グローバル変数 非常に広いスコープを持つ変数。存在しないグローバル変数を指定するとnilを返す。 ※可読性が下がる可能性があるため、あまり使用しない スコープの範囲は、どこからでも参照可能です。 $foo = 'foo' puts $bar #=> nil 定数 変化しない値を扱う変数。大文字で定義するのが慣習です。 ※再代入すると、警告が出るが禁止はされていない。 FOO = 'FOO' puts FOO #=> 'FOO' def bar BAR = 'BAR' #=> 文法エラー end インスタンス変数 インスタンスの中でのみ参照できる変数。「@〜」から始まる変数。 class Ruler def length=(val) @length = val end def length @length end ruler = Ruler.new ruler.length = 30 ruler.length #=> 30 end attr_accessorを利用することで、簡単に定義出来ます。 class Ruler attr_accessor :length ・ ・ ・ end クラス変数 クラスとそのインスタンスをスコープとした変数。「@@〜」から始まる変数。 class Foo @@foo = 'foo' def foo puts @@foo end def self.foo puts @@foo end foo_class = Foo.new foo_class.foo #=> 'foo' Foo.foo #=> 'foo' 終わりに 普段使うもの、あまり使わないもの、いろいろありますが知識として持っておくことで、使い分けが可能になります!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 6 + MySQL8.0 + Docker 環境でMySQLを日本語化

初学者向けの記事です。 私の備忘録として残します。 docker-compose.yml上で2つのことをしようとしてハマった ・「MySQL8.0の認証方法に対応」 ・「MySQLの文字コードを変更」 これを同時にやろうとしてハマりました。 やりたいこと1 「MySQLの認証方法変更」 MySQL8.0から command: --default-authentication-plugin=mysql_native_password を追加する必要がありました。 コード全体を確認 (docker-compose.yml) version: '3' services: db: image: mysql:8.0 command: --default-authentication-plugin=mysql_native_password volumes: - ./src/db/mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./src:/app ports: - "3000:3000" depends_on: - db やりたいこと2 MySQLの文字コードをutf8mb4に変えたい また、dockerでmysqlの文字コードを日本語対応のものに変更しようとすると、次のようなコマンドを打つ必要があるとわかりました。 (imageを引っ張ってくるとデフォルトの文字コードは「latin1」でした) command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci で、「commandを2つ書けば良いんだな」と思って調整していたのですが、うまくいきません。 というのも、docker-compose.ymlのcommandは「1つしか書けない」からなんですね。 Run a one-off command on a service 参考文献 思いついた解決策1(失敗):1つの長いcommandにする 下記リンクを参考に長い1つのcommandを作ろうと思いましたが失敗しました。 もう少し粘れば行ける気がするのですが、そもそも長いコマンドはあまり美しくないかも・・・と思って解決策2を試したところ、すんなり解決しました。 参考リンク 思いついた解決策2(成功):localのmy.cnfをmysqlのdbコンテナにコピーする まずlocalの適当な場所にmy.cnfを作ります。 そこにdbコンテナのmy.cnfをコピーして、先ほどコマンドでやりたかったことを追記します。 そしてdocker-compose.ymlを編集 1、commandを削除(全てmy.cnfに書いたので) 2、volumesに下記の一行追記 - ./src/db/my.cnf:/etc/mysql/my.cnf コード全体を確認 (docker-compose.yml) version: '3' services: db: image: mysql:8.0 volumes: - ./src/db/mysql_data:/var/lib/mysql - ./src/db/my.cnf:/etc/mysql/my.cnf environment: MYSQL_ROOT_PASSWORD: password web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./src:/app ports: - "3000:3000" depends_on: - db おわり これで無事文字コードの置き換えとMySQL8.0の認証を同時に行うことができました。 Rails 6 + MySQL8.0 + Dockerで開発をすれば誰でもこの状況になる気がするので、みなさん普通に解決してるんですよね。 私は1時間以上かかりました。 これからも精進します。 何か間違いがあればご指摘いただけますと幸いです。 備考 docker-compose.ymlを書き換えた時はdocker-compose downとupだけで動作確認できます。 私はよくわからなくて途中まで毎回buildしていました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsサーバー起動時にLoadErrorが発生した

いつも通り何気なくrails sでサーバー起動しようとした際、なぜかいきなりLoadErrorが表示されました。 色々なサイトを見ていると、pumaの再インストールやバージョンの書き換えなどで解決しているものもありましたが、私の場合は該当しませんでした。 とは言ってもとても簡単にエラー解決できたので、備忘録として残しておきます。 結論、 ApplicationsControllerがおかしくなっていたので、そこを修正すればきちんと起動するようになりました。 エラー内容を確認すると、「Unable to autoload constant ApplicationsController ~」となっていたので、 ApplicationControllerを一度確認しました。 すると一度目では発見できなかったのですが、よく見てみるとclass以降の表記が変わっていました。 application_controller.rb class ApplicationsController < ActionController::Base  略 end 正しくは、 application_controller.rb #ApplicationsControllerのsを削除 class ApplicationController < ActionController::Base  略 end この修正によってきちんと起動できるようになりました。 なぜ書き変わっていたのかは不明のため、原因が分かる方いらっしゃれば教えていただきたいです。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】String#tr メソッドについて覚え書き

String#tr メソッド 文字列に含まれる文字の置き換えができる puts "abcabc".tr("a", "z") # =>"zbczbc" 検索する文字は範囲指定もできる puts "abc".tr('a-z', 'A-Z') # => "ABC" # シーザー暗号(アルファベットを3文字分ずらす)の解読 puts "ORYV".tr("A-Z", "D-ZA-C") # => "RUBY" # 任意の文字数分ずらしたい場合 chars = [*"A".."Z"] keyword = "RUBY" encrypted_keyword = keyword.tr(chars.join, chars.rotate(-5).join) # Array#rotateで任意の分だけ文字をずらせる。 puts encrypted_keyword # => "MPWT" 参照 https://docs.ruby-lang.org/ja/2.6.0/method/String/i/tr.html https://docs.ruby-lang.org/ja/2.6.0/method/Array/i/rotate.html https://docs.ruby-lang.org/ja/latest/method/Array/i/join.html https://qiita.com/ya-maruchoba/items/9e26c971fbaffb77c7d2
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

4乗的ガウスをRubyで解いてみた

プログラミング学習を始めて間もない自分が、数学の問題をプログラミングで解く機会があったのでアルゴリズムの理解も含めて記録してみました。 もっと簡単に解ける方法があると思いますが、今の自分ではこれが精一杯でした。笑 精進します。 【4乗的ガウス】 1の4乗から60の4乗までの和を求める。 i = 0 while i <= 59 i += 1 num = num.to_i + (i ** 4) puts num end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby/OpenCVでスプラトゥーン2の戦況を可視化する索敵補助ツール作ってみた

はじめに 本ツールは、 https://qiita.com/Kazuma_Kikuya/items/4767afe581c94b0c16f1 の別実装です (画像処理をやったことがなかったのですが、元記事には解析に必要な要点がまとめられており、本ツールを作る上で非常に参考になりました。) 元記事はスタンドアローン型でしたが、本ツールはサーバ/クライアント型で構成しています。 サーバ/クライアント型にしたことで、1人が画像解析した結果をwebページ経由で味方全員に提供できるようになりました。 概要 switchから取り込んだ画像をPCで解析し、解析結果をwebsocket経由で送信して、webページ上でイベントに合わせてなんらかをする、というツールです。 websocket経由で送信することで、通知の受信が用意になりました。 下記図にある、 通知受信用WEBアプリ(client) はheroku上で動いています。 switch -> 解析用アプリ: 解析用アプリ-> 解析用アプリ: 画像解析 解析用アプリ-> 解析用アプリ: イベントデータの生成 解析用アプリ -> redis : イベントデータの送信 redis -> 通知受信用WEBアプリ(client): 通知受信用WEBアプリ(client) -> ブラウザ: ブラウザ -> ブラウザ: 音を鳴らす 機能の説明 本ツールでは、webページを開いているだけで通知を受け取れるので、リグマやっているときの味方にこのURLを共有しておくと味方に情報を伝えることができます。 元記事から機能をだいぶ削っていて、敵復活時点のみ音を出すようにしています。生存時間を表示する機能は実装予定です。 おわりに 詳細な実装に関することは http://blog.jiikko.com/152 に日記みたいな感じで書いています。 ガチマッチで本ツールを使っている動画をアップロードしました。 https://www.youtube.com/watch?v=QFrYSWYJ3lw 通知受信用WEBアプリ のソースコードは公開しています。 https://github.com/splaspla-hacker/splatoon2_enemy_visualizer_frontend 画像解析のソースコードは準備中です。 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

オリジナルアプリ開発【DB設計】

現在、転職先の企業へのアピールポイントになるポートフォリオ作成(オリジナルアプリ開発)をしています。 私は、タスク管理ツールの完成を目指しています。 今回は、DB設計についてです。 エンティティを洗い出す エンティティ(実体)とは、ある共通項を持ったデータの集合体のこと。 「システムに必要なエンティティ(=データ)は何か?」を洗い出していきます。 機能 サインアップ・サインイン機能 リスト機能 カード機能 これらの機能に必要なテーブルを以下のように抽出します。 必要なテーブル usersテーブル listsテーブル cardsテーブル これで必要なテーブルは決まりました。 次はそれぞれのテーブルに必要なカラムを決めるために、テーブルごとに管理する情報を考えていきます。 テーブルごとに管理する情報 usersテーブル ニックネーム メールアドレス パスワード listsテーブル リストタイトル user情報(外部キー) cardsテーブル カードタイトル カードの詳細 list情報(外部キー) 全ての情報の関係性を考えます。 全ての情報をの関係を洗い出したら、テーブル設計を行います。 テーブル設計には、ER図を描きます。 Railsプロジェクト新規作成してから行います。 下の記事を参考にしてみてください! ER図 ER図とは、データベース設計における代表的な設計図のことです。 ER図のEはエンティティ(Entity)の略で、Rはリレーションシップ(Relationship)の略です。 READMEに設計情報を記述 README(リードミー)とは、ソフトウェアの仕様、規格、インストール方法などを文書化したアプリケーションの説明書のようなファイルです。 特徴として、rails newを実行した際に自動生成され、マークダウンと呼ばれる記述方法で記載されています。 今回、READMEには以下の内容を記述します。 テーブル名 カラム名 カラムの型 カラムのオプション(null false制約など) アソシエーション README.md # テーブル設計 ## usersテーブル | Column | Type | Options | | ------------------ | ------ | ----------- | | nickname | string | null: false | | email | string | null: false | | encrypted_password | string | null: false | ### Association - has_many :lists ## listsテーブル | Column | Type | Options | | ---------- | ---------- | ------------------------------ | | list_title | string | null: false | | user | references | null: false, foreign_key: true | ### Association - has_many :cards - belongs_to :user ## cardsテーブル | Column | Type | Options | | ---------- | ---------- | ------------------------------ | | card_title | string | null: false | | memo | text | null: false | | prototype | references | null: false, foreign_key: true | ### Association - belongs_to :list マークダウンを用いて記述すると、上記は以下の画像のように見た目が整った形で反映されます。 マークダウンが反映されているかどうかはGitHub等で確認します。 テーブル設計 usersテーブル Column Type Options nickname string null: false email string null: false encrypted_password string null: false Association has_many :lists listsテーブル Column Type Options list_title string null: false user references null: false, foreign_key: true Association has_many :cards belongs_to :user cardsテーブル Column Type Options card_title string null: false memo text null: false prototype references null: false, foreign_key: true Association belongs_to :list テーブル設計については以上です。 ER図の描き方やREADMEの記述方法については今回触れませんでしたが、今後、ご紹介できればと思っています!! 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails初学者によるRailsチュートリアル学習記録⑧ 第6章

目次 1. はじめに 2. 第6章の概要 3. 学習内容 4. 終わりに 1. はじめに この記事は、Rails初学者の工業大学三年生がRailsチュートリアルの学習記録をつけるための記事です。 筆者自体がRailsやWebについて知識が少ないので、内容の解釈などに間違いがある可能性があります。(その時はコメントで指摘してくださると助かります!) Railsチュートリアル内ではRailsの内容以外にも、gitでのバージョン管理やHerokuを使ったデプロイも学習しますが、gitに関しては既に私が学習済みのため学習記録には記述しません。 演習の記録も省略します。 2. 第6章の概要 この章では、ユーザーのデータモデルを定義し、データベースにデータを保存する方法について学びます。 モデルが作成できたら、登録ページを準備してフォームのバリデーションやパスワードをセキュアに扱う機能を実装していきます。 ユーザーモデルの作成 Userデータモデルの設計 ユーザーオブジェクトをデータベースに保存する ユーザーオブジェクトを更新する ユーザーを検証する インデックスの作成 セキュアなパスワードを追加する 3. 学習内容 1. ユーザーモデルの作成 1-1. Userデータモデルの設計 この章で作成するユーザーモデルは4章で作成したような、nameとemailという属性を持つユーザーモデルです。 モデルを作成するためにrails generate model User name:string email:stringコマンドを実行します。 このコマンドによりマイグレーションファイルが作成され、そこにRubyでデータベースの構造を記述していくことになります。 ↓ 作成されたマイグレーションファイル db/migrate/[timestamp]_create_users.rb class CreateUsers < ActiveRecord::Migration[6.0] def change create_table :users do |t| t.string :name t.string :email t.timestamps end end end このファイルはデータベースに与える変更を定義したchangeメソッドの集まりで、 このファイルではコマンド実行時に指定したstring型のname, emailという2つの属性が定義されている。 t.timestampsという行は自動的に追加される属性で、ユーザーが作成されたり更新された時にその時刻を自動的に記録する属性である。 ↓Userのデータモデル 属性 データ型 id integer name string email string created_at datetime updated_at datetime そして、rails db:migrateを実行することでマイグレーションファイルに定義された データベースへの変更を、データベースに反映できます。 1-2. ユーザオブジェクトをデータベースに保存する マイグレーションによって作成したユーザーオブジェクトをデータベースに保存する準備ができたので、 railsコンソールでユーザーオブジェクトを作成・保存してみます。 コンソールでuser.newを使用してユーザーオブジェクトを作成してもデータベースには保存されていないため、 コンソールを終了するとオブジェクトは消えてしまいます。 作成したオブジェクトをデータベースに保存するには、saveメソッドを用います。 saveメソッドは成功したらtrue、失敗したらfalseを返します。 このコマンドを実行するとデータベースにオブジェクトが保存されますが、 今回のように試しに保存してデータベースへの変更は取り消したいという時には コンソールをサンドボックスモードで起動するrails console --sandboxを実行すると良いです。 また、saveメソッドでオブジェクトの保存を行うにはnewメソッドでオブジェクトの生成をする必要があるのですが、 オブジェクトの生成とデータベースへの保存を同時に行うにはcreateメソッドを使用します。 データベースに保存したユーザーを検索するには、いくつかの方法があるので順に紹介していきます。 ①idを指定して検索する ユーザーのidを指定して検索するにはfindメソッドを使用します。 例: User.find(3) → idが3のユーザーを検索する ②特定の属性で検索する id以外の特定のユーザーで検索するにはfind_byメソッドを使用します。 例: User.find_by(email: "abc123@example.com") → email属性がabc123@example.comのユーザーを検索する ③データベースの最初のユーザーを検索する データベースの最初のユーザーを取得するにはfirstメソッドを使用します。 例: User.first → データベースの最初のユーザーを検索する ④すべてのユーザーを取得する データベースの全てのユーザーを取得するにはallメソッドを使用します。 例: User.all → データベースの全てのユーザーを取得する 返ってくるオブジェクトはActive-Record::Relationというクラスで、各オブジェクトが配列としてまとめられています。 1-3. ユーザオブジェクトを更新する 一度データベースに保存した情報を更新するには2つの方法があります。 1つ目はユーザーオブジェクトを取得して、属性を代入する方法です。 ユーザーオブジェクトを検索した後、user.email = "aiueo@example.com"のように 属性に対して値を代入し直してからsaveメソッドを実行することでオブジェクトを更新できます。 2つ目はupdateメソッドを使用する方法です。 user.update(name: "The Dude", email: "dude@abides.org") updateメソッドは属性のハッシュを受けとって成功時には更新と保存を同時に行います。 オブジェクトにパスワードが実装されると更新時に保存を要求するようになり、 正しいパスワードを渡さないと検証で失敗するようになります。 このメソッドでは全ての属性を渡す必要があるが、特定の属性のみを更新したい場合は、 update_attributeメソッドを使用します。 user.update_attribute(:name, "El Duderino") このメソッドは検証を回避することができます。 1-4. ユーザを検証する 作成したUserモデルはnameとemailという属性があり、これらはどんな値でも取ることができます。 しかし、実際にアプリケーションを運用するには nameとemailは空ではいけない、emailはメールアドレスのフォーマットに従っていなければならないといった制限が必要です。 この制限のことを検証(Validation)と呼びます。 ①存在性の検証 まずは最も基本的な、「値が存在するか?」を検証していきます。 最初に存在性の検証が正しくできているかを確認するテストをtest/models/user_test.rbというファイルに記述していきます。 テストファイルにはsetupという特殊なメソッドを使用してユーザーオブジェクトを生成、@userに代入します。 setupメソッド内に書かれた処理はテストの前に実行されるので、全てのテスト内で@userというインスタンス変数を使用することができます。 存在性のテストは@userのnameとemailに空白を設定した後に、@userの有効性を確認します。 テストは以下のように書きます。 test/models/user_test.rb require 'test_helper' class UserTest < ActiveSupport::TestCase def setup @user = User.new(name: "Example User", email: "user@example.com") end test "should be valid" do # 初めに@userが有効かテストする assert @user.valid? end test "name should be present" do # nameの検証ができているかのテスト @user.name = "" assert_not @user.valid? end test "email should be present" do # emailの検証ができているかのテスト @user.email = " " assert_not @user.valid? end end 上記のテストで assert と assert_not が使用されているのは、 最初の有効性のテストはオブジェクトが有効になっている → valid?がtrueを返せばOKなのに対して、 存在性の2つのテストは、値が空白になることでオブジェクトが無効になる → validがfalseを返せばOKだからassert_notを使用しています。 これでテストが完成し、この時点では検証が実装されていないのでこのテストは失敗します。 実際の検証は以下のようにapp/models/user.rbに記述します。 app/models/user.rb class User < ApplicationRecord validates :name, presence: true validates :email, presence: true end validates :属性名, presence: trueと記述することで存在性が検証できます。 このように検証の実装は望ましくない値を代入して、オブジェクトが無効になるかを確認するテストを書き、 その後に検証を実装するというテスト駆動開発の流れが適しています。 下にこの章で実装する完全なを検証を載せて、簡単な説明のコメントを添えます。 app/models/users.tb class User < ApplicationRecord before_save {self.email = email.downcase} # 保存する前に実行される emailを小文字にする validates :name, presence: true, length: {maximum: 50} # nameの検証 最大50文字で値が存在するか VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i # emailフォーマットの正規表現 詳細は割愛 # 以下emailの検証 validates :email, presence: true, length: {maximum: 255}, # 最大255文字 format: { with: VALID_EMAIL_REGEX }, # フォーマットは上記の正規表現に従う uniqueness: true # 一意性を持つ # 以下パスワードの検証 詳細は後述 has_secure_password validates :password, presence: true, length: {minimum: 6} end 2. インデックスの作成 インデックスとはデータベース上のデータの検索速度を速めたり、データベース上のデータの制約を追加するものです。 特定の属性に対して追加するもので、今回はemail属性にインデックスを追加します。 そのためのコマンドはrails generate migration add_index_to_users_emailです。 最後のadd_index_to_users_emailはファイル名となります。 db/migrate/[timestamp]_add_index_to_users_email.rb class AddIndexToUsersEmail < ActiveRecord::Migration[6.0] def change add_index :users, :email, unique: true end end add_indexといメソッドでusersテーブルのemailカラムにインデックスを追加しています。 unique: trueはemailカラムに一意性を強制しています。 2. セキュアなパスワードを追加する パスワードは入力された文字列をそのままデータベースに保存するのではなく、 文字列をハッシュ化したものを保存します。 このようなセキュアなパスワードの実装はhas_seure_passwordというメソッドでほとんどが済みます。 このメソッドをUserモデルで呼び出すと、以下の機能が使えるようになります。 1. ハッシュ化したパスワードを、password_digestという属性に保存する 2. password と password_confirmation という2つの仮想的な属性が使えて、存在性と2つの値が一致するかの検証が追加される 3. authenticateメソッドという引数とパスワードが一致するかを確かめるメソッド メソッドの追加のほかにやることは、Userモデルへのpassword_digest属性の追加と、 bcryptというハッシュ関数を使用するためのgemの追加です。 それらができたら、users.rbの最後に以下の二行を追加して、パスワードを使用した認証機能の完成です。 app/models/users.tb has_secure_password validates :password, presence: true, length: {minimum: 6} # パスワードの最小文字数を6文字にする 4. 終わりに 第6章から本格的なアプリケーションの機能追加が始まって内容が難しくなってきた印象です。 内容が濃いので、記事に書く内容を選別しており特にテストの内容に関しては今回載せた検証などの、 特に重要度が高かったり、内容の理解が重要な部分のみを記述していく予定です。 記事作成に3~4時間くらいかかっているのですが、読み返してみると数分で見れる内容になっているのが、 見やすいようで、あれだけ頑張ってこれくらいの文量かとなって複雑な気持ちになってます:( これ以降も難しい内容が終わりまで続くと思うので、進むスピードが落ちそうですが挫折しないことを第一に頑張りますb
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでグループチャット機能を実装

1.Railsでのグループ機能実装で躓いたポイントについてまとめてみた  Railsチュートリアルを一通りやった後でオリジナルアプリを作るためにもグループチャット機能とかあったら面白そうだと考えましていざ色々なサイトを巡りながら実装してみましたが、思いの外苦戦してエラーを返されてばかりでした。結局実装しようと思い立ってから実装し終わるまでに色々なサイトを参考にしたにも関わらず丸1日ほどかかってしまいましたので実装までに苦労したポイントや最終的にどんな形で実装したかについて備忘録も兼ねて記事にしようと思います。 2.必要ファイルの作成  これについてはそこまで苦労しませんでした。先達のやり方を参考に以下のコマンドをターミナルで打ち込み、マイグレーションファイルやモデルファイル、コントローラーを作成することから始めました。 ターミナル. rails g controller groups rails g model group rails g model group_user  必要ファイルを作成した後マイグレーションファイルを以下の形でいじります。ここも特に苦労しませんでした。 ~~_create_groups.rb class CreateGroups < ActiveRecord::Migration[6.1] def change create_table :groups do |t| t.string :name, null: false t.index :name, unique: true t.timestamps end end end ~~_create_group_users.rb class CreateGroupUsers < ActiveRecord::Migration[6.1] def change create_table :group_users do |t| t.references :group, foreign_key: true t.references :user, foreign_key: true t.timestamps end end end  修正が終わったら忘れないうちにマイグレーションします。 ターミナル. rails db:migrate 3.モデルファイルの修正  モデルファイルに必要事項を追加していきます。ここも基本的には先達の方々がやってきた通りにコードを書けば問題ありません。ただし、注意点がひとつあります。開発用データベースとしてMySQLを使っている場合、一部のモデルファイルにある記述をしておかないとエラーを返してきます。他のデータベースを使った場合どうなるかについては私にもわからないですのでなんとも言えないですが…。ご存知の方いましたら是非とも教えていただければと思います。 3-1.追加箇所  まずは、先達の方々に倣ってモデルファイルに追加していきます。コードの追加の仕方はどのサイトを巡っていても同じでした。 app/models/user.rb has_many :group_users has_many :groups, through: :group_users app/models/group.rb class Group < ApplicationRecord has_many :group_users has_many :users, through: :group_users validates :name, presence: true, uniqueness: true end app/models/group_user.rb class GroupUser < ApplicationRecord belongs_to :group belongs_to :user end  これについても既出の情報になります。むしろ先達の方々の方がこれに加えてリレーションの説明とか事細かにしてくれたりしていますのでこのあたりに関しては初学者の私よりも後述の参考サイトを書かれた方々の記事を読んでいただいた方がいいかもしれません。 3-2.MySQLを使ってたからこそ投げられたエラー  グループを作成したり、編集するだけでしたらこの節で取り上げる修正は不要ですが、グループを削除する処理も追加したい方でなおかつ開発データベースにMySQLを使っている方でしたら以下のファイルにこのような形で修正を加える必要が出ます。 app/models/user.rb has_many :group_users, dependent: :destroy #追加 has_many :groups, through: :group_users, dependent: :destroy #追加 app/models/group.rb has_many :group_users, dependent: :destroy #追加 has_many :users, through: :group_users, dependent: :destroy #追加  上記の4行にdependent: :destoryを追加しました。これ追加しとかないと後で削除処理を実際にやってみたらエラーを投げてきます。外部キーを参照しているためデータを消せないとか何とか…。他のデータベースでやったらどうなるか検証する気にはなりませんので詳しい方教えてください。  ですので、削除処理を追加する方は必ずモデルファイルに上記の追記をしておきましょう。 4.ルーティング  ルーティングについては特筆することはないと思います。コントローラーにどんな関数を実装するかによってここは適宜変えていただければと思います。 app/config/routes.rb resources :groups, only: [:index, :new, :create, :show, :edit, :update, :destroy] 5.コントローラーの作成  こちらも先達の方々のものを見よう見まねで書き写して実装していきました。最終的なコードはこちらになります。 app/controllers/group_controller.rb class GroupsController < ApplicationController before_action :set_group, only: [:edit, :update] def index @group_lists = Group.all @group_joining = GroupUser.where(user_id: current_user.id) @group_lists_none = "グループに参加していません。" end def new @group = Group.new @group.users << current_user end def create @group = Group.new(group_params) if @group.save redirect_to groups_url, notice: 'グループを作成しました。' else render :new end end def show @group = Group.find(params[:id]) end def edit @group = Group.find(params[:id]) end def update @group = Group.find(params[:id]) if @group.update(group_params) redirect_to groups_path, notice: 'グループを更新しました。' else render :edit end end def destroy delete_group = Group.find(params[:id]) if delete_group.destroy redirect_to groups_path, notice: 'グループを削除しました。' end end private def set_group @group = Group.find(params[:id]) end def group_params params.require(:group).permit(:name, user_ids: []) end end  実装したのは一覧表示(index)、新規作成(new,create)、詳細表示(show)、編集(edit,update)、削除(destroy)です。ここで躓き始めたわけですが、どんな風に躓いたかは後述します。 6.ビューの作成  こちらも必要最低限のことしか書いてません。とりあえず動けばいい、装飾は後からすればいい、そう考えていますので…。必要になってくるファイルは一覧表示(index)、グループ作成(new)、グループ編集(edit)、グループ詳細(show)の4つです。ひとまず最低限表示されるように以下の形で書きました。 app/views/group/index.html.erb <div class="chat-group">   <h1>チャットグループ一覧</h1> <div class="group-search"> <div class="group-search-form"> <%= form_with url: groups_path do |f| %> <%= f.text_field :keyword, placeholder: "グループ検索", class: "group-search-form-input" %> <%= f.submit '検索' %> <% end %> </div> <div class="group-new"> <%= link_to 'グループ作成', new_group_path %> </div> <% if @group_joining == [] %> <%= @group_lists_none %> <% else %> <div class="group-list"> <ul class="group-list-table"> <% @group_lists.each do |list| %> <% if list.user_ids.include?(current_user.id) %> <li class="group-list-table-each-group"> <%= link_to "/groups/#{list.id}" do %> <%= list.name %>(<%= list.user_ids.count %>) <%= link_to '編集', edit_group_path(list.id), method: :get %> <%= link_to '削除', "/groups/#{list.id}", method: :delete %> <% end %> </li> <% end %> <% end %> </ul> </div> <% end %> </div> <div class="user-page"> <%= link_to 'ユーザーページへ', current_user %> </div> </div> app/views/group/new.html.erb <h1>新規作成</h1> <%= form_with(model: @group, local: true) do |f| %> <div class="group-new-form"> <div class="gtoup-new-form-name"> <%= f.label :name, 'グループ名' %> <%= f.text_field :name, class: 'form-control' %> <%= f.collection_check_boxes :user_ids, User.all, :id, :username %> </div> <%= f.submit '新規作成', class: "btn btn-primary" %> </div> <% end %> app/views/group/edit.html.erb <h1>グループ編集</h1> <%= form_with(model: @group, local: true) do |f| %> <div class="group-new-form"> <div class="gtoup-new-form-name"> <%= f.label :name, 'グループ名' %> <%= f.text_field :name, class: 'form-control' %> <%= f.collection_check_boxes :user_ids, User.all, :id, :username %> </div> <%= f.submit '更新', class: "btn btn-primary" %> </div> <% end %> app/views/groups/show.html.erb <div class="group-show"> <div class="show-group-chat-back"> <span class="group-show-group-chat-back"> <%= link_to groups_path do %> < <% end %> </span> </div> <div class="chat-group-show-talk"> トーク </div> </div>  ビューの実装は以上です。シンプルにただ表示するだけのものですが、それでもこれだけの量打ち込む必要がありなかなか大変でした。 7.躓いた点  ただ先達のコードを書き写すだけで動くなら話は簡単でしたが、3つのトラブルのせいで散々回り道させられました。 7-1.グループが作成されない(permitの中身が空)  最初に躓いたのがこれです。コントローラーは間違いなく正確に書いた、にも関わらずuser_idsの中身が入っていないせいでグループが作成されない問題に直面しました。原因はビューの書き方にありました。最終的には問題の箇所は<%= f.collection_check_boxes :user_ids, User.all, :id, :username %>という形にすることで正常に動いたわけですが、そうなる前はNoNameエラーがただひたすらに返されました。「groupの中身が空ですよ?」だそうです。知らんがな。  この形で動くようになるまではただひたすら:user_idsの部分とコントローラーのStrong Permission(params.require(:group).permit(:name, user_ids: [])のとこ)をいじくり回してました。手探りで動くように試行錯誤しなければいけなかったのは大変でした。 7-2.メソッドがあらへんよ?(NoMethodError)  グループ作成がどうにか成功したと思ったら今度は編集画面をテストしていてまたもやエラー。editもupdateもパスつなげてあるはずなのにです。コントローラーも何度も先達のコードを確認して書いたにも関わらず「set_groupメソッドがありませんよ?」という理由でNoMethodErrorが帰ってきたわけです。先達のコード色々と見直しても誰もそんなメソッドについて書いている方はいませんでした。  そこで、何が原因かを探るためにもrails g scaffoldでCRUDファイル一式を作成した上でコントローラーのコードを今一度見直し、欠けている関数が何なのかを探ることから始めました。  結論を言ってしまいますと、あっけなく答えは出てきました。privateよりも下に以下のコード追加するだけでよかったんです。 app/controller/group_controller.rb def set_group @group = Group.find(params[:id]) end  ただこれだけでした。Railsの初歩的すぎるところすっ飛ばしていきなりアプリ作ったりしてましたので完全に盲点でした。そりゃ誰もここについて書かないわけですよ…。知ってて当たり前のことなんでしょうから…。 7-3.データが消せない!!  最後に躓いたのがグループ削除処理です。モデルファイルへの加筆のところでも少し触れましたが、外部キーを幾重にも使ったリレーションを構築している以上、特定のデータベースを使った場合か、全てのデータベースで起こることかは定かではありませんが、dependent: :destroyを追記しておかないと、外部キーを参照しているインスタンスを削除できない問題があるようです。もしこういった機能の実装を考えてる方がいましたらモデルファイルに追記するのを忘れないようにしましょうね? 8.最後に  結局実装に1日近くかかってしまったわけですが、いざ動くのを見ていると、やりきった達成感でいっぱいでした。もっとも、こうしたコードとかリレーションを考えてくれてた先達の方々がいたからこそ1日で済んだわけで私一人で最初から作ることを考えたら1日では済まなかったと思います。コードを考えてくれてた先達の方々に感謝します。 参考にしたサイト ・https://qiita.com/savaniased/items/ce7dd5a825ad0f6be53c ・https://no-idea.hateblo.jp/entry/2020/06/25/135552 ・https://yanai-blog.net/entry/%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%81%AE%E6%96%B0%E8%A6%8F%E4%BD%9C%E6%88%90%E3%83%BB%E7%B7%A8%E9%9B%86%E6%A9%9F%E8%83%BD%E3%81%AE%E5%AE%9F%E8%A3%85%EF%BC%88%EF%BC%91%EF%BC%89
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】いいね機能の実装 [初心者] まとめ

概要 投稿アプリ作成の際に「いいね機能」を実装しました。 いいね機能が動くまでの流れを忘れないために載せておきます! 環境構築・アプリ作成は既に済んでる状態で記載していきます。 環境 ruby 2.6.5 Rails 6.0.3.5 全体の流れ 今回は「userテーブル」「postsテーブル」「likesテーブル」の3つのテーブルで実装していきます。 ①【同期いいね】 ②【いいね数の表示】 ③【非同期いいね】 ④【アイコンの使用】 手順①【同期いいね】 likesテーブルの作成 ユーザーIDと投稿IDを保存するための「likesモデル」を作成。 カラムは外部キーの「user_id」「post_id」のみ。 以下のコマンドを実行 % rails g model Like user_id:integer post_id:integer % rails db:migrate このコマンド以外にもモデルの作成方法はあります。 以下のリンクを参考にしてください。 モデルとテーブルを作成する(Ruby on Rails) -Qiita Railsでモデルを生成する方法を現役エンジニアが解説【初心者向け】 アソシエーションの定義 user.rb class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :posts has_many :likes # この1行を追加 end post.rb class Post < ApplicationRecord belongs_to :user has_many :likes # この1行を追加 end like.rb class Like < ApplicationRecord belongs_to :user # この1行を追加 belongs_to :post # この1行を追加 end いいねの表示 次にビューを編集します。 ビューはいいねを押すことができるリンクを作成します。 「views/posts/index.html.erb」を編集し、「いいねを外す」と「いいね」がそれぞれ表示されるように設定します。 views>posts>index.html.erb <% if current_user.liked_by?(post.id) %> <div>いいねを外す</div> <% else %> <div>いいね</div> <% end %> 「liked_by?(post.id)」はユーザーがいいねを押しているかどうかを判断するメソッドです。 「liked_by?」メソッドの定義 likesテーブルに「post_id」が存在するかどうかの検索をかけます。 user.rb #下記を追加 def liked_by?(post_id) likes.where(post_id: post_id).exists? end exists?メソッドは値が存在すればtrue、存在しない場合はfalseを返すメソッドです。 いいねを押す ここまででビューにいいねが表示されます。しかし、リンクを付与していないため「いいね」をクリックすることができません。なので次はいいねを押したり解除できる機能を実装していきます。 likesコントローラー作成 % rails g controller likes 次にlikesコントローラーにcreateアクション(いいねを押す機能)を定義します。 likes_controller.rb class LikesController < ApplicationController def create Like.create(user_id: current_user.id, post_id: params[:id]) redirect_to posts_path end end ルーティングを作成 routes.rb Rails.application.routes.draw do devise_for :users root 'home#index' resources :posts post 'like/:id' => 'likes#create', as: 'create_like' #この1行を追加 % rails routesを実行すると「create_like POST /like/:id(.:format) likes#create」が出力されます。 次に「いいね」にリンクを付与するためにビューを編集します。 views>posts>index.html.erb <div>いいね</div> ↓ 以下のように編集 <div><%= link_to 'いいね', create_like_path(post), method: :POST %></div> これで「いいね」をクリックすることができるようになりました。 create_like_path はルーティング作成の時に「as: 'create_like'」でパス名を指定しています。 いいねを解除する 次にいいねを解除する機能を実装します。 likes_controller.rbにdestroyアクション(いいねを解除する機能)を定義します。 likes_controller.rb class LikesController < ApplicationController def create Like.create(user_id: current_user.id, post_id: params[:id]) redirect_to posts_path end #下記を追加 def destroy Like.find_by(user_id: current_user.id, post_id: params[:id]).destroy redirect_to posts_path end end 「find_byメソッド」は複数の検索条件を指定することができるメソッドです。 ルーティングも編集しましょう。 routes.rb Rails.application.routes.draw do devise_for :users root 'home#index' resources :posts post 'like/:id' => 'likes#create', as: 'create_like' delete 'like/:id' => 'likes#destroy', as: 'destroy_like' #この1行を追加 end rails routesを実行すると「destroy_like DELETE /like/:id(.:format) likes#destroy」が出力されます。 次に「いいねを外す」にリンクを付与するため、ビューを編集します。 views>posts>index.html.erb <div>いいねを外す</div> ↓ 以下のように編集 <div><%= link_to 'いいねを外す', destroy_like_path(post), method: :DELETE %></div> これで「いいねを外す」をクリックすることができるようになりました。 destroy_like_path はルーティング作成の時に「as: 'destroy_like'」でパス名を指定しています。 これでいいねを解除することができるようになりました。 挙動確認 これで【同期いいね】の実装は完了です。挙動を確認してみましょう。 クリックするごとに「いいね」→「いいねを外す」→「いいね」→「いいねを外す」と表示が変更されていれば成功です。 実装手順②【いいね数の表示】 次にいいねが押された数を表示させましょう。 いいね数の取得には「countメソッド」を使用します。 「countメソッド」を使用することで簡単に実装することができます。 index.html.erbを以下のように編集しましょう。 views>posts>index.html.erb <% if current_user.liked_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE %></div> <% else %> <div><%= link_to 'いいね', create_like_path(post), method: :POST %></div> <% end %> ↓ 以下のように編集 <% if current_user.favorited_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE %> <%= post.likes.count %></div> <% else %> <div><%= link_to 'いいねする', create_like_path(post), method: :POST %> <%= post.likes.count %></div> <% end %> これで【いいね数の表示】は完了です。 いいねの右側に「いいね」の数が表示されるようになりました。 実装手順③【非同期いいね】 次に非同期でのいいねを実装していきます。 少し実装が複雑になるので実装全体の内容を話します。 全体の流れ ⑴それぞれの投稿を部分テンプレートで切り出す。      ↓ ⑵JavascriptでHTML構造を置き換える。(「いいね」「いいねを外す」を押した瞬間の時)      ↓ ⑶それぞれの投稿の部分テンプレートに異なるidを付与して判別する では全体の流れを把握した上で実装していきましょう。 部分テンプレートの切り出し まずは「いいね」の箇所を部分テンプレートで切り出します。いいね部分を切り分けることでその部分だけを変更できるようにしています。 views>posts>index.html.erb <% @posts.each do |post| %> <% if current_user.liked_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE %> <%= post.likes.count %></div> <% else %> <div><%= link_to 'いいねする', create_like_path(post), method: :POST %> <%= post.likes.count %></div> <% end %> <% end %> ↓以下のように変更 <% @posts.each do |post| %> <%= render 'post', post: post %> <% end %> views>posts>_post.html.erb <% if current_user.liked_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE %> <%= post.likes.count %></div> <% else %> <div><%= link_to 'いいねする', create_like_path(post), method: :POST %> <%= post.likes.count %></div> <% end %> remote:trueの追加 次に以下のようにlink_toメソッドに「remote:true」を追加します。 【非同期いいね】では「remote:true」が必ず必要になります。 views>posts>_post.html.erb <% if current_user.liked_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE %> <%= post.likes.count %></div> <% else %> <div><%= link_to 'いいねする', create_like_path(post), method: :POST %> <%= post.likes.count %></div> <% end %> ↓ 以下のように編集 <% if current_user.liked_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE, remote: true %> <%= post.likes.count %></div> <% else %> <div><%= link_to 'いいねする', create_like_path(post), method: :POST, remote: true %> <%= post.likes.count %></div> <% end %> 「remote: true」を追加することで、パラメーターがHTML形式ではなくJS形式で送られるようになります。 今回は「remote: true」をlink_toメソッドに追加したことで、likes_controller.rbのcreateアクション後は、views/likes/create.js.erbが呼び出されることになります。 redirect_toの削除 「redirect_to」を記述すると画面遷移が行われてしまい、非同期処理ができなくなってしまいます。 そのため、likes_controller.rbの「redirect_to」の記述を削除します。 さらに、「before_action」を使用して、投稿のidを取得できるようにしましょう。 likes_controller.rb class LikesController < ApplicationController def create Like.create(user_id: current_user.id, post_id: params[:id]) redirect_to posts_path end def destroy Like.find_by(user_id: current_user.id, post_id: params[:id]).destroy redirect_to posts_path end end ↓ 以下のように変更 class LikesController < ApplicationController before_action :post_params def create Like.create(user_id: current_user.id, post_id: params[:id]) end def destroy Like.find_by(user_id: current_user.id, post_id: params[:id]).destroy end private def post_params @post = Post.find(params[:id]) end end js.erbファイルの作成 次に、 ⑵JavascriptでHTML構造を置き換える。(「いいね」「いいねを外す」を押した瞬間) の実装を行います。 createアクションとdestroyアクションのjs.erbファイルをそれぞれ作成しましょう。 (js.erbファイルが発火するか確認するため、alertを記載します) views>likes>create.js.erb alert('いいねを押す!'); views>likes>destroy.js.erb alert('いいねを解除する!'); 現時点でクリックした際に「非同期アラート」が表示されていればOKです。 idの付与 ⑶それぞれの投稿の部分テンプレートに異なるidを付与して判別する を実装していきます。 部分テンプレートを切り替える部分にidを付与します。 具体的には「id=”post_<%= post.id %>”」と記述することで、投稿それぞれに異なるidを付与することができます。 views>posts>index.html.erb <% @posts.each do |post| %> <%= render 'post', post: post %> <% end %> ↓ idを付与 <% @posts.each do |post| %> <div id="post_<%= post.id %>"> <%= render 'post', post: post %> </div> <% end %> これで部分テンプレートを切り替える際にidを付与することができるようになりました。 js.erbファイルの編集 部分テンプレートの切り替えができるようにそれぞれのjs.erbファイルを編集します。 「innerHTMLメソッド」を使用することで、特定のHTML要素を置き換えることができます。 -参考リンク- 要素の中身を変える!JavaScriptでinnerHTMLの使い方【初心者向け】 views>likes>create.js.erb document.getElementById('post_<%= @post.id %>').innerHTML = '<%= j(render @post) %>' views>likes>destroy.js.erb document.getElementById('post_<%= @post.id %>').innerHTML = '<%= j(render @post) %>' 「j」とは「escape_javascriptメソッド」の省略形です。部分テンプレート内の改行をエスケープ処理してくれます。 省略せず、以下のように記述することもできます。 document.getElementById('post_<%= @post.id %>').innerHTML = '<%= escape_javascript(render @post) %>' 挙動確認 これで【非同期いいね】の実装が完了しました。 正しく「いいね」と「いいねの数」がクリックごとに変更されていれば成功です。 実装手順④【アイコン使用】 いいねの基本的な動作は完了しました。 次にSNSで使用されているアイコンを用いたいいね機能を実装していきます。 アイコンはFontAwesomeを使用します。 FontAwesome:https://fontawesome.com/ FontAwsomeの導入 まずはFontAwesomeの導入から行います。 Gemの導入。 Gemfile gem 'font-awesome-sass' % bundle install 次に「application.css」の名前を「application.scss」に変更します。 さらに以下のコードを追加しましょう。(既にあるコードは消さないで下さい) application.css → application.scss @import "font-awesome-sprockets"; @import "font-awesome"; これでFontAwesomeを使用することができるようになります。 アイコンの表示 次にアイコンをビューで表示します。 「いいね」と「いいね解除」を区別するためにそれぞれのアイコンに「like-btn」と「unlike-btn」というクラス名を追加します。 また、link_toメソッドにも「like_link」というクラスを追加しています。 views>posts>_post.html.erb <% if current_user.liked_by?(post.id) %> <div><%= link_to 'いいね外す', destroy_like_path(post), method: :DELETE, remote: true %> <%= post.likes.count %></div> <% else %> <div><%= link_to 'いいねする', create_like_path(post), method: :POST, remote: true %> <%= post.likes.count %></div> <% end %> ↓ 以下のように編集 <% if current_user.liked_by?(post.id) %> <div> <%= link_to destroy_like_path(post), class: "like-link", method: :DELETE, remote: true do %> <i class="fa fa-heart unlike-btn"></i> <% end %> <%= post.likes.count %> </div> <% else %> <div> <%= link_to create_like_path(post), class: "like-link", method: :POST, remote: true do %> <i class="fa fa-heart like-btn"></i> <% end %> <%= post.likes.count %> </div> <% end %> 「link_to do --- end」を使用することで、アイコンがリンク化されます。 デザインの変更 次にCSSを用いて、アイコンの色を変更します。 likes.scss .like-link{ text-decoration: none; } .like-link:hover { background-color: #fff!important; } .like-btn { font-size: 10px; color: #C0C0C0; } .unlike-btn { font-size: 15px; color: #FF0000; } Scaffoldでアプリ作成すると以下のような記述がデフォルトで入る場合があります。 a { color: #000; &:visited { color: #666; } &:hover { color: #fff; background-color: #000; } } アイコンをhoverした際に背景が黒になるのを避けるため、「!important」を追加してコードを上書きします。 .like-link:hover { background-color: #fff!important; } 挙動確認 これでアイコンでのいいね表示が完了しました。 いいね機能の実装はこれで全て完了です! 参考リンク いいね機能 ❏Rails❏ -Qiita 【Rails】いいね機能の実装 -Qiita 最後に 今回は「同期いいね」「いいね数の表示」「非同期いいね」「アイコン使用」の4つの流れで実装していきました。 今後も時より復習していこうと思います。 振り返るといいね機能は簡単に実装できるので、ぜひ自身のアプリにも使用してみて下さい!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyで解くAtCoder ABC 200 (A,B,C問題まで)

はじめに Rubyの勉強の一環として,AtCoderのコンテストの過去問を解いています。 (割と楽しくて,半分くらい趣味になっていますが・・・) コンテストに出てみた せっかくなら大会に出たほうが目標ができて楽しめると思ったので,初心者向けのコンテストに出てみました。 結果としてはA~Fの問題のうち,A~Cまで解けて,DやEの問題を読んで考えてみている間に制限時間が終わってしまいました。 Rubyでの解説は少ないため,解説を読んで自分なりに考えたりしたことをまとめてみようと思います。 A - Century 1~3000の数字 N が与えられるので,西暦 N 年は何世紀かを出力する問題。 「金額にしたとき,何枚の100円玉で払えるか」という小学生向けの覚え方を思い出して,whileループで解いてみました。 ABC200_A n = gets.to_i cnt = 0 while n > 0 cnt += 1 n -= 100 end puts cnt 【解説を読んで】 「99を足して100で割って小数点以下を切り捨て」だともっと短く書けました。 ABC200_A N = gets.to_i puts (N + 99)/100.to_i B - 200th ABC-200 整数 N に対し, 以下のいずれかの操作を K 回行った結果を出力します。 整数 N が 200 の倍数であれば、N を 200 で割る。 そうでなければ、整数 N を、N の後ろに文字列として 200 を付け加えた整数に置き換える。 操作 1 はそのまま 200 で割ればいいとして,操作 2 は文字列に変換して操作してから数値に戻す必要があるかなと思ったのですが・・・ 操作 2 は「1000 をかけて 200 を足す」とすれば数値のまま同じことができるので,こうしました。 ABC200_B n,K = gets.split.map(&:to_i) K.times do if n%200 == 0 n /= 200 else n = n*1000 + 200 end end puts n C - Ringo's Favorite Numbers 2 N 個の数列内から 2 つの数値を選んだとき,その差が200で割り切れる ( 0 も含む) 組み合わせの個数を求める問題。 知識がまだ少ないので,自分なりに考えてやってみました。 「200 で割った余りが同じ数字どうしの組は,差が 200 で割り切れる」ことが基本方針です。 まず,数列内の全ての数値を,200 で割った余りに変換します。 その後,group_byメソッドで値ごとにキーにしたハッシュを生成します。 (例) [123, 223, 123, 523, 200, 2000] ↓ [123, 23, 123, 123, 0, 0] ↓ {123 => [123, 123, 123], 23 => [23], 0 => [0, 0]} 数字が 2 つあれば,その中から 2 つ選ぶ組み合わせは $ _2 C _2 $ 通り 数字が 3 つあれば,その中から 2 つ選ぶ組み合わせは $ _3 C _2 $ 通り 数字が 4 つあれば,その中から 2 つ選ぶ組み合わせは $ _4 C _2 $ 通り ... 数字が n つあれば,その中から 2 つ選ぶ組み合わせは $ _n C _2 $ 通り ということで,キー値ごとの値の個数を $ _n C _2 = \frac{n(n-1)}{2} $ で計算して足し合わせています。 ABC200_C N = gets.to_i nums = gets.split.map(&:to_i) nums.map! { |i|i%200 } h = nums.group_by{|i| i} cnt = 0 h.each_value do |arr| n = arr.length cnt += n*(n-1)/2 end puts cnt 感想 初めての大会でしたが,非常に楽しめました。 D問題以降は基本的なアルゴリズムの知識が必要そうなので,解説を読んだりほかの過去問も解いてみて,少しずつできるようになりたいと思っています。 ほぼ毎週,初心者向けの大会があるらしいので,来週も出てみようと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

オリジナルアプリ開発【Railsプロジェクトの作成】

現在、転職先の企業へのアピールポイントになるポートフォリオ作成(オリジナルアプリ開発)をしています。 私は、タスク管理ツールの完成を目指しています。 今回は、Railsの新規プロジェクトの立ち上げを行います。 Railsの新規プロジェクト作成 RailsでWebアプリケーションを作成します。(Rails6の環境がある前提)。 rails newコマンドを入力します。 ターミナル rails new [作成するアプリケーション名] ここでは、 『TaskApp』 という名前のアプリケーションを作成します。 ターミナル rails new TaskApp 命令文のrailsとnewの間にRailsのバージョンを入力すると、Railsのバージョンを指定できます。 作成したディレクトリに移動する cdコマンドを使って、新たに作成した『TaskApp』ディレクトリに移動します。 cdとは 「cd」は、change directory(ディレクトリを移動する)の略です。 ターミナル cd [移動したいディレクトリ名] ターミナル cd TaskApp コマンドを実行すると、『TaskApp』ディレクトリに移動します。 ローカルサーバーを起動 ローカルサーバーを立ち上げるには、次のコマンドを入力します。 ターミナル rails s ローカルサーバーを起動するときはターミナルで新規タブ(command+T)を 開いて行うと今までの作業と混同しなくて済みます。 うまくサーバーが起動すると、ターミナルで次のように表示されます。 ターミナル => Booting Puma => Rails 6.0.3.7 application starting in development => Run `rails server --help` for more startup options Puma starting in single mode... * Version 4.3.7 (ruby 2.6.5-p114), codename: Mysterious Traveller * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://127.0.0.1:3000 * Listening on tcp://[::1]:3000 Use Ctrl-C to stop Railsのデフォルトページを表示 ローカルサーバーを起動したら、ブラウザで「http://localhost:3000/ 」にアクセスします。 次の画像のようにRailsのデフォルトページが表示されていれば、うまく動作しています。 GitとGitHubに連携 GitとGitHubでファイルの変更修正のバージョン管理を行うために連携します。 1.立ち上げたアプリのローカルリポジトリを作成する。 2.commitする。 3.リモートリポジトリを作成する。(「Keep this code private」にチェックが入っていると非公開になってしまうので、チェックを外して、「Publish Repository」をクリックする。) 4.pushする。 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【rails6】Action Cableを EC2/Nginx/MariaDB/unicornの環境で使用する

こんにちは! 今日はEC2にデプロイしているアプリケーションにActionCableを適用させていきたいと思います 環境 Ruby on Rails 6.0 AWS/EC2 Nginx MariaDB unicorn エディタはVS Codeを使用しています ※上記の細かな解説は控えます 前提条件 ローカル環境でAction Cableは実装済み 上記環境を持ちいて、web上で通常の動作が確認できている Action Cableの実装開始 まずは完成品のGifをご確認ください ※ リロードの挙動が見られない ※ 送信時刻が"今"と自身で設定したものですので、間違いなくActionCabeが挙動している というご認識でお願いいたします では早速設定を始めていきましょう! 手順① 「Action Cableの環境設定ファイル、 cable.ymlの編集」 「config/cable.yml」に以下の記述に書き換えてください 【まずは従来の記述】 config/cable.yml development: adapter: async test: adapter: test production: adapter: redis url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> channel_prefix: kch_production ↓ 以下のように書き換えます ↓ config/cable.yml development: adapter: async test: adapter: test production: adapter: async # ここを書き換えるだけ ※本来async型の通信は非推奨ですが、今回はこのまま進めます development環境やtest環境での利用を意図したものであり、production環境で使うべきではありません。 とrailsガイドにも記述がございます 私はまた直してみます 手順② 「本番環境の設定 production.rbに追記」 「config/environments/production.rb」に以下の記述を書き足してください 一番下で大丈夫です config/environments/production.rb # 省略 # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session config.assets.initialize_on_precompile = false # ↓以下を書き足します ↓ ActionCable.server.config.disable_request_forgery_protection = true config.action_cable.url = 'ws://Elastic IP/cable' config.action_cable.allowed_request_origins = [ 'http://Elastic IP' ] end 手順③ 「Nginxの設定を編集する」 では、EC2にログインしていきましょう! ターミナル (base) takahiro@***** .ssh %. ssh -i ***.pem ec2-user@1*.1**.1*.1** ↓ ログインするとおなじみのアイコン?でお出迎え ↓ Last login: Sat May 8 13:53:22 2021 from 11-11-1-1.rev.home.ne.jp __| __|_ ) _| ( / Amazon Linux 2 AMI ___|\___|___| hogehugahogehuga〜〜 では、Nginxの設定をしていきましょう 下記のコマンドをコピペで実行しましょう! [ec2-user@i%-111-11-11-0 ~]$ sudo vim /etc/nginx/conf.d/rails.conf すると、下記の表示に変わるので、 「 i 」を押して編集モードに切り替えます upstream app_server { # Unicornと連携させるための設定 server unix:/var/www/自分のアプリ/shared/tmp/sockets/unicorn.sock; } # {}で囲った部分をブロックと呼ぶ。サーバの設定ができる server { # このプログラムが接続を受け付けるポート番号 listen 80; # 接続を受け付けるリクエストURL ここに書いていないURLではアクセスできない server_name 11.111.11.111; # 自分のElastic IPに書き換えてください # クライアントからアップロードされてくるファイルの容量の上限を2ギガに設定。デフォルトは1メガなので大きめにしておく client_max_body_size 2g; # 接続が来た際のrootディレクトリ root /var/www/自分のアプリ/current/public; # assetsファイル(CSSやJavaScriptのファイルなど)にアクセスが来た際に適用される設定 location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; root /var/www/自分のアプリ/current/public; } try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://app_server; } error_page 500 502 503 504 /500.html; } ~ ~ ~ ↓ 書き換えましょう ↓ upstream app_server { server unix:/var/www/自分のアプリ/shared/tmp/sockets/unicorn.sock; } server { listen 80; server_name 11.111.11.111; # 自分のElastic IPに書き換えてください client_max_body_size 2g; root /var/www/自分のアプリ/current/public; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; root /var/www/自分のアプリ/current/public; } try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://app_server; } error_page 500 502 503 504 /500.html; # ↓ 以下が書き加えられます ↓ location /cable { proxy_pass http://app_server/cable; proxy_http_version 1.1; proxy_set_header Upgrade websocket; proxy_set_header Connection Upgrade; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; } # ↑ 以上 ↑ } ~ ~ 書き換えましたら、 「 esc → : → w → q → Return(Enter) 」 を押して保存、終了します 手順④ 「Nginxを再起動」 上記から抜けましたら、Nginxを再起動しましょう [ec2-user@i%-111-11-11-0 ~]$ sudo systemctl reload nginx [ec2-user@i%-111-11-11-0 ~]$ sudo systemctl restart nginx これで全てOKです 本番環境でAction Cableが実装できました!! もし上手くいかないという方は、 ①インスタンスを再起動する ②unicornを再起動する ③MariaDBを再起動する ④もう一度デプロイし、全て再起動しなおす と複数試してみてください! 参考文献 今日もありがとうございました!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む