20210913のRubyに関する記事は27件です。

初心者がGemについて解釈する!

初めて聞いた時、何のことかさっぱりわからなかったです。。。 そもそもGemとは?初心者なりにわかりやすく噛み砕いていこうと思います! Gemとは? 結論は、GemはRubyのライブラリと言うことです! RubyGemsにはたくさんのライブラリがあり、それぞれをGemと呼ぶ。 ライブラリとは? 結論は、他のプログラムと組み合わせて使用する為に、複雑なプログラムを1つのセットにしたもの! プログラミングにおける拡張機能は、ライブラリと呼ばれ、複雑な機能実装でも、ライブラリをアプリへ読み込ませることにより、簡単に実装できるようになる!と言うことですね! まとめ わかりやすく言うと、良いパーツを使って簡単に実装していくって事だと思います! 言語化して説明するの本当に難しいです汗 間違っていたりしたら、遠慮なくご指導してください(; ;) とりあえず慣れるまで、今後もこんな感じで描いていこうと思います。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

kaminari gemってorderの位置で取得順変わるの?

RubyやRailsのページネーションの実装でよく使われるkaminari gem。 レビュワーから「orderの指定位置で中身の順番変わる可能性ある?」と指摘を受けて検証してみたので その結果のメモです。 どういうことかというと、次の2つって実行結果同じなの?という話。 Hoge.order('created_at ASC').page(0)  #1 Hoge.page(0).order('created_at ASC')  #2 1の方は、Hogeをcreated_atで昇順で並び替えた後に1ページ目の件数分を取得? 2の方は、Hogeから1ページ目の件数分を取得した後に並び替える? ということは1と2で結果が同じになることは保証されないのでは? という話。 結論 同じでした! 検証してみる コンソールで実行し、流れているSQLを確認します。 1:先にorderするパターン SELECT `products`.* FROM `products` ORDER BY created_at ASC LIMIT 11 OFFSET 0 2:後からorderするパターン SELECT `products`.* FROM `products` ORDER BY created_at ASC LIMIT 11 OFFSET 0 一緒ですね。 補足 あくまで1、2のような単純な例での話なのかもしれない。 気になる方は上記のようにコンソール実行して流れいているSQLを確認してみると良きかもです。 「このパターンだと結果変わる!」みたいなことあったら教えていただけると嬉しいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

<%= form_with do |f| %> updateやcreateが発火/動作しない問題

<%= form_with do |f| %> updateやcreateが発火しない問題 コントロールやモデルに問題があるコードがないのに発火/動作しない... updateやcreateができない原因は使っているタグ、ビューファイル(html.erb)に問題があるかも タグ <div></div> <table></table> いっぱいあるけど割愛 うまく動作しない集 form <form>#bootstrapで参考しがちなformタグ..これをform_withと併用するとうまく発火しない原因になる。 <%= form_with model:@user, local:true do |f| %> <%= f.label :profile_image %> <%= attachment_image_tag @user, :profile_image, :fill, 30, 30, fallback: "noimage.png"%> <%= f.submit %>#submitボタンを押して画面がrenderみたいに遷移する </form>#form_withを消して<div>で囲もう! tabel <table>#テーブルタグも同様になる可能性がある。あまり使わない方がいい <%= form_with model:@user, local:true do |f| %> <%= f.label :profile_image %> <%= attachment_image_tag @user, :profile_image, :fill, 30, 30, fallback: "noimage.png"%> <%= f.submit %> </table> しっかりとタグで囲もう!! <%= form_with model:@user, local:true do |f| %> <div>------------------------------------------------------------------------------------ <%= f.label :profile_image %> <%= attachment_image_tag @user, :profile_image, :fill, 30, 30, fallback: "noimage.png"%> <%= f.submit %> </div>----------------------------------------------------------------------------------- divで変な囲い方をすると発火しない原因になる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

2部グラフの判定の練習:BFS・DFS・Union-Find

2部グラフの判定をきちんとやったことが無かったので練習することにした。 また、通常のグラフ探索の方法で気になる点があり、Union-Findの要領で解決できそうだったので、これも試してみた。 グラフ探索 2部グラフの判定をするには、グラフの頂点に2値(例えば 0 と 1 )を振ってみて、矛盾が生じるか調査する。「辺で繋がった2頂点は逆の値」という規則があるため、適当な頂点に値を決め打ちしたら隣接する頂点を貪欲に埋めていけばいい(探索順序は問わない)。隣接する頂点に既に値が振ってあれば、それが期待通りかどうか検査する。 1セットの探索(例えば下記コードの bfs() 1回の呼び出し)では開始地点と連結な頂点しか調べられないので、未調査の頂点を探して何セットか探索する。 幅優先探索(BFS) 開始地点から近い順に頂点を埋めていくパターン。 bipartite_bfs.rb n, m = gets.split.map!(&:to_i) edges = Array.new(m) { gets.split.map!(&:to_i).map!(&:pred) } @nbrs = Array.new(n) { [] } edges.each do |i, j| @nbrs[i] << j @nbrs[j] << i end ########## @parity = Array.new(n) def bfs(k) @parity[k] = 0 queue = [k] while (i = queue.shift) expected = @parity[i] ^ 1 @nbrs[i].each do |j| if @parity[j] raise "Not bipartite" if @parity[j] != expected next end @parity[j] = expected queue << j end end end begin n.times { |k| @parity[k] || bfs(k) } puts :Yes rescue RuntimeError puts :No end 深さ優先探索(DFS) 再帰で書けば短く済むものの、スタックオーバーフローの危険がある。 bipartite_dfs.rb n, m = gets.split.map!(&:to_i) edges = Array.new(m) { gets.split.map!(&:to_i).map!(&:pred) } @nbrs = Array.new(n) { [] } edges.each do |i, j| @nbrs[i] << j @nbrs[j] << i end ########## @parity = Array.new(n) def dfs(i, expected = 0) if @parity[i] raise "Not bipartite" if @parity[i] != expected return end @parity[i] = expected @nbrs[i].each { |j| dfs(j, expected ^ 1) } end begin n.times { |k| @parity[k] || dfs(k) } puts :Yes rescue RuntimeError puts :No end 素集合データ構造(Union-Find) グラフ探索の方法で、連結でない頂点には適当な値を仮決めしているのが気になった。もし後から辺が追加されて連結になったら、1/2の確率で破綻してしまい、もう一度値を振り直す必要がある。仮決めではなく上手いこと相対的な偶奇性(同じ値なのか逆の値なのか)だけ記憶しておけば、辺が追加される状況にも対処できるのではないかと思った。 連結を扱える高速なアルゴリズムを考えたら、Union-Findが思い浮かんだ。この処理の中に2部グラフが成立していることの確認を追加してみた(Union-Find自体はAtCoder Libraryを参考にした)。 親ノードに対する偶奇性を記憶しておく 代表元は便宜上、自分自身に対する偶奇(なので必ず偶)とする 代表元の取得 find() では親ノードを変えるので、記憶している偶奇性も更新する 具体的には「 k ← j ← i 」という連鎖から「 k ← i 」の関係を求める グループの併合 union() では、代表元同士の偶奇を考えるよう変換する i と j を連結する(2部グラフなので関係が奇であることを要請する)際は、それらの代表元 ii と jj の間にリンクを張るが、この関係の偶奇を求める必要がある i と j が既に連結なら ii == jj であり、自分自身との関係は偶でなければ矛盾になる 辺が追加される状況に対応できるということで、事前に隣接する頂点のリスト(前節の @nbrs )を作る必要は無く、片っ端から辺の情報を与えていけばいい。 bipartite_dsu.rb n, m = gets.split.map!(&:to_i) edges = Array.new(m) { gets.split.map!(&:to_i).map!(&:pred) } ########## @parent = Array.new(n, -1) @parity = Array.new(n, 0) # relative to @parent[i] def find(i) return i if @parent[i] < 0 j = @parent[i] k = find(j) @parity[i] ^= @parity[j] @parent[i] = k end def union(i, j) ii = find(i) jj = find(j) expected = 1 ^ @parity[i] ^ @parity[j] if ii == jj raise "Not bipartite" if expected != 0 return end ii, jj = jj, ii if -@parent[ii] < -@parent[jj] @parent[ii] += @parent[jj] @parent[jj] = ii @parity[jj] = expected nil end begin edges.each { |i, j| union(i, j) } # n.times { |k| find(k) } # fix @parity: relative to find(i) puts :Yes rescue RuntimeError puts :No end テスト用の入力 正しく動作するか、高速に( O(n) 程度で)求まるか、などを確かめるためにテストデータを生成したい。頂点や辺の数は自由に指定できるようにする。 入力の作成とテスト実行 ruby bipartite_test_random.rb 100_000 100_000 > input.txt time ruby bipartite_bfs.rb < input.txt time ruby bipartite_dfs.rb < input.txt time ruby bipartite_dsu.rb < input.txt ※これはプログラムの実行時間全体を計っているので、判定アルゴリズムのみにかかった時間は見れない。 ランダムな辺 適当に選んだ2頂点に辺をひく(自己ループは除く)。辺の数 m を大きくすれば高確率で2部グラフではなくなる。 bipartite_test_random.rb n, m = ARGV.map(&method(:Integer)) raise "n must be positive" if n <= 0 raise "m must be non-negative" if m < 0 puts "#{n} #{m}" m.times do i = rand(n) j = i + 1 + rand(n - 1) puts "#{i + 1} #{j % n + 1}" end 2部グラフ 事前に頂点を2グループに分けておいて、必ずグループをまたぐよう辺をひく。 bipartite_test_true.rb n1, n2, m = ARGV.map(&method(:Integer)) raise "both n1 and n2 must be positive" if n1 <= 0 || n2 <= 0 raise "m must be non-negative" if m < 0 n = n1 + n2 grp1 = [*1..n].shuffle! grp2 = grp1.pop(n2) puts "#{n} #{m}" m.times do i, j = grp1.sample, grp2.sample i, j = j, i if rand < 0.5 puts "#{i} #{j}" end 閉路グラフ n が偶数のとき2部グラフ。深さ優先探索の再帰を効率よく殺すためのパターンで、どこから開始しても深さが n に達する。手元の環境( RUBY_THREAD_VM_STACK_SIZE=1048576 )では n = 3743 で死んだ。 bipartite_test_cycle.rb n, * = ARGV.map(&method(:Integer)) raise "n must be positive" if n <= 0 order = [*1..n].shuffle! order << order[0] pairs = order.each_cons(2).to_a.shuffle! puts "#{n} #{n}" pairs.each do |i, j| i, j = j, i if rand < 0.5 puts "#{i} #{j}" end 木・森 必ず2部グラフ。 bipartite_test_forest.rb n, m = ARGV.map(&method(:Integer)) raise "n must be positive" if n <= 0 raise "m must be non-negative" if m < 0 raise "m must be less than n" if m >= n order = [*1..n].shuffle! pairs = Array.new(m) do |i| j = rand(n - i - 1) + i + 1 [order[i], order[j]] end pairs.shuffle! puts "#{n} #{m}" pairs.each do |i, j| i, j = j, i if rand < 0.5 puts "#{i} #{j}" end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】gemのアンインストールの仕方

1.背景 Rubyを使用して個人開発を行っています。 使用を検討していたgem(ActiveRecord)をインストールしたものの結局使わなかったのでアンインストールしたところ、 別プロジェクトのデータベースが消えてしまい、「慎重にやっておけば良かった...」と思いました。 データベースは削除されていませんでした。なのでアンインストールの仕方を備忘録としてまとめます。 2.環境 mac.os バージョン10.15.6 Ruby 2.7.3 Rails 6.1.3.1 psql (PostgreSQL) 12.6 3.アンインストールを実行 下記のコマンドを実行し、Gemfileからも削除、bundle installを行いました。 project_name % bundle exec gem uninstall ActiveRecord 補足:bundle execコマンドについて bundle execコマンドとは、アプリのGemfile.lockに記載されているgemを使用するコマンドを言います。今回の場合だと該当プロジェクト内のGemfile.lockに沿ってアンインストールが実行されていることになります。 4.gemとは gemをまとめると下記のようになります。 ライブラリのうち、外部ライブラリに該当する インストールと読み込みで使用することができる 外部ライブラリのファイルやフォルダを1つのgem形式のファイルにパッケージングされたもの 5.インストール時とアンインストール時の違い インストールを行うとgem listに追加され、アンインストールを行うとgem listから削除されます。 # project_name % gem list  (--local) gem名 project_name % gem list  Activerecord *** LOCAL GEMS *** # gem名 (カッコ内はバージョン名) が表示される # アンインストールするとブランクになる activerecord (6.1.3.2, 6.1.3.1, 6.1.3, 6.1.2.1, 6.0.3.4) activerecord-import (1.0.8) kaminari-activerecord (1.2.1) ... 補足:アンインストールの使用例 (本当に)不要になったとき 古いバージョンのものを削除したいとき ※アップデートした結果、残った古いバージョンのgemを削除する場合は gem cleanupというコマンドもあります。 6.参考 1.【Rails】gemのアンインストール・バージョン変更 2.library rubygems 3.【Ruby】 gemの仕組みを図解形式で学ぼう 4.【Rails】gemとbundleについてまとめてみた 5.【Rails】 結局bundlerって何?bundlerの仕組みを図解形式で徹底解説 6.RubyGemsの使い方 7.最後に 記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。 読んでいただき、ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】gemのアンインストールは、慎重に。

1.背景 Rubyを使用して個人開発を行っています。 使用を検討していたgem(ActiveRecord)をインストールしたものの結局使わなかったのでアンインストールしたところ、 別プロジェクトのデータベースが消えてしまい、「慎重にやっておけば良かった...」と思いました。 今回はその反省を備忘録としてまとめます。 2.環境 mac.os バージョン10.15.6 Ruby 2.7.3 Rails 6.1.3.1 psql (PostgreSQL) 12.6 3.アンインストールを実行 下記のコマンドを実行し、Gemfileからも削除、bundle installを行いました。 project_name % bundle exec gem uninstall ActiveRecord その結果、無事削除することができました。しかし、別プロジェクト(RubyとRuby on Rails使用)のデータベースが削除されてエラーになりました。 データベースを作成し直した話はこちら(作成中) 補足:bundle execコマンドについて bundle execコマンドとは、アプリのGemfile.lockに記載されているgemを使用するコマンドを言います。今回の場合だと該当プロジェクト内のGemfile.lockに沿ってアンインストールが実行されていることになります。 特定のプロジェクトのみ使用しているgem(またはバージョン)だと一部アンインストールになるのですが、いろんなところで使用している場合だとその分影響する範囲が多くなります。 「bundle exec」をつけると特定のプロジェクトのgemのみをアンインストールできるという思い込みが失敗の原因でした 4.gemとは gemをまとめると下記のようになります。 ライブラリのうち、外部ライブラリに該当する インストールと読み込みで使用することができる 外部ライブラリのファイルやフォルダを1つのgem形式のファイルにパッケージングされたもの 5.インストール時とアンインストール時の違い インストールを行うとgem listに追加され、アンインストールを行うとgem listから削除されます。 # project_name % gem list  (--local) gem名 project_name % gem list  Activerecord *** LOCAL GEMS *** # gem名 (カッコ内はバージョン名) が表示される # アンインストールするとブランクになる activerecord (6.1.3.2, 6.1.3.1, 6.1.3, 6.1.2.1, 6.0.3.4) activerecord-import (1.0.8) kaminari-activerecord (1.2.1) ... 今回はアンインストールをすることでインストールそのものをなかったことにしているので、インストール+読み込みで使用できる条件から外れてしまい、別プロジェクトのデータベースが消えてしまいました。 補足:アンインストールを使うときはこんなとき (本当に)不要になったとき 古いバージョンのものを削除したいとき ※アップデートした結果、残った古いバージョンのgemを削除する場合は gem cleanupというコマンドもあります。 6.参考 1.【Rails】gemのアンインストール・バージョン変更 2.library rubygems 3.【Ruby】 gemの仕組みを図解形式で学ぼう 4.【Rails】gemとbundleについてまとめてみた 5.【Rails】 結局bundlerって何?bundlerの仕組みを図解形式で徹底解説 6.RubyGemsの使い方 7.最後に 記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。 読んでいただき、ありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

view内でif文を用いた条件分岐のスマートな書き方[Ruby, Rails]

はじめに 今回の記事はとても局所的なテーマを扱います Rubyの構文において、以下のようなif文を用いた冗長的な書き方を、よりスマートにまとめます app/views/announcement.html.erb Before <th>配信元</th> <td> <% if @announcement.user_id %> <%= @announcement.user.name %> <% else %> 管理者 <% end %> </td> 結論 三項演算子を用いて、かつ文字列の部分はStringオブジェクトにします After <th>配信元</th> <td><%= @announcement.user_id ? @announcement.user.name : "管理者" %></td> 想定状況 announcementインスタンスはuserインスタンスに紐づく、もしくは紐づいていない、状況です app/models/user.rb class User < ApplicationRecord has_many :announcements, dependent: :destroy end app/models/announcement.rb class Announcement < ApplicationRecord belongs_to :client, optional: true end ポイント 文字列の部分をStringクラスにしていること 以下の場合、Encountered a syntax error while rendering templateのエラーが発生し、失敗します。理由は、Railsが<%= %>のなかに、存在しない変数もしくはメソッドを探してしまうからです(管理者の部分)。 なので、ただの文字列の場合でもクオテーションで囲んであげることで、ただの文字列を文字列オブジェクトにする必要があります。 失敗例 <th>配信元</th> <td><%= @announcement.user_id ? @announcement.user.name : 管理者 %></td> # 管理者 → "管理者" こうしないとだめ さいごに とても小さなテーマですが、5行が1行になったことは感動しました(知識不足なだけやん 最後までお読み頂きありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】bulletを使ってN + 1問題解決

N + 1問題とは N+1問題とは、データベースからデータを取り出す際に、大量のSQLが発行されてパフォーマンスが低下してしまう問題のことです。以前にN + 1問題について配信してありますので気になった方はご参照ください。 bulletとは N + 1問題がどこに発生しているかお知らせしてくれるgemです。 公式のドキュメント 導入方法 以下のコードをGemfileに追記。 Gemfile group :development do gem 'bullet' end $ bundle install デフォルト設定 config/environments/development.rb Rails.application.configure do # ここから config.after_initialize do Bullet.enable = true Bullet.alert = true Bullet.bullet_logger = true Bullet.console = true # Bullet.growl = true デフォルトでコメントアウト Bullet.rails_logger = true Bullet.add_footer = true end # ここまでが追加。 end (解説) * Bullet.enable...Bulletのgemを利用可能 * Bullet.alert...ブラウザにJSのアラート表示 * Bullet.bullet_logger...bulletのログファイルを表示 * Bullet.console...console.logに警告 * Bullet.growl...Growlがインストールされているときに、ポップアップの警告を表示 * Bullet.rails_logger...railsのログに警告を表示 * Bullet.add_footer...画面左下にメッセージを表示 N + 1問題検出 実際に使用すると、下記の感じで警告が表示。 ご丁寧に修正方法まで記載 表示の通りコントローラーにincludes[:user])に修正 #before @chats = Chat.all #after @chats = Chat.includes(:user) [Before] [After] includesを指定することで関連をまとめて取得し、最小限のクエリ回数を減らせました。 最後に N+1問題に自分で気づけない人のために便利だと思いますが、やはり設計、開発でN+1問題が生じない為にもSQLに強くなる必要があると感じました。今回、SQLのクエリの画像を残すべきところを失念しており申し訳ございません
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラー:Routing Error_Uninitialized constant HomesControllerにつまづいた話

Ruby on Rails ver.5.2.5にて通販サイトの作成をするにあたり、namespaceとscope moduleの使い分けができておらず発生したエラー。 初心者ゆえの初歩的なミスですが、備忘録として記しておきます。 ■エラー内容 devise にて管理者側と顧客側を定義し、namespaceによりcontrollerをそれぞれ[controllers/admin]と[controllers/public]に棲み分けて作成しました。 そしてrutes.erbを以下のように記載 各controllerにアクション名を定義し、いざサーバー起こしてページ確認しようと思ったら、、 Routing Error Uninitialized Constant HomeController というエラーが発生。 エラーの内容は、namespaceにて定義されているadmin側のルーティングは辿れるけど、それより前のルーティングは一体どこの階層のコントローラを呼んでんの?分からないよ?というエラーでした。 ■解決方法 scope moduleでpublic側も設定してあげないといけなかったようです。 ここで使用した scope module: 'public' do 〜 end ですが、namespaceとは異なり、URLに/publicを追加せず、controller#actionにだけpublic/を追加することができるようです。 public側はURLに/publicを表示しないという仕様のため、namespaceで指定しなければいいのか〜と思っていたのですが、コントローラアクションはちゃんとpublicフォルダ内のコントローラを使うよ!と設定してあげないといけなかったんですね。 勉強になりました...。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6 コメント機能でよくある問題の解決方法】

実装内容 以前に投稿したコメント機能実装の記事では、お伝えできなかったコメント機能で起こりうる問題点とその解決方法をまとめてみました。 解決する問題一覧 改行問題 半英数字の連続文字によるはみ出し問題 改行問題(プレビュー) before after 半英数字の連続文字によるはみ出し問題(プレビュー) before after 環境 macOS Big Sur 11.2.3 ruby: 2.7.2 rails: 6.1.3 jQuery テンプレートエンジン: slim レイアウト: bootstrap4 改行問題の解決法 改行しても反映されず、文字が続いて表示されてしまう問題から解決していきます。 app/views/comments.hide_comments.html.slim = comment.comment # before = simple_format(comment.comment) # after Railsのヘルパーメソッドであるsimple_formatを使用することで、コメントを以下の条件で整形し、改行されるようになります。 文字列を<p>で囲む 改行には<br />を付与 連続した改行は、</p><p>を付与 英数字の連続文字によるはみ出し解決法 日本語の場合、単語の途中でも自動で改行されるのですが、英数字の場合、表示範囲を超える連続する長いものは改行されずはみ出してしまいます。 app/assets/stylesheets/application.scss body { // 半角英数折返しの設定 word-wrap: break-word; overflow-wrap: break-word; } CSSのword-breakプロパティを使用し、値をbreak-wordとすることで、枠内に収まらない英単語の場合は単語の途中でも折り返しますが、枠内に収まる限り、単語の途中では折り返さないようにしてくれます。また、overflow-wrapはword-wrapの古い名称で、サポートされていないブラウザもあるため、併記した方がいいようです。 最後に 以上でコメント機能でよくある問題の解決方法でした! 実はポートフォリオ完成後にレビュー会を行なったのですが、その時指摘してもらい、初めて気づいた感じでした^^; 間違っている箇所や分かりづらい箇所が多々あるかと思います。 その際は、気軽にコメントいただけれると幸いです。 最後までご覧いただき、ありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] AtCoder 過去問 B - Collatz Problem

はじめに AtCoder過去問B問題をRubyで解いてみました。 他の方々の解き方を見ていると自分の解き方をしている人は見かけなかったので考え方少し変なのかなと思いながら、ACいただいているからいっかと思ったりしています。 それではよろしくお願いします。 問題はこちらから確認してください。↓ B - Collatz Problem まずは入力を受け取ります、今回はシンプルですね。 integerで受け取ります。 s = gets.to_i aを配列で管理します。 入力値が初期値となるので配列aに入れておきます。 s = gets.to_i a = [s] 問題文に従って条件分岐をして、配列aに追加するif文を作ります。 s = gets.to_i a = [s] if s % 2 == 0 s = s/2 a << s else s = 3*s +1 a << s end このifの処理を繰り返すのですが、uniqメソッドを使って条件式を作成します。 配列aの要素が重複したらuniqメソッドで重複している要素を取り除きます。 uniqメソッドを使用した配列aと何もメソッドを使っていない配列aが同じ間はifの処理を繰り返すようにします。 要素が重複したらこの条件から外れるので処理が終わります。 s = gets.to_i a = [s] while a.uniq == a if s % 2 == 0 s = s/2 a << s else s = 3*s +1 a << s end end 処理が終わった時点の配列aの要素の数=答えですのでlengthメソッドで出力して完成です。 s = gets.to_i a = [s] while a.uniq == a if s % 2 == 0 s = s/2 a << s else s = 3*s +1 a << s end end puts a.length
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails g kaminari:views bootstrap4でNo such file or directoryのエラー解決方法

実装したいこと ある記事を参考にgem 'kaminari'を導入してページネーション機能を作ろうとしておりました。 gemの導入後に、% docker-compose run web rails g kaminari:views bootstrap4コマンドを実行したところタイトルのようなエラーが発生したので解決に至るプロセスをまとめようと思います。 エラー内容 % docker-compose run web rails g kaminari:views bootstrap4 % docker-compose run web bundle exec rails g kaminari:views bootstrap4 Creating locat_web_run ... done Running via Spring preloader in process 29 /usr/local/bundle/gems/kaminari-core-1.2.1/lib/generators/kaminari/views_generator.rb:117:in `initialize': No such file or directory @ rb_sysopen - https://api.github.com/repos/amatsuda/kaminari_themes/git/refs/heads/master (Errno::ENOENT) from /usr/local/bundle/gems/kaminari-core-1.2.1/lib/generators/kaminari/views_generator.rb:117:in `open' from /usr/local/bundle/gems/kaminari-core-1.2.1/lib/generators/kaminari/views_generator.rb:117:in `get_files_in_master' from /usr/local/bundle/gems/kaminari-core-1.2.1/lib/generators/kaminari/views_generator.rb:41:in `themes' from /usr/local/bundle/gems/kaminari-core-1.2.1/lib/generators/kaminari/views_generator.rb:30:in `copy_or_fetch' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/command.rb:27:in `run' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/invocation.rb:134:in `block in invoke_all' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/invocation.rb:134:in `each' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/invocation.rb:134:in `map' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/invocation.rb:134:in `invoke_all' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/group.rb:232:in `dispatch' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/base.rb:485:in `start' from /usr/local/bundle/gems/railties-6.1.3.1/lib/rails/generators.rb:275:in `invoke' from /usr/local/bundle/gems/railties-6.1.3.1/lib/rails/commands/generate/generate_command.rb:26:in `perform' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/command.rb:27:in `run' from /usr/local/bundle/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command' from /usr/local/bundle/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch' from /usr/local/bundle/gems/railties-6.1.3.1/lib/rails/command/base.rb:69:in `perform' from /usr/local/bundle/gems/railties-6.1.3.1/lib/rails/command.rb:50:in `invoke' from /usr/local/bundle/gems/railties-6.1.3.1/lib/rails/commands.rb:18:in `<main>' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require' from /usr/local/bundle/gems/zeitwerk-2.4.2/lib/zeitwerk/kernel.rb:34:in `require' from /locat/bin/rails:5:in `<main>' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load' from /usr/local/bundle/gems/bootsnap-1.7.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/commands/rails.rb:6:in `call' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/command_wrapper.rb:38:in `call' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/application.rb:220:in `block in serve' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:10:in `block in fork' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:10:in `block in fork' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:8:in `fork' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:8:in `fork' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:26:in `fork' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:8:in `fork' from /usr/local/bundle/gems/activesupport-6.1.3.1/lib/active_support/fork_tracker.rb:26:in `fork' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/application.rb:180:in `serve' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/application.rb:145:in `block in run' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/application.rb:139:in `loop' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/application.rb:139:in `run' from /usr/local/bundle/gems/spring-2.1.1/lib/spring/application/boot.rb:19:in `<top (required)>' from <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require' from <internal:/usr/local/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require' from -e:1:in `<main>' ERROR: 1 kaminari導入後に、bootstrap4のページネーションのデザインに合わせたビューファイルを上記のコマンドで実行したところエラーが発生しデザインを適用できない状態になりました。 こちらの記事を参考にしたところ、既にrequire 'open-uri'は記述されていたためエラー解決できませんでした。 解決方法 こちらの記事を参考にしたところ、 gem 'kaminari'を gem 'kaminari', git: 'https://github.com/kaminari/kaminari' に修正した後にで解決できたと記載されていました。 gemfileを修正後にbundle installを行い、再度コマンドを実行したところbootstrapが適用できました。 % docker-compose run web rails g kaminari:views bootstrap4 Creating locat_web_run ... done Running via Spring preloader in process 29 downloading app/views/kaminari/_first_page.html.erb from kaminari_themes... create app/views/kaminari/_first_page.html.erb downloading app/views/kaminari/_gap.html.erb from kaminari_themes... create app/views/kaminari/_gap.html.erb downloading app/views/kaminari/_last_page.html.erb from kaminari_themes... create app/views/kaminari/_last_page.html.erb downloading app/views/kaminari/_next_page.html.erb from kaminari_themes... create app/views/kaminari/_next_page.html.erb downloading app/views/kaminari/_page.html.erb from kaminari_themes... create app/views/kaminari/_page.html.erb downloading app/views/kaminari/_paginator.html.erb from kaminari_themes... create app/views/kaminari/_paginator.html.erb downloading app/views/kaminari/_prev_page.html.erb from kaminari_themes... create app/views/kaminari/_prev_page.html.erb 同じようなエラーに遭遇している方の参考になれば幸いです。  開発環境 rubymine ruby(3.0.1) Ruby on rails (6.1.3.1) Docker (20.10.7)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby会議2021 レポート

こんにちは!最近rubyを書き始めたHiraです! 今回は、Ruby会議2021に参加してきたので紹介したいと思います! ほとんど、自分のメモ用なので、実際の内容に関して知りたい方は、公式のYoutubeがアップロードされていたので、そちらからご確認ください! https://www.youtube.com/channel/UCBSg5zH-VFJ42BGQFk4VH2A イベントのタイムスケジュールとセッション セッション すべてを見ることはできなかったので、個人的に気になったトピック TypeProf for IDE: Enrich Dev-Experience without Annotations IDEによる、静的型付けがメインのお話 ruby3.1から解析が可能 rubyの静的解析機はTypeProf,Steep,Sorbet等がある。 其の中でも、TypeProfは、型を明示しなくても良いが、エラーレポートが弱いらしい。 RBSを書いて上げると静的解析の際に早く解析でき、明示しているのでご動作もあんくなる。 Why Ruby's JIT was slow JITと呼ばれるコンパイラのお話。正直、コンパイラの話は全然わからなかったが、AtCoderなどの競技プログラミングをする際にはコンパイルの速さとかが関係あるので、意識しなければならないポイントなのかもしれない、、、 MJITが悪さをしていて遅くしていた。 MJITを使うとcにコンパイルしているから、わかりやすい。 cにコンパイルしていることで、後にgccにコンパイルするから、メンテンス性が良くなる。 m-jit,y-jit,MIRなどの種類がある。 RuboCop in 2021: Stable and Beyond RuboCopによる静的解析ツールのお話 ver1.0以前の方が一番ダウンロード数が多かったらしい、、、! 新しいcopが入ってきた際には、pendingで選択できるようにしている。 新しいcopを入れるときにどうするかをnew cop: trueみたいなので、適用できる。 新しいrubyの場合は、最新にupdateする必要あり。 parallelオプションを使う場合はとても早くなる。defaultになった。 ルールが厳しいと感じたら DiasabledByDefault: trueを使って、実際の遭遇したものを随時copとして、追加していく。 rubocop_rails_config のgemを使うことによって、ruleが厳しいと感じたら使う。 Steepなどをいれて、静的解析をもう少し賢くするというか、型による解析を行っていこうと思っている。 The Art of Execution Control for Ruby's Debugger 個人的に一番良かったセッション、、、!時間があるときに使ってみたい! 新規のdebug gemの話。 スライド: https://www.atdot.net/~ko1/activities/2021_rubykaigi_takeout.pdf 既存のデバッガー lib/debug.rb byebug debase ruby-debug Ractorに対応するために作られた vscodeとも連携していて、breakpointの指定とかもできて、変数名などもみることができる。 trace on 、trace offもできて、一部のlogみたいなのを出せる。 リモートデバッグができる。(railsのデバッグもできる!) record onみたいなので、巻き戻視機能があり、変数の値などが確認できる。 break pointを使っても、既存のデバッガーよりも大分早い! The newsletter of RBS updates 最新のRBSとして、依存関係を見たうえで勝手にRBSファイルを作成してくれるという便利になったよ的なお話。個人的に、RBSをつかうのであれば、めちゃくちゃ役立つ気がする、、、? RBS railsと呼ばれる、ruby on railsのためのRBS生成機がある。 新機能(rbs collection) - rbsのためのbundler - third partyのためのrbsを準備するのが厳しかったため、開発した。 - もともと、rbsをrailsに入れるために、全て依存関係を考えた上で、行う必要があった。 - rbsコマンドと、steepの設定が混雑していた。 - rbsコレクションコマンドを使うと、依存性を自動的に解決してくれる。 - rbsファイルの設定をコマンド操作可能になる。 - gemfile.lockから、依存関係を認識している。 Charty: Statistical data visualization in Ruby rubyによるグラフの可視化。 統計的データ可視化 A列とB列とC列があった際に、それに対応したデータの作成が可能。 グラフ処理は外部ライブラリに任せている plotolyなどを使っている。 様々な入力パターンに対応している。 adopterを書くことで、対応する型を増やすことが可能。 Ruby, Ractor, QUIC Ractorを使った、QUICの実現。Transport層での通信周りを行っている話で、パケット通信をrubyで行っていた。パケットの生成から、デコードまで行おうとしていたが、残念ながらRactor内でOpenSSLが使えずに終わってしまった。今後、対応していけば、こういったことも実現できるので期待大。 全体の所感 ruby初心者には難しいセッションが多かったですが、噛み砕いて説明してくれるセッションも多く、勉強になりました! 新しいgemや静的解析のツールが今後も出てくると思うので、いろいろと使ってみたいなと感じました! (英語のセッションがほんとに聞き取れなかったので、そこも勉強しなきゃと感じました、、、。)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

退会したユーザーの表示を変える

現在投稿系のアプリを作っていて退会したユーザーの扱いどうしようかなーと考えていたら、teratailなどのサービスで「退会済みユーザー」のような表記になっているのを見受けました 直感的に見てもわかりやすいし実装もしやすそうだなと思ったのでこれで行こうと思います。 実装 まず退会機能なんですが、完全にデータを削除といったことはせずに退会したことにするといった 論理削除といった状態にするといいといろんな記事に書いてありました。 論理削除の概要については下記記事がわかりやすかったので参考させていただきました 情報提供を依頼されたりするときにすぐに出せるようにするみたいなこともあるみたいですね。 誹謗中傷とか犯罪予告とか まあ僕の場合は投稿系なので100件投稿してくださったユーザーが退会した時にそれを全部削除するってなったら中身がスカスカになりそうだと思ったんで退会した場合はユーザーネームを 退会済みユーザーみたいな表記に変えてコメントや投稿を残すことにしました まずは退会の扱いですが、users,テーブルにis_deletedとかdeleted_flagみたいなカラムを持たせてboolean型で追加します maigration class AddIsDeletedToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :is_deleted, :boolean, default: false, null: false end end add_column (追加したいテーブル), (カラム名), (データ型), null:falseなどの制約 デフォルトをfalseにすることで退会処理が実行された時にtrueになり、このユーザーは退会したユーザーとして扱えます。 view 例) <% if @user.is_deleted == false %> *is_deletedがfalseなので退会していないことになる <%= @user.username %> <% else %>   *elseでis_deleted == trueの場合、つまり退会した場合の表示にする* 退会済みユーザー <% end %> もっと適切な使い方があるのだと思いますが、僕はこれが精一杯でした。。 こんな感じで投稿やコメントは残したまま退会ユーザーとして扱えます。 結構穴がある実装だと思います。 正直これ以外でつかえる場面が思いつかないのでこれでいいか不安ですがとりあえず現状は問題ないのでこのまま行きます。 退会したら30日間は同じメールアドレスで登録できないみたいな感じの動作が理想なのでしょうが、データが変わるのはis_deletedだけなので他のカラム(username,email,password)達は残っているので退会したら同じメールアドレスでログインすることが2度とできなくなるっぽいです まあデータが残ったままですからね 自分でも調べますが、こんなん良いよみたいな案がありましたらコメントで教えていただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RubyKaigi Takeout 2021参加したYO

はいどうもー!Ruby on RailsエンジニアYOです。 先日RubyKaigi Takeout 2021に参加したので、個人的に面白いセッション、感想も含めてメモりたいです。 個人向けのメモ程度の内容ですので、イベント自体に興味ある方は公式のYoutubeアーカイプ待ちましょうね。見てね: コロナの状況がまだ落ち着いていないので、今年のRubyKaigiもTakeout形式での主催になります。サイトはこちらです: https://rubykaigi.org/2021-takeout (個人的に)面白かったセッション イベントのタイムスケジュールとセッション表: 以下一日目のセッション TypeProf for IDE: Enrich Dev-Experience without Annotations(by Yusuke Endoh) Ruby向けの型推測ツール(?)を作ったので、そのメリットとまだバグってるところの共有です。Rubyは静的型言語じゃないので、型はきっちり決めていなくて、渡された値によって型が決まります。 methodのautocompleteや、間違った関数を渡すときにもIDE上で警告を出せます。 感想:そういうツールを作るときの考え方は自分全く考えたことなかったので(考える必要もなかった)、その中身の話をしてくれて大変勉強になりました。あと世の中はどんどんVSCodeなので、そろそろIDEも切り替えたい。 slide: https://www.slideshare.net/mametter/typeprof-for-ide-enrich-development-experience-without-annotations RuboCop in 2021: Stable and Beyond(by Koichi ITO) RuboCop 1.0 & それ以降のバージョンの話。 --parallel optionで並行実行ができます! 自動修正がもっとよくなったとか、-A optionで全部修正もできます(危険ですが。。。) 感想:Rubyやってる人ならほぼ全員が使ってるRuboCop、大変便利なツールを作ってくれてありがとうございます!書き方の指摘などで、勉強になることも何回かありました! Ruby Archaeology(by Nick Schwaderer) Ruby考古学の授業を受けた感じです。 昔のRubyの書き方や、歴史を、今もよく使われてるツールのcommit日付が古いコードからピックアップして解説した感じです。 感想:良い意味での変人感が溢れてるスピーカーです。wあと色々お土産くれます(ruby version 1.8のvagrantbox?)。 vagrantbox: https://app.vagrantup.com/schwad/boxes/ruby_archaeologist 以下二日目のセッション Ractor’s speed is not light-speed(by Satoshi "moris" Tagomori) Ruby Actorからとって、Ractorと呼ぶらしいです。 RubyのParallel処理のために開発された新機能(?)らしいです。 自分はRactorの存在を今日まで知らなかったので、もうちょい勉強すべきです(土下座) まだ大規模アプリケーションで検証していないので、本当に速くなるかどうかがまだ不明です。 感想:ある意味で今まで知らなかったことを知ることになったので、これからは少しずつアンテナを張って情報収集したいです! Ruby Committers vs the World いわばRuby Commitersたちと対話できるセッション! というものの、中の人が話しつつ、チャット欄を見てみんなの質問や疑問に答える感じのセッションです。 金曜日の午後でもあるため、ほぼ飲み会感が出てます。w 感想:あぁー我々は巨人の肩の上に立ってるのだなぁーと感じさせました。そしてその巨人達を見る機会ができてよかったです。 以下三日目のセッション Do regex dream of Turing Completeness?(by Daniel Magliola) 「Game of LifeをRubyのregexだけで、実装できないか?」と、すごくチャレンジングなハックをやっている人です。 化け物みたいなでかいregexを生成して一発で置換させる方法です。 Turingマシーンの話も出てました。 感想:これもマニアックなセッションです。でもやってる試みがとっても面白いで、聞いてて楽しいセッションです。 資料&slide: https://github.com/dmagliola/regex_game_of_life Dive into Encoding(by Mari Imaizumi) Rubyの文字エンコードを理解するために、IROHAエンコードを作った話です。 Rubyの文字エンコードをどうやって作られたのか、どうやって新しいエンコードを作るのか知ることができます。 Rubyのカーソルがかわいい。 感想:普段何も考えずに使ってる文字エンコードの中身がしれて、少し成長しました。最近は日本語の文字化けは結構出なくなったので、だいぶ楽な世の中になったなぁー slide: https://speakerdeck.com/ima1zumi/dive-into-encoding Matz Keynote(by Yukihiro "Matz" Matsumoto) 我らRubyの生みの親、Matzさんからのキーノートです。 Matzさんのキーノートは過去に数回も聞きましたが、2.5 -> 2.7 -> 3.0 -> 3.1で、rubyのバージョンアップの話です。 2.7 -> 3.0 までは聞きましたが、それ以降は暫くブリなので、raptorやパフォーマンス向上なども結構進めたので、いい話です。 3日間のセッションの振り返り&総括もしていました。 Rubyを速くすると賞金がもらえるシステムも考案中みたいで、Rubyがどんどん速くなることを押したいです!みんなも支援できればお願いします!(Rubyふるさと納税で盛り上がった!) 感想:Ruby 3.0も去年12月25日にリリースされて(クリスマスの日に毎年りりーするらしい)、そろそろ新しいバージョンも使って行かないとどんどん置いていかれちゃいそうです。 全体の感想 コロナで世の中がリモートワークの流れになりました。通勤時間が減って、個人の自由時間が増えたが、孤独との戦いや、精神的なストレスの対処をしてそろそろ一年半過ぎました。エンジニアとしてもニューノーマルに慣れてきた(と思う)ので、また昔見たいに、いろんな処の勉強会に参加して、新しい技術をどんどん触っていきたいです! そんな考えを改めたイベントでした! とりあえずasakusa.rbを調べて、次の勉強会から参加したいです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

日本語でエラー文章

gemを入れる GEM gem 'rails-i18n' bundle install config/application.rbに追記 config/application.rb module Stoma class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 5.2 config.i18n.default_locale = :ja ここ追加する # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. end end 3点未入力がありますのエラー部分テンプレート作成 layouts/_errors.html.erb <% if obj.errors.any? %> <div id="error_explanation"> <h3><%= pluralize(obj.errors.count, "点") %> 未入力があります</h3> <ul> <% obj.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> obj:@エラー文の対象とし、部分テンプレートを呼び出す html <%= render 'layouts/errors', obj: @ostomy%> config/locales/models/ja.ymlで日本語化する インデントずれると翻訳できないので注意 config/locales/models/ja.yml ja: activerecord: errors: messages: record_invalid: 'バリデーションに失敗しました: %{errors}' restrict_dependent_destroy: has_one: "%{record}が存在しているので削除できません" has_many: "%{record}が存在しているので削除できません" attributes: ostomy: color: ストーマの色 edema: むくみ skin: 皮膚の状態 ##########この順序でかく################################## attributes:        # attributes:の直下 post:           # モデル名 title: 名前       #カラム    content:ブログ本文    #カラム名 ############enumsの訳も以下############################ enums:  #enum ostomy: #モデル名 color:  #カラム pink: ピンク #訳 red: あか #訳 brown: ちゃいろ #訳 black: くろ      #訳
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】退会機能をgemなしで実装する方法

対象者 退会機能を実装予定の方 目的 退会機能を実装して退会後、ログイン出来ないようにする 実際の手順と実例 1.deviseの導入 User認証で新規登録とログインを行うためにdeviseを導入します Gemfile. gem 'devise' Terminal. $ bundle install $ rails g devise:install $ rails g devise user name:string is_valid:boolean #① $ rails g devise:views ①で退会したかどうかを判断するカラムを作成しています。 booleanは真偽のどちらの値なのかを決めるデータ型です。 boolean型はデフォルト値を設定する必要があるので、マイグレーションファイルを編集します。 db/migrate/20210815082848_add_is_valid_to_users.rb class AddIsValidToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :is_valid, :boolean, default: true, null: false end end デフォルト値がtrue(有効)に設定しているのでfalseが退会している状態を表しています。 Terminal. $ rails db:migrate 実行後下記のようにテーブルが作成されます。 db/schema.rb create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" t.string "name" t.boolean "is_valid", default: true, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end 2.コントローラーの設定 Homes_Controllerに作成していきます。 app/controllers/homes_controller.rb def unsubscribe #退会画面 @user = current_user end def withdraw #退会処理 @user = User.find(params[:id]) @user.update(is_valid: false) #falseにすることで退会済に変更 reset_session redirect_to root_path, alert: "ご利用誠にありがとうございました。" end 続いて退会済のUserが再ログインできないようにSessions_Controller に設定していきます。 app/controllers/users/sessions_controller.rb before_action :reject_user, only: [:create] : (中略) : # 退会後のログインを阻止 def reject_user @user = User.find_by(name: params[:user][:name]) if @user if @user.valid_password?(params[:user][:password]) && (@user.active_for_authentication? == false) flash[:error] = "退会済みです。" redirect_to new_user_session_path end else flash[:error] = "必須項目を入力してください。" end end 3.ルーティングの設定 config/routes.rb get "unsubscribe/:name" => "homes#unsubscribe", as: "confirm_unsubscribe" patch ":id/withdraw/:name" => "homes#withdraw", as: "withdraw_user" put "withdraw/:name" => "users#withdraw" 4.Viewの設定 app/views/homes/unsubscribe.html.erb <div class = "container"> <div class = "title text-center">本当に退会しますか?</div> <div class = "card unsub-text"> <div class = "row justify-content-center"> <div class = "text-center"> <p class = "py-3"> 退会すると、会員登録情報が閲覧できなくなります。<br> 退会する場合は『退会する』をクリックしてください。 </p> <div class = "row unsub-text mt-3"> <div class = "no-delete"> <%= link_to "退会する", withdraw_user_path(@user), method: :patch, data: { confirm: '本当に退会しますか?' }, class: "btn btn-outline-danger btn-sm " %> </div> <div class = "float-right"> <%= link_to "退会しない", user_path(@user), class: "btn btn-outline-primary btn-sm" %> </div> </div> </div> </div> </div> </div> ※bootstrap4を使用しています。 applicaiton.scss // 退会機能 .unsub-text { text-align: center; margin: 50px; } .no-delete { margin-left: 50px; margin-right: 100px; text-align: center; } これで実装完了です! 参照 Rubyでbooleanの判定を行う方法を現役エンジニアが解説【初心者向け】
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

トランザクションとは。

はじめに 本記事では、トランザクションについて記述しました。 トランザクションとはなんですか? と聞かれた際に、私は何も答えることができませんでした。 悔しかったので調べました。 トランザクションとは レコードの更新を行う複数の処理を1つにまとめて行うことを指します。 トランザクションを利用することにより、 「処理の一部は成功し、一部は失敗した」という事象は発生せず、 すべての処理の成功または失敗のみの状態を作ることができます。 Railsではこのような利用 ActiveRecord::Base.transaction do 処理1 処理2 処理3 ... end ここに処理1、処理2...を1つのまとまりとして記述することで、 処理が1つでも失敗すれば、全体としての処理は失敗ということになります。 トランザクションのACIDプロパティー 以下を参照しています。 トランザクションは、銀行のATMに例えることが多いみたいです。 かなりわかりやすいので勝手にオススメです。 トランザクションの ACID プロパティー トランザクション処理における ACID という頭字語は、原子性 (A)、一貫性 (C)、独立性 (I)、および耐久性 (D) というトランザクションの 4つの重要なプロパティーを表しています。 A 原子性を表すAtomicity トランザクションが終わった時に、 そこに含まれていた更新処理が全て実行されるか、 全て実行されない状態で終わることを保証する性質。 ある口座から別の口座に資金を移動するアプリケーションで、原子性プロパティーは、ある口座から引き落としが正常に行われると、対応する入金が別の口座に行われることを保証します。 C 一貫性のConsistency トランザクションに含まれる処理はそれぞれの制約を満たすという性質。 ある口座から別の口座に資金を移動するアプリケーションで、一貫性プロパティーは、各トランザクションの開始時と終了時で、両方の口座の資金の合計金額が同じになることを保証します。 I 独立性のIsolation トランザクションが実行中の場合、 もう一方のその他のトランザクションの影響を受けないという性質。 ある口座から別の口座に資金を移動するアプリケーションで、独立性プロパティーは、別のトランザクションから見て移動資金がいずれかの口座に存在していて、両方に存在していたりどちらにも存在しなかったりすることはないことを保証します。 D 耐久性のDurability トランザクションが完了した後、そのデータ状態が保存され失われることは無いという性質。 ある口座から別の口座に資金を移動するアプリケーションで、耐久性プロパティーは、それぞれの口座に対して行われた変更が元に戻されることはないことを保証します。 以上です。 終わりに 今回もスマッシュブラザーズで例えてやろうと考えており、 ファルコンパンチってトランザクションじゃないかなとか思ったんですが、 ファルコンパンチってBボタンを押したら、モーションはあるものの、 複数の処理を1つにまとめているかと言われたら違うような気がしたので、やめました。 自分の知らなかった言葉を 何か身近なものに例えて理解するのはとてもいいなと感じております。 以下参考サイトです。 「トランザクションのACID特性」を理解する トランザクションの ACID プロパティー 明日も頑張ります!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 入門 [インスタンス変数を簡単に操作]

● インスタンス変数を簡単に操作する class Drink def name ———#①attr_reader :name @name end def name=(text) ———#②attr_write :name @name = text end end drink = Drink.new drink.name="カフェラテ" puts drink.name ↪️カフェラテ ①と②の省略できる書き方 class Drink attr_reader :name ———#① attr_writer :name ————#② end drink = Drink.new drink.name="カフェラテ" puts drink.name ↪️カフェラテ ①と②を合体させたattr_accessor class Drink attr_accessor :name end drink = Drink.new drink.name="カフェラテ" puts drink.name ↪️カフェラテ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 入門 [例外の詳しい情報を得る]

● 例外の詳しい情報を得る 例外オブジェクトの代入 begin  #例外が発生する可能性がある処理 rescue 例外クラス => e #変数eに例外オブジェクトが代入される  #例外が発生する可能性がある処理(rescue節) end def cat(filename) #ファイルの内容を表示する File.open(filename) do |file| —————①ファイルを開く file.each_line {|line| puts line} ————②ファイルの内容を表示する end ————③ファイルを閉じる resucue SystemCallError => e ————④例外処理 : 例外オブジェクトを変数eに代入 puts "--- 例外が発生しました ---" puts "例外クラス: #{e.class}" ———⑤e.classで例外オブジェクトのクラス名を表示 puts "例外メッセージ: #{e.message}” ————⑥e.messageで例外メッセージを表示 end filename = ARGV.first ———⑦コマンドプロントの引数を読み込み cat(filename) ↪️>ruby cat.rb menu.txt -menu.txtテキストファイルを用意して”カフェラテ””カプチーノ”を入力 カフェラテ カプチーノ 存在しない適当なファイル名を指定してプログラムを実行すると ↪️>ruby cat.rb not found.txt —例外が発生しました— 例外クラス: Errno::ENOENT 例外メッセージ: No such file or directory @ rb_sysopen - not found.text ●Fileクラス —ファイル操作に組み込みライブラリのFileクラスを使う ●File.open —引数filenameで指定したファイルを開きファイル操作のためのFileオブジェクトを作ってfile変数に代入する ●each_line —配列のeachに似たメソッドで、ファイルの先頭から1行ずつ読み込み、繰り返しline変数 に代入する。読み込んだ各行は、putsメソッドで画面に表示する。 ●SystemCallError => —ファイル操作などに失敗した時に発生する例外クラスです。例外クラスの後ろの=> eのeは変数。受け取った例外オブジェクトが変数eに代入される。 ●e.class —例外オブジェクトのクラス名を表示 ●e.class —例外のメッセージを表示 ●classとmessage —例外クラスで使えるメソッド ●ARGV —Rubyが用意した特別な定数で、コマンドプロントで指定した引数を要素として持つ配列。AVGRで先頭の要素を取得する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 入門 [例外を処理]

● 例外を処理する 例外処理 begin  #例外が発生する可能性がある処理 resucue  #例外が発生した時に実行する処置(resucue節) end puts "金額を入力してください" bill = gets.to_i puts "割り勘する人数を入力してください" number = gets.to_i begin warikan = bill / number puts "1人あたり#{warikan}円です" rescue ZeroDivisionError # ZeroDivisionError例外が発生したらメッセージを表示する puts "おっと、0人では割り切れません" end ↪️金額を入力してください 100 割り勘する人数を入力してください 0 おっと、0人では割り切れません ——#例外がなければ発生しない ↪️金額を入力してください 100 割り勘する人数を入力してください 4 1人あたり25円です 例外がなければresucue節は発生しない。 0で割り算した時に発生するZeroDivisionError例外を処理する時はrescue ZeroDivisionErrorと書く。 メソッド内で例外処理を書く場合は、beginとrescueを省略できる。メソッドの初めからrescueまでの処理で発生した例外を、rescue節で受け入れる。 def warikan(bill, number) warikan = bill/number puts "1人あたり#{warikan}円です" rescue ZeroDivisionError # ZeroDivisionError例外が発生したらメッセージを表示する puts "おっと、0人では割り勘できません" end warikan(100,0) warikan(100,1) warikan(100,2) ↪️おっと、0人では割り勘できません 1人あたり100円です 1人あたり50円です Ruby2.5以降ではブロック内でもbeginとendを省略できる。 bill = 100 numbers = [0,1,2] numbers.each do |number| warikan = bill/number puts "1人あたり#{warikan}円です" rescue ZeroDivisionError puts "おっと、0人では割り勘できません" end ↪️おっと、0人では割り勘できません 1人あたり100円です 1人あたり50円です
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 入門 [部分を共同利用-モジュール]

複数のクラスでメソッドを共同利用する モジュールの定義 modul モジュール end モジュールはクラスと似ているが、クラスと違ってインスタンスを作ることができない。 ● モジュールにメソッドを定義する module whippedCream def whipped_cream @name += "ホイップクリーム" end end ↪️#何も表示されない クラス同様、定義しただけではメソッドは実行されない ● モジュールのメソッドをクラスで使う -inclide includeメソッド class クラス名  include モジュール名 end module WhippedCream def whipped_cream @name += "ホイップクリーム" ——————#① end end class Drink include WhippedCream ————#② def initialize(name) @name = name ————#③ end def name @name ————#④ end end drink = Drink.new("モカ") ————#⑤ drink.whipped_cream ————#⑥ puts drink.name ————#⑦ ↪️モカホイップクリーム ①で@nameの末尾に”ホイップクリーム”が足される ②モジュールWhippedCreamのメソッド、whipped_creamが利用可能になる ③⑤のDrink.newメソッドの引数に”モカ”が渡され、@nameに代入される ④戻り値として@nameに代入されているオブジェクトを返す ⑤③に”モカ”を渡す ⑥Drinkオブジェクトのwhipped_creamメソッドが呼び出される ⑦@nameを取得すると”モカホイップクリーム”になっている ● モジュールは複数のクラスで共同利用できる module WhippedCream def whipped_cream @name += "ホイップクリーム" end end class Drink include WhippedCream def initialize(name) @name = name end def name @name end end class Cake include WhippedCream def initialize(name) @name = name end def name @name end end drink = Drink.new("モカ") drink.whipped_cream puts drink.name cake = Cake.new("チョコレートケーキ") cake.whipped_cream puts cake.name ↪️モカホイップクリーム チョコレートホイップクリーム モジュールは複数のクラスで使える。複数のクラスでモジュールをincludeすることで、そのモジュールを共同利用できる。 ● モジュールのメソッドをクラスメソッドにする -extend クラスにモジュールを定義する class クラス名  include モジュール end module Greeting ————#①extendメソッドで利用するモジュールを定義 def welcome ————#②extendしたいメソッドをインスタンスメソッドとして定義 "いらっしゃいませ!" end end class Cafe extend Greeting ————#③extendメソッドの引数にモジュールGreetingを渡す end puts Cafe.welcome ————#④Cafeクラスのクラスメソッドwelcomeを呼び出す ↪️いらっしゃいませ! ● モジュールにクラスメソッドを定義する module Whipped_Cream def self.info "トッピング用ホイップ" end end puts Whipped_Cream.info ↪️トッピング用ホイップクリーム 定数を使った例 #クラスメソッドinfoを定義して呼び出している module Whipped_Cream Price = 100 ———#Priceは定数なので、大文字出始める end puts Whipped_Cream::Price ↪️100 #Whipped_creamの中で定義されている定数Priceを使う時はWhipped_cream::Priceで繋げて書く ● 名前空間 クラス名(またはモジュール名)の指定 クラス名(またはモジュール名)::クラス名(またはモジュール名) module BecoCafe class Coffee def self.info "深みと香りのコーヒー" end end end module MachuCafe class Coffee def self.info "豊かな甘みのコーヒー" end end end puts BecoCafe::Coffee.info puts MachuCafe::Coffee.info ↪️深みと香りのコーヒー 豊かな甘みのコーヒー モジュール名::クラス名と書くことでクラスを使い分けることができる 部分を別ファイルに分ける ● 別ファイルのクラスやモジュールを読み込む whipped_cream.rbファイル module WhippedCream def whipped_cream @name += "ホイップクリーム" end end drink1.rbファイル require_relative "whipped_cream" ————#whipped_cream.rbファイルを読み込んでいる class Drink include WhippedCream def name @name end def initialize @name = "モカ" end end mocha = Drink.new mocha.whipped_cream puts mocha.name ↪️モカホイップクリーム ● includeとrequire_relativeの違い include ———モジュール名を渡してそのモジュールに書かれたメソッドをクラスから利用できるよう             にするメソッド require_relative ———ファイル名を渡してそのファイルに定義されたクラスやモジュールを使えるよ        うにするメソッド ファイルを読み込む require_relative “ファイル名”
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 入門 [クラス]

クラスとは オブジェクトを作る方法(newメソッド) ● オブジェクト作成 クラス.new #=>そのクラスのオブジェクト ● クラスの定義(class) class クラス名 end ● クラスのオブジェクトを作る クラス.new #=>そのクラスのオブジェクト オブジェクトが呼び出せるメソッドを作る ● クラスでのメソッド定義 class クラス名  def メソッド名  end end ● クラスに定義したメソッドを呼び出す class Drink def name "カフェラテ" end end drink = Drink.new ————#①Drinkクラスのオブジェクトを作って変数drinkへ代入 puts drink.name ————#②Drinkクラスのオブジェクトのnameメソッドを呼び出す ↪️カフェラテ ● クラスに引数を受け取るメソッドを定義する class Drink def order(name) ————#引数として受け取ったオブジェクトを変数nameへ代入 puts "#{name}をください" end end drink = Drink.new ————#Drinkクラスのオブジェクトを作って変数drinkへ代入 drink.order("カフェラテ") ————#orderメソッドを呼び出して引数で”カフェラテ”を渡す ↪️カフェラテ ● クラスの中で同じクラスのメソッドを呼び出す class Drink def name "モカ" + topping ————#①同じクラスのtoppingメソッドを呼び出し end def topping "エスプレッソショット" end end drink = Drink.new ————#② puts drink.name ————#③ ↪️モカエスプレッソショット オブジェクトにデータを持たせる ● インスタンス変数 class Drink def order(item) puts "#{item}をください" @name = item ————#インスタンス変数@nameに注文した商品itemを代入 end def reorder puts "#{@name}をもう一杯ください" —#orderメソッドで変数@nameに代入した商品を使う end end drink = Drink.new ——————#① drink.order("カフェラテ") ————#② drink.reorder ———————#④ ↪️カフェラテをください カフェラテをもう一杯ください ● インスタンス変数を取得するメソッドを作る class Drink def order(item) puts "#{item}をください" @name = item end def name ————#①nameメソッドを定義 @name ————#②戻り値として@nameに代入されているオブジェクトを返す end end drink = Drink.new drink.order("カフェラテ") puts drink.name ————#③drink.nameの戻り値を画面に表示しする ↪️カフェラテをください カフェラテ ● インスタンス変数へ代入するメソッドを作る class Drink def name=(text) ————#①name=メソッドを定義した @name = text ———#③引数で渡された”カフェオレ”をインスタンス変数@nameへ代入 end def name @name end end drink = Drink.new drink.name="カフェオレ” ———#②name=メソッドを呼び出し、引数として”カフェオレ”を渡す puts drink.name ↪️カフェオレ ● instance_variablesメソッド class Drink def name=(text) @name = text end def name @name end end drink = Drink.new drink.name=("カフェラテ") puts drink.name p drink.instance_variables ————#インスタンス変数の変数名一覧を取得するメソッド ↪️カフェラテ [:@name] ● selfを使ってレシーバーを調べる class Drink def name=(text) p self ——————#② @name = text end def name @name end end drink = Drink.new drink.name=("カフェラテ") puts drink.name p drink ————#① ↪️#<Drink:0x00007fc9f90d8980> ————①で表示したdrinkオブジェクト カフェラテ #<Drink:0x00007fc9f90d8980 @name="カフェラテ"> ————②でselfで取得してレシーバ #:に続く文字列はそのオブジェクトの認識番号で、これが同じであれば同じオブジェクトです オブジェクトが作られる時に処理を行う ● initializeメソッド class Drink def initialize ——————#①initializeメソッドを定義 puts "新しいオブジェクト!" end end Drink.new ——#②newメソッド呼ばれるとオブジェクトが作られますが、その際にinitializeメソッド                                  ↪️新しいオブジェクト! -------#が自動で呼ばれる。 ● インスタンス変数の初期値設定する class Drink def initialize @name = “カフェラテ” ——#①インスタンス変数@nameに”カフェラテ”が代入されます end def name @name end end drink = Drink.new ——#②Drink.newしてオブジェクトが作られる時にinitializeメソッドが呼ばれる puts drink.name ↪️カフェラテ ● initializeメソッドへ引数を渡す class Drink def initialize(name) ———-#①initializeメソッドに引数を受け取るに定義しています @name = name ———#②引数で受け取ったオブジェクトを@nameへ代入します end def name @name end end drink = Drink.new("モカ") ———#③newメソッドを呼び出し”モカ”を渡しています puts drink.name ————#④@nameの変数の中身を表示すると”モカ” ↪️モカ クラスを使ってメソッドを呼び出す ● クラスメソッドを定義する def self.メソッド名 end class Cafe def self.welcom ——————#①クラスメソッドを定義する時はメソッド名の前にself.をつける "いらっしゃいませ!" end end puts Cafe.welcom ———#②Class.welcomeのように、クラス名につづいて.メソッド名で呼び出すことができます。 ↪️いらっしゃいませ!                           ● 同じクラスのメソッドを呼び出す class Cafe def self.welcome "いらっしゃいませ!" end def self.welcome_again welcome + "いつもありがとうございます!" ————#クラスメソッドwelcomeを呼び出し end end puts Cafe.welcome_again ↪️いつもありがとうございます! 継承を使ってクラスを分ける ● 継承を使ってクラスを分ける class クラス名 < スーパークラス名 end class Item def name @name end def name=(text) @name = text end end class Drink < Item ———#① def size @size end def size=(text) @size = text end end item = Item.new item.name = "マフィン" drink = Drink.new drink.name = "カフェオレ" ——————#② drink.size = "tall" puts "#{drink.name} #{drink.size}サイズ" ↪️カフェオレ tallサイズ ①class Drink < Item でクラスを定義すると、Itemクラスを継承したDrinkクラスを作ることができる。このDrinkクラスはItemクラスの全てのメソッドを受け継具ことができる。つまりここでは、Itemクラスとnameメソッドとname=メソッドをDrinkクラスでも使うことができる。 ②でDrinkクラスのオブジェクトへ呼び出しているname=メソッドは、親にあたるItemクラスのname=メソッドを使っている。 ● 親メソッドのメソッドを呼び出す -super class Item def name @name end def name=(text) @name = text end def full_name ———#④superで呼び出される @name end end class Drink < Item def size @size end def size=(text) @size = text end def full_name ———#②full_nameを定義 super ————#③親クラスの同名メソッドだ呼び出される end end item = Item.new item.name = "マフィン" drink = Drink.new drink.name = "カフェオレ" drink.size = "tall" puts drink.full_name ———#①呼び出し ↪️カフェオレ メソッドの呼び出しを制限する ● クラスのメソッド定義の中だけで呼び出せるメソッドを作る class Cafe def staff makanai —————#① end private ————#③以降で定義するメソッドをprivateなメソッドにする def makanai "店員用スペシャルメニュー" end end cafe = Cafe.new puts cafe.staff puts cafe.makanai ————#② ↪️店員用スペシャルメニュー Traceback (most recent call last): one.rb:13:in `<main>': private method `makanai' called for #<Cafe:0x00007f89db87c7d0> (NoMethodError) ● privateとpublic class Foo def a ————#public end def b ————#public end private def c ————#private end public def d ————#public end end #Privateをメソッド定義するdefの前に書くことで、そのメソッドだけをprivateなメソッドにできる class Foo private def a ————#private end def b —————#public end end ● privateなクラスメソッドを定義する class Foo private_class_method def self.a ——#メソッド定義のdefの前にprivate_class_methodと書く "method a" end end p Foo.a ↪️Traceback (most recent call last): one.rb:7:in `<main>': private method `a' called for Foo:Class (NoMethodError)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

簡単例: Singleton(オブジェクト)

概要 下記 MyClass を Singleton にする簡素なコード. myclass.rb #!/usr/bin/env ruby # -*- encoding: utf-8 -*- require 'singleton' class MyClass include Singleton attr_accessor :a def initialize @a = 0 end def run(val) @a = val end end user.rb 上記 MyClass.rb の呼び出し側. #!/usr/bin/env ruby # -*- encoding: utf-8 -*- require_relative 'myclass' if __FILE__ == $0 o = MyClass.instance o.run(44) puts "o.a => <#{o.a}>" end 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] 簡単例: Singleton(オブジェクト)

概要 Singleton の概念は知っており、 単に Ruby ではどのように書くのかを知りたかっただけなので、 簡素なコードを書き残しておく. 下記は、MyClass を Singleton にする例である. myclass.rb singleton モジュールの取り込みにより、 「new メソッドが非公開」になり、且つ「インスタンス変数 instance」が定義される #!/usr/bin/env ruby # -*- encoding: utf-8 -*- require 'singleton' class MyClass include Singleton attr_accessor :a def initialize @a = 0 end def run(val) @a = val end end user.rb 上記 MyClass.rb の呼び出し側. newメソッドは使えないので、instance メソッドでインスタンスを得る. メソッド run は、単にインスタンス変数へのアクセス例である. #!/usr/bin/env ruby # -*- encoding: utf-8 -*- require_relative 'myclass' if __FILE__ == $0 o = MyClass.instance o.run(44) puts "o.a => <#{o.a}>" end 参考書籍 ・Rubyによるデザインパターン 以上
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初歩中の初歩】Ruby・if文を参考演算子でスマートに書いてみよう

今回はタイトルの通り、三項演算子について触れてみます。 文字列aとbが与えられていて、ふたつが一致すれば「Yes」、一致していなければ「No」と表示させるコードを考えてみます。 if文を使う場合のコードが下記のようになります。 if文利用 a = gets b = gets if a==b print "Yes" else print "No" end 次に三項演算子を用いて書いた場合が下記になります。 三項演算子利用 a = gets b = gets print a==b ? "OK":"NG" 「条件 ? 出力パターン1 : 出力パターン2」でif文がスマートに書けました! ぜひ使ってみましょう★
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初歩中の初歩】Ruby・if文を三項演算子でスマートに書いてみよう

今回はタイトルの通り、三項演算子について触れてみます。 文字列aとbが与えられていて、ふたつが一致すれば「Yes」、一致していなければ「No」と表示させるコードを考えてみます。 if文を使う場合のコードが下記のようになります。 if文利用 a = gets b = gets if a==b print "Yes" else print "No" end 次に三項演算子を用いて書いた場合が下記になります。 三項演算子利用 a = gets b = gets print a==b ? "OK":"NG" 「条件 ? 出力パターン1 : 出力パターン2」でif文がスマートに書けました! ぜひ使ってみましょう★
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む