- 投稿日:2020-02-24T23:09:14+09:00
check_boxとradio_button
チェックボックスとラジオボタンを作ろう
今回はラジオボタンはスムーズに出来たのですが、チェックボックスで少し苦戦したのでメモをしたいと思います。
説明
小説サイトを練習として真似して作成中です。
まず最初に、タイトルやキーワード、小説のジャンルなどを纏めるテーブル
novel_listsテーブルを作りました。続いて、今回のチェックボックスとラジオボタン部分です。
・ novel_keyword キーワード
・ genre ジャンル二つのカラムを作りました。
novel_list.rb
こちらにenumを使って配列を作りたいと思います。
ジャンルの配列 enum genre:{ different_world: 1, #異世界 real_world: 2, #現実世界 high_fantasy: 3, #ハイファンタジー low_fantasy: 4, #ローファンタジー } キーワードの配列 enum novel_keyword:{ status_difference: 1, #身分差 year_difference: 2, #年の差 non_love: 3, #非恋 villain_daughter: 4, #悪役令嬢配列が出来た所で、フォームです。novel_listsのnew.html.erbに今回は作成します。
<%= form_with(model: @novel_list, local: true) do |f| %> form_withの中に今回は作っていきたいと思います。 <%= f.radio_button :genre, :different_world, checked: "checked" %> <%= f.label :genre, "異世界", class: "different_world" %> <%= f.radio_button :genre, :real_world %> <%= f.label :genre, "現実世界", class: "real_world" %> <%= f.radio_button :genre, :high_fantasy %> <%= f.label :genre, "ハイファンタジー", class: "high_fantasy" %> <%= f.radio_button :genre, :low_fantasy %> <%= f.label :genre, "ローファンタジー", class: "low_fantasy" %> まずはラジオボタンですね。 第一引数部分にカラム名としてgenre 第2引数部分にプロパティ名 最後にオプションとして、checked:"checked" これを入れる事で最初に異世界のラジオボタンにチェックが入った状態となります。 ちなみにradio_buttonは一つしか選択が出来ません。 続いて・・・チェックボックスです。こちら苦戦して、teratailで質問しました。後半URL置いておきます。 <%= f.check_box :novel_keyword, {}, :status_difference, nil %> <%= f.label :novel_keyword, "身分差", class: "status_difference" %> <%= f.check_box :novel_keyword, {}, :year_difference, nil %> <%= f.label :novel_keyword, "年の差", class: "year_difference" %> <%= f.check_box :novel_keyword, {}, :non_love, nil %> <%= f.label :novel_keyword, "非恋", class: "non_love" %> <%= f.check_box :novel_keyword, {}, :villain_daughter, nil %> <%= f.label :novel_keyword, "悪役令嬢", class: "villain_daughter" %> <%= f.check_box :novel_keyword, {}, :status_difference, nil %> # 第1引数:カラム名 # 第2引数:オプション # 第3引数:チェックされたときのvalue # 第4引数:チェックされてないときのvalue とわかりやすく教えて頂きました。後は、radio_buttonと同じくlabelを付けて出来上がりです。今後の試行錯誤・・・
今回このようにチェックボックスや、ラジオボタンを作りましたが。
collectionなどを使って、モデルデータから.allで作成などしてる記事があったので
カラムのデータだけをチェックボックスとして取得。などそういった事が出来るのではないかと思われます。
検索しつつ、自分でも試行錯誤してみようと思います。現在の状態だと、多くなるほどコードが見にくいです。これが2行で収まればとても良いと思います。
またわかり次第載せたいと思います。https://teratail.com/questions/243125
今回質問した際のURLです。
参考にした記事も載せて頂きました。大変わかりやすかったです。
さらに、
システムのDBとしてpostgresqlを使っているのであれば、1カラムに対して配列をinsertすることができたと思います。
との情報も頂いたので検索して見たいと思っています。以上今回のメモでした。
- 投稿日:2020-02-24T23:04:06+09:00
【Rails】掲示板アプリでTopicとPostを紐づける方法(アソシエーション)
はじめに
現在、ポートフォリオとして掲示板アプリを作成しており、題目にある「TopicとPostを紐づける」部分でハマった(時間かかった)ので備忘録として。
ちなみに、初投稿なので暖かい目で見守ってやってください。笑早速ですが、紐づけるために必要な要素として以下の2点を中心に記載します。
- model側の修正
- controller側の修正
やりたいこと
各modelを関連付けて、「@post.topic.title」のような形で値を取得したい
環境
macOS:10.14.6
Ruby:2.5.7
Rails:5.2.4.1model側の修正(アソシエーション)
今回登場するmodelは、以下の3つ。
・Topic
・User(deviseを使ってます)
・PostTopicがスレッド、Postがスレッドに対するレスで、
Topic(1)---(多)Post
User(1)---(多)Post/Topic
というような位置付けになります。今回の場合は既に各modelを作成(generate)済みだったので、アソシエーション用のマイグレーションファイルを作って、マイグレートしていく形で進めます。
マイグレーションファイルを作成する
$ rails g migration AddUserToTopic $ rails g migration AddTopicToPostマイグレーションファイルを編集する
文法は、「add_reference table名、reference名」が基本形になります。
indexはオプションなのでお好みで。
ちなみに超ざっくりですが、indexは読み込み/取得速度を上げてくれるものです
(但し、書き込み速度は遅くなるので注意が必要)20200222110925_add_user_to_topic.rbclass AddUserToTopic < ActiveRecord::Migration[5.2] def change add_reference :topics, :user, index: true #追記箇所 end end20200223032448_add_topic_to_post.rbclass AddTopicToPost < ActiveRecord::Migration[5.2] def change add_reference :posts,:topic #追記箇所 end endマイグレートする
$ rails db:migrate上記コマンド実行後、以下のようなmigratedが出力されればOK
== 20200223032448 AddTopicToPost: migrating =================================== -- add_reference(:posts, :topic) -> 0.0796s == 20200223032448 AddTopicToPost: migrated (0.0797s) ==========================モデルを編集する
topic.rbclass Topic < ApplicationRecord validates :title, presence: true has_many :posts #追記 belongs_to :user #追記 endpost.rbclass Post < ApplicationRecord belongs_to :topic #追記 belongs_to :user #追記 enduser.rbclass User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable validates :name,:email,:encrypted_password, presence: true has_many :topics, through: :posts #追記 endこれでmodel側はOKです!
controller側の修正
各modelの関連付けできたので以下のような形で、関連先の値を拾ってこれるようになりました。細かく言うとパラメーターの中から明示的に値を取得するイメージです。
params[:topic_id]という風な感じで。topics_controller.rbclass PostsController < ApplicationController def new @topic_id = params[:topic_id] @post = Post.new end def create @post = Post.new @topic_id = params[:topic_id] #paramsからtopic_idを取得し、インスタンス変数@topic_idに代入 @post.topic_id = @topic_id #上記を@post.topic_idに代入 @post.body = params[:post][:body] @topic = Topic.find(@topic_id) @post.user_id = current_user.id if @post.save redirect_to topic_path(@topic_id), notice: '投稿しました' else render 'posts/new', alert: '投稿できませんでした' end end endちょっと汚いですね、、、汗
取得したい値は「paramsから取得してインスタンスに代入」と書く形です。
なので、取得したい値に応じて編集してください。上記はあくまで参考として。viewの修正(おまけ)
以下はトピック一覧画面(topic#index)ですが、postの数やpostの投稿時間を取得して表示することができます。
index.html.erb<div class="container mt-5 ml-5"> <div class="row"> <% @topics.each do |topic| %> <div class="table tabel-hover"> <%= link_to topic do %> <div class="list-group" style="max-width: 500px;"> <div class="list-group-item list-group-item-action"> <%= topic.title %> (<%= topic.posts.count %>) #post数を計算 <br> <small class="text-muted text-right"> 最終投稿日時:<%= topic.posts.last.created_at %> #最新のpost投稿時間を取得する </small> </div> <% end %> </div> <% end %> </div> </div> </div>こんな表示になります↓
非常に便利ですね。
参考文献
- 投稿日:2020-02-24T22:50:59+09:00
Railsアプリケーションの環境構築周りのまとめ
Railsの案件に携わって最初めちゃ苦しんだ。
まとめておいて後から振り替えれるようにしておく。1. 各パッケージ管理ソフトの概要
パッケージ管理ソフト 概要 rbenv 複数のRubyバージョンを管理するツール。バージョンを指定してrubyをインストールできる。インストール後は各バージョンごとに利用するgem置き場が提供される。Railsアプリケーションごとに使用するRubyバージョンを指定できるようになる。 RubyGems Rubyライブラリのgemのパッケージ管理ツール。現在利用しているバージョンのrubyに対してgemをインストールできる。rubyをインストールすると付属してくるツール。目的のgemをインストールする時に別のgemが必要になる(=依存関係がある)場合、それもインストールして目的のGemを使える状態にすることができる。 Bundler RubyGemsをより高機能に使うgem。RailsプロジェクトごとにGemfileというファイルで使用するgemを明示的に管理できる(PC全体を汚さず、Railsプロジェクトで完結する)。こいつ自体がRubyGemsによってインストールされるgemであるが、RubyGemsを操って各Railsアプリケーションに必要なgemをGemfile, Gemfile.lockというgem一覧ファイルに基づいてインストールできる。
RubyGemsの説明を見てるとそれで十分じゃね?と思うかもしれないが、Gemfile.lockが一番重要な機能。例えばgem「A」をインストールする場合にgem「B」が必要だったとする。そんなgem「A」をRubyGemsでインストールしたとする。このときgem「B」もインストールされる。ここまではよい。しかし時が流れてなにかの拍子にgem「B」のバージョンを上げたとする。このとき、gem「A」を利用するには実はgem「B」の特定のバージョンが必要であり、互換性がなくなってしまった場合、gem「A」は使えなくなってしまう。gem「B」のどのバージョンが必要なのかももうわからなくなってしまう。Bundlerを使ってgemをインストールして使用する場合は、Gemfile.lockに具体的にどんなgemをどんなバージョンでインストールしたのかが細かく記録されるため、この問題へ対処できるのだ。また、複数人で開発するときに対象のRailsアプリケーションが使用するgemの一覧をバージョン含めて共有する時にも役に立つ。補足
rubyenv
- 関係するディレクトリ
# rbenv周り ~/.rbenv/ versions/ X.X.X/ # Ruby(Ver X.X.X)の各種ファイルを管理するディレクトリ bin/ # 当該Rubyバージョンの標準ライブラリ、RubyGems経由でインストールしたコマンドの実行ファイル include/ lib/ # 標準ライブラリ、RubyGems経由でインストールしたライブラリ openssl/ share/ # マニュアル類 shims/ <各コマンドの実行ファイル> version # PC全体で使うruby環境のバージョン番号が書かれている # Railsプロジェクト周り <Railsプロジェクト用ディレクトリ>/ .ruby-version # このRailsプロジェクトで使うRuby環境のバージョン番号が書かれている(優先順位は version < .ruby-version)2. 関係図
言葉だけだと見返した時に意味わかんなくなりそうなので、イメージ図を貼っておく。
3. よく使うであろうコマンド
3.1. rbenv
コマンド 説明 rbenv install --list インストール可能なRubyのバージョンを表示。無印のバージョンが最も高くてdevとかついてないやつが最新の安定版みたい。 rbenv install <バージョン> バージョン指定してRubyをインストール rbenv rehash インストールしたRubyへパスを通す(新しくバージョン指定してインストールした場合に必須で必要になる。rbenv install とセット) rbenv global <バージョン> 特段の指定がない場合に本マシンで使用するRubyのバージョンを設定 rbenv local <バージョン> カレントディレクトリ配下で使用するRubyのバージョンを指定。このコマンドを実行するとカレントディレクトリに.ruby-versionというファイルができ、開くと<バージョン>が記載されている。後述のGemfileではRailsアプリケーションが使うRubyバージョンは指定できない(Bundler自体が現在使っているRubyを親とするため)ため、なかなか重要なファイルである ruby -v rbenvのコマンドではないが。カレントディレクトリにおいて使用することになるRubyのバージョンを確認する 3.2. RubyGems
基本的にgemはBundlerを使ってアプリケーションごとにインストール、管理するため、RubyGemsのコマンドを使用することは少ない。
コマンド 説明 gem install bundler 現在使用しているバージョンのRubyに足しいてBundlerをインストールする。以降、るため、基本的にこのコマンドだけで良さげ。 gem list -ra <gem名>
イントール可能なgemのバージョンを確認。には正規表現も使えるため、例えばrailsならば^rails$とすると表示がすっきりする gem update --system RubyGems自体のバージョンをあげる。 3.3. Bundler
コマンド 説明 bundle install 1. Gemfile.lockを確認してgemをインストール。
2. Gemfileを確認してGemfile.lockに存在しないgemをインストールし、Gemfile.lockに追記。
bundle update <特定のgem名> Gemfile.lockを無視してGemfileに書いてある条件に基づいて特定のgemをインストール。一部のgemをアップデートしたいときに影響範囲を小さく抑えるために使用する。<特定のgem名>を省略してしまうと、Gemfile.lockの内容をすべて無視して、イチからGemfileに基づいてgemをインストールし直してしまうため、これまで動いていたRailsアプリケーションが動かなくなった、ということが起きうる。基本的に使っちゃダメなコマンド。 bundle exec <各種コマンド> Gemfile.lockに書いてあるバージョンのgemを使用して<各種コマンド>を実行。bundle execがないと意図せぬバージョンのgemが使われたりして大変なことになる。railsアプリケーションを操作するときには絶対にbundle execをつけるべき。
- 投稿日:2020-02-24T22:28:05+09:00
Active Storageを導入する前に知っておきたかったこと(ACLディレクトリ設定)
概要
ファイルアップロード機能を実装する際に、Rails5.2で導入されたActive Storageを使ってみました。
実際に使ってみて困ったことがいくつかあったので、誰かのために役立てばと思いまとめておきます。環境
- Rails 6.0.2.1
- Ruby 2.6.5
結論: 困った点と解決方法
困った点
Active Storage のサービスとして、Amazon S3を利用して、以下の点で困りました。
- アップロード時にアクセス権限(S3のACL)を
public-read
に設定できない- ファイルを保存するディレクトリが設定できない
(正確には、S3にはフォルダという概念は存在しないので、ファイルのキー名につけるprefixがつけられない)解決方法
以下のパッチで対応しました。
この書き方だと、ファイルごとにアクセス権限を変更したり、ディレクトリを変更したりといった細かい設定はできません。# lib/active_storage/service/better_s3_service.rb require 'aws-sdk-s3' require 'active_storage/service/s3_service' require 'active_support/core_ext/numeric/bytes' module ActiveStorage class Service::BetterS3Service < Service::S3Service attr_reader :root def initialize(bucket:, upload: {}, root:, **options) @root = root super(bucket: bucket, upload: upload, **options) end def upload(key, io, checksum: nil, content_type: nil, **) instrument :upload, key: key, checksum: checksum do object_for(key).put(upload_options.merge(body: io, content_md5: checksum, content_type: content_type, acl: 'public-read')) rescue Aws::S3::Errors::BadDigest raise ActiveStorage::IntegrityError end end private def object_for(key) path = root.present? ? File.join(root, key) : key bucket.object(path) end end end以下のように
root
を設定する。# config/storage.yml amazon: service: BetterS3 root: root-directory1. アップロード時にアクセス権限(S3のACL)
アップロードしたファイルにパブリック読み取りアクセス許可をつけようとしましたが、
v6.0.2.1
ではアップロード時に権限を設定することはできません。ただ2019年7月のPR1で、
public
というオプションをstorage.yml
で設定できる変更がマージされたので、将来的にはサポートされそうです。
いくつかの記事2やissueへのコメント3を参考にしてパッチをあてる形で対応しました。2. ファイルを保存するディレクトリが設定できない
S3にアップロードするファイルにprefixをつけて、フォルダを作成したいことは多々あると思いますが、現時点(v6.0.2.1)のActive Storageではサポートされていません。
「Active Storageでフォルダーを使う」といった旨のissue4 で議論されていますが、あまり議論が進んでいないので、まだまだサポートされなそうですね…。こちらも先述のissue4にあったパッチ5を利用して、
config/storage.yml
から特定のディレクトリ名を設定できるようにしました。まとめ
Active Storageを使ってみましたが、意外とサポートされていない機能が多く、少し驚きました。
Delyさんの記事にもありましたが、Rails本体に入っていても過信せず、使う前にユースケースを満たしているか利用すべきだと勉強になりました。読んでいただきありがとうございました!
Permanent URLs for Active Storage blobs by peterzhu2118 · Pull Request #36729 · rails/rails · GitHub ↩
ActiveStorage: Allow access to backing file from Service API · Issue #31419 · rails/rails · GitHub ↩
Folder with active storage · Issue #32790 · rails/rails · GitHub ↩
(Folder with active storage · Issue #32790 · rails/rails · GitHub) ↩
- 投稿日:2020-02-24T22:20:17+09:00
ERROR: While executing gem ... (Errno::EACCES)が出た時の解決法
実現したいこと
railsでWEBアプリケーションを作るための環境構築。
エラー内容
Rubyの拡張機能(gem)を管理するためのbundlerをインストールした時にでたエラー
ERROR: While executing gem ... (Errno::EACCES)
bundlerとは
gem一種
railsでアプリケーションを開発する際には複数のgemを使用します。gem同士の互換性を保ちながらバージョン等を管理してくれる仕組みのこと。複数人、複数環境で開発を行う際に各環境で扱うパッケージの種類やバージョンを合わせてくれて非常に便利である。解決方法
参考記事
今回このエラーの解決までに参考にした記事です。
https://qiita.com/nachiguro1003/items/4b564b92eca3ba35744a修正内容
上記参考記事にも記載されていますが、今回のエラー内容は、gemをインストールする時に不必要
sudo
をつけて実行してしまったため、ファイルへ書き込みする権限を失ってしまったためです。
ですので解決策としてはこの権限を修正します。
ターミナルで以下の通り実行します。
sudo chown -R (ユーザ名):staff /Users/(ユーザ名)/.rbenv
これで権限が戻りますので、再度'gem install bundler'することで無事解決できました。
- 投稿日:2020-02-24T21:15:48+09:00
Ruby on Rails 学習メモ.1
Ruby on Rails学習メモ.1
以下、初学者の独学によるメモ(チラシの裏)。
Progateでの学習もある程度進んできたため、アウトプットをすることにした。
学習中のため、誤った解釈もあるかもしれない。Railsでのサイト作成は、
view(ブラウザ)→
ルーティング(アクションを呼び出す)→
コントローラー(URLに対応したHTMLを送信)
(→view…)
の編集の連続である。これらの基本をよく理解すること。
また、何をやろうとしているのか(目的を)理解しないまま、コードを覚える事を深追いしながら無理矢理学習を進めようとすると単なる写経になってしまうので、まず目的を理解する事に努めること(理解できない場合は何度も読む)。(先の学習内容まで進めた後に復習すると理解できる場合もあるので、まず進める方が良い場合もある。)1.新規投稿
HTML(view)の設定
<div class="form-body"> <%= form_tag("/posts/create") do %> <textarea name="content"></textarea> <input type="submit" value="投稿"> <% end %> </div>
<%= form_tag("/posts/create") do %>
のform_tagが設定されていることにより、
<input type="submit" value="投稿">
、つまり投稿ボタンを押すと、submitされたデータを「/posts/create」のURLに送信するようになっている。
<textarea name="content"></textarea>
入力したデータにname属性を指定している。
これにより、コントローラーのアクション内(変数:params)で入力したデータを受け取れるようになる。ルーティングの設定
get "posts/create" => "posts#create"URL「/posts/create」から情報を受け取り、
「posts」コントローラーの「create」アクションを呼び出す。コントローラーの設定
def create @post = Post.new(content: params[:content]) @post.save redirect_to("/posts/index") endルーティングからcreateアクションが呼び出され、以下の処理が実行される。
@post = Post.new(content: params[:content])
@post.save
変数@postに投稿された内容を代入(受け取るために変数paramsを使用している)し、データベースに保存する。
redirect_to("/posts/index")
URL:/posts/indexに転送(ページ移行)する。※
@user = User.new(name: params[:name], email: params[:email])
のように、配列として複数のデータを受け取ることもできる。2.投稿詳細画面の表示
HTML
<% @posts.each do |post| %> <div class="posts-index-item"> <div class="post-right"> <%= link_to(post.name, "/posts/#{post.id}") %> </div> </div> <% end %>idを取得・送信するように設定。
ルーティング
get "posts/index" => "posts#index" get "posts/:id" => "posts#show"showアクションのルーティングはindexアクションより下に書かないといけないことに注意する。
コントローラー
def show @posts = Post.find_by(id: params[:id]) end3.投稿成功・失敗の表示
クラス定義:投稿の制限(Validate:検証の意)
class Post < ApplicationRecord validates :content, {presence: true} validates :content, {length: {maximum: 140}} endValidateはクラス内(models/post/rb)で定義するので、postクラス配下すべてで適用される。
上記は空の投稿と140字以上の投稿にfalseを返すようになっている。コントローラー(アクション)
def create @post = Post.new(content: params[:content]) if @post.save redirect_to("/posts/index") flash[:notice] = "投稿を作成しました" else render("posts/new") endif @post.saveがtrueの場合、「/posts/index」に飛び、
「flash[:notice] = "投稿を作成しました"」を実行する。falseの場合、「posts/new」に飛ぶ
HTML
flashはいろいろな箇所で共通で使っていくのでapplication.html.erbに設定する。
投稿成功の場合:<% if flash[:notice] %> <div class="flash"> <%= flash[:notice] %> </div> <% end %>投稿失敗の場合
投稿失敗の場合posts/newに飛ぶので、application.htmlではなくnew.htmlを編集する。(2行目から6行目までが該当。)<%= form_tag("/posts/create") do %> <% @post.errors.full_messages.each do |message| %> <div class="form-error"> <%= message %> </div> <% end %> <textarea name="content"><%= @post.content %></textarea> <input type="submit" value="投稿"> <% end %>saveメソッドを呼び出した際にバリデーションに失敗すると、Railsでは自動的に@post.errors.full_messagesの中にエラーメッセージが配列で入るようになっている。
each文を用いることで、配列の中のメッセージ全てを表示させる。
また、<textarea>
内に<%= @post.content %>
を設定しているため、入力した(投稿に失敗した)文章が出力される。
(newアクションではこの時点では変数postが定義されていないため、@post = Post.newを定義する必要があることに注意。←newアクション作成時に作っておく?)4.投稿一覧ページの作成
先にターミナルで「rails g model Post content:text」(Post:モデル名、content:カラム名、text:データ型)を実行し、モデルとマイグレーションファイル(データベース)を作成しておく。
コントローラー(アクション)
def index @posts = Post.all endHTML
<% @posts.each do |post| %> <div class="posts-index-item"> <%= post.content %> </div> <% end %>each文で変数@posts内の内容を繰り返し(全て)表示させる。
5.投稿の編集
HTML(edit.htmlを作成する必要あり)
<div class="main posts-new"> <div class="container"> <h1 class="form-heading">編集する</h1> <%= form_tag("/posts/#{@post.id}/update") do %> <div class="form"> <div class="form-body"> <% @post.errors.full_messages.each do |message| %> <div class="form-error"> <%= message %> </div> <% end %> <textarea name="content"><%= @post.content %></textarea> <input type="submit" value="保存"> </div> <% end %> </div> </div>4行目:idを取得し「/posts/id/update」のURLを送信する。
7行目:アクション(コントローラー)内のifでエラーが出てrenderメソッドを介してページに戻ってきた場合、エラーメッセージを表示させるようになっている。ルーティング
post "posts/:id/update" => "posts#update"コントローラー(アクション)
def update @post = Post.find_by(id: params[:id]) @post.content = params[:content] if @post.save flash[:notice] = "投稿を編集しました" redirect_to("/posts/index") else render("posts/edit") end end
@post = Post.find_by(id: params[:id])
:送信されてきたURLとidを参照し、変数@postに代入する。
@post.content = params[:content]
:送信されてきた内容をparamsで受け取り、変数@postのcontentに代入する。
if @post.save
が成立したら「投稿を編集しました」のメッセージとともに、「/posts/index"」に戻る。
成立しない(エラーの)場合、renderで「posts/edit」に戻る。
renderで戻らないと「/posts/index」を介し投稿内容の変数が更新されてしまう(編集内容が最初の投稿に戻り、編集したかった投稿がフォームに維持されない。)6.投稿の削除
HTML(show.html)
<div class="post-menus"> <%= link_to("編集", "/posts/#{@post.id}/edit") %> <%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %> </div>(投稿詳細画面のshow.htmlで完結するので、新しくhtml(view)を追加する必要はない。)
link_toメソッドの第三引数に{method:"post"}を設定しないと、次のルーティングでpostではなくgetを探してしまい、エラーとなってしまう。ルーティング
post "posts/:id/destroy" => "posts#destroy"コントローラー(アクション)
def destroy @post = Post.find_by(id: params[:id]) @post.destroy flash[:notice] = "投稿を削除しました" redirect_to("/posts/index") end編集の際と同様、HTMLより送信されたidを変数に代入し、destroyアクションで削除する。
(実際のポートフォリオでは「削除しますか?」の質問を出せるようにする?)
- 投稿日:2020-02-24T20:54:30+09:00
Rails+AxiosでCSRF対策用のトークンを使う設定
Rails+WebpackerのJavaScriptでAxiosを使うときは、POSTやPATCHで送信する際にCSRF対策用のトークンを指定する必要があります。送信のたびに指定するのは面倒なので、あらかじめ設定しておきましょう。
AxiosのInterceptorsの機能を使います。送信前にHTTPメソッドがPOST, PUT, PATCH, DELETEだったら、meta要素からトークンを取り出してHTTPヘッダにセットします。ここではjQueryを使っています。
サンプル: https://github.com/kazubon/blog-rails6-vuejs
app/javascript/axios_config.jsimport Axios from 'axios'; Axios.interceptors.request.use((config) => { if(['post', 'put', 'patch', 'delete'].includes(config.method)) { config.headers['X-CSRF-Token'] = $('meta[name="csrf-token"]').attr('content'); } return config; }, (error) => { return Promise.reject(error); });このJavaScritptをどこかで動かします。とりあえずapplication.jsに入れとけばいいでしょう。
app/javascript/packs/application.jsimport '../axios_config';あとは、ふつうにAxiosが使えます。
import Axios from 'axios'; Axios.post('/entries.json', { entry: this.entry });
- 投稿日:2020-02-24T20:47:47+09:00
Windows10にRuby on Rails環境をつくってみたらコケた
Rials環境をWindows10でも作ろう
新しくWindows10を手に入れたので、こっちでも環境を作ろうと動き出しましたが、コケまくりました。
コケまくったので、解決法を記録として残そうと思います。Rubyのインストール
公式サイトで以下をダウンロードします。
https://rubyinstaller.org/downloads/
私の環境では「rubyinstaller-devkit-2.6.5-1-x64」をダウンロードしました。ダウンロード後、exeファイルを実行し、各内容はデフォルトで行いました。
参考サイト: Windows10環境にRubyとRailsをインストールしてみた
途中Toolkitのインストールがあったので、チェックを付けてインストール。コマンドプロンプトかPower Shellを起動して、[ruby -v]でバージョンを確認します。
>ruby -v ruby 2.6.5p114 (2019-10-01 revision 67812) [x64-mingw32]Railsをインストール
先程立ち上げたコマンドプロンプトかPower Shwlleに[gem install rails]を入力してEnter
>gem install railsそのままインストールが始まって勝手に終わります。
時間がかかるのでちょっと放置。。。Railsをインストールしたら、バージョンを確認します。
>rails -v Rails 6.0.2.1Bundlerのインストール
[gem install bundler]を入力してインストールします。
>gem install bundlerインストールが終わったらお決まりのバージョンの確認
>bundler -v Bundler version 2.1.4Sqlite3もインストール
だいたいの説明がここが抜けてたりして、[Rails new]してSqlite3でコケる。。。
ので、これも忘れず行います。>gem install sqlite3 --platform ruby大丈夫だとは思うのですが、Path通してやるのが良いかもです。
色々としすぎて途中でpathを追加したので、そのままインストールして出来るのかわかりません。pathの通し方
↓サイトがわかりやすいです。
参考サイト:Windows10で実行ファイルへのパスを通す手順>sqlite3 --version 3.31.1 2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6で、終わりかと思ったら。。。
これでrails newしたらnode.jsでコケたりします・・・・なので、node.js入れます。
Node.jsをインストールする
Node.jsインストールページ
私は『推奨版』のインストーラーでインストールしました。
node.jsのバージョンと同梱のnpmのバージョンを確認します。>node -v v12.16.1 >npm -v 6.13.4もしバージョン確認ができなかった場合は、上で書いたpathを追加します。
自動で出来たような気もしますが、色々とやりすぎて記憶が曖昧なので一応追記しておきます。追加するpathは
C:\Program Files\nodejs\
バックスラッシュになっていますが、Windowsなので「¥」です。
後ろの¥を忘れずに。。。で、Yarnのインストール
先ほど入れた同梱のnpmでインストールします。>npm install -g yarnそして確認のための
>yarn -v 1.22.0これで大丈夫!!!
Railsアプリケーションを作る
アプリケーションの作り方は Railsチュートリアル を参考にします。
チュートリアルの最初のアプリケーション通りにしてみます。
rails newはバージョンをしていせずにしました。
>rails new hello_appめっちゃ時間かかります。。。。
>cd hello_appでディレクトリを移動してから
>bundle installしたら
>rails serverお疲れさまでした!!!
昨日(2020/02/23)にやっと解決したのですが、それまで色々やりすぎて
何回も書きすぎうろ覚えもあります。
やらなくて良いこともあると良いのですが、エラー出まくったのを一つ一つ解決していったところ、この様になった次第です。
参考になると嬉しいです♪
- 投稿日:2020-02-24T19:59:00+09:00
deviseのユーザー登録失敗後にビューがずれる。
登録画面ビュー
通常の登録画面でapp/view/devise/registrations/new.html.hamlにCSSを当てたもの
これにフォームに空などの無効な値を入れると以下のようになる。
登録失敗後のビュー
//登録失敗時のnickname部分のHTML <span class="nickname"> <div class="field_with_errors"><label for="user_nickname">ニックネーム</label></div> <div class="field_with_errors"><input type="text" value="" name="user[nickname]" id="user_nickname"></div> </span>"field_with_errors"クラスが自動生成されてしまっていることが原因
registrations.scss.field_with_errors { display: contents; }上記のCSSを追記して解決
- 投稿日:2020-02-24T19:34:42+09:00
Ruby on rails でTodoアプリを作る
今回はRuby on railsを使ってTodoアプリを作っていきます!!!
完成品が↑
railsの学習のために作ります!
1.プロジェクトを作ろう!
コンソールを起動して、
$ rails new #app名これでプロジェクトを作ります!
次にcdでプロジェクトに移動しましょう一旦作成したファイルの方にいって
gemfile
というものがあると思うのでそれを編集します!
ここをいじってBootstrap等を導入するワケですね!# gem 'bcrypt', '~> 3.1.7' gem 'bootstrap', '~> 4.1.1' #この1行だけ追加 # Use ActiveStorage variantこのように記載すればOKです!
ではコンソールに戻りましょう
※ここまででsqliteについてエラーが発生した人がいる場合
ridk exec pacman -S mingw-w64-x86_64-sqlite3
こちらのコマンドを一度うってくださいそして全て完了したらコンソールにて
bundle installこちらのコマンドをうちます
( bundlerというgemを使って、Gemfileに従ってgemをインストールするためのコマンドです!)ここまで完了したら
rails sでサーバーを起動してみましょう!
こういうのが出たら成功です!
成功を確認できたら、ブラウザを開いて
localhost:3000
を入力してください!
このような画面が出てきたら無事、railsアプリの作成準備が整いました!!
(サーバーを終了させたい場合はCtrl+cでyを入力して終了できます)2.データベースを構築しよう!
RailsはModelを使ってデータベースを操作します
id、created_at、updated_atの3つのカラムがデフォルトで作成されます。
今回はstring型のcontentというカラムを追加したいと思います。
Model名は頭文字が大文字で、単数形でなくてはなりません。
ではコンソールに戻って$ rails g model Task content:string $ rails db:migrateを実行してください!
これで(migurate)データベースにテーブルが作成されます。
このようにTaskというテーブルを作成すると
tasksというように複数形のテーブルができます以上でデータベースの構築は終わりました!
3.Controllerを使ってみよう!
controllerはMVCを構成するコンポーネントの1つです。
MVCとは
Model:データベースを取り扱う
View:画面表示を取り扱う
Controller:ModelとViewと連携する
といったようなものです。では今回はタスクの一覧を表示するアクションcontrollerを作っていきましょう!
$ rails generate controller Tasks indexこれでタスク一覧を表示するトップページのtasks_controllerを作ります!
作成されたControllerに、登録されている全てのタスクを取得する処理を記述します。/app/controllers/tasks_controller.rbdef index @tasks = Task.all endTask.allでtasksテーブルの全てのレコードを取得します!
4.ルーティングを設定しよう!
URLに対するリクエストを受けた時にcontrollerのどのアクションを実行するか、を設定します。
resources :{Controller名}
で複数のルーティングが一気に設定できるようになります!
これでlocalhostに入った際にindexアクションが動くようになっています/config/routes.rbRails.application.routes.draw do root 'tasks#index' resources :tasks end設定されているルーティングは
rails routes
で確認しよう!5.Viewを作ろう!
Controller内のアクション(タスク一覧表示する)が実行されると、対応するViewファイルが呼び出されます!
今回の場合は対応するViewファイルはindex.html.erbです!/app/views/tasks/index.html.erb<div class="mx-auto" style="width: 200px;"> <h1>Task list</h1> </div> <h2><%= link_to 'Creat new Todo', new_task_path ,class: 'btn btn-info'%></h2> <table class="table"> <thead> <tr> <th>タスク</th> <th>編集</th> <th>削除</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> </tr> <% end %> </tbody> </table>Bootstrapを使ってテーブルとかを綺麗に表示するようにしてるよ
<% @tasks.each do |task| %>
にて格納されているタスクを表示するようにしています!https://hackerthemes.com/bootstrap-cheatsheet/#input-group-append
↑もっとBootstrap使いたい方向けにチートシート紹介しときます↑6.タスクを追加するための準備!
タスク追加画面を表示するためのnewアクションを作ります!
/app/controllers/tasks_controller.rbdef new @task = Task.new endこれを追記します!
リクエストがあった時にフォームを表示するために@task = Task.newでTaskのオブジェクトを作成しています!次に、タスク追加画面のviewファイルを作成します。
/app/views/tasks/new.html.erb<%= form_for(@task) do |f| %> <div><%= f.text_field :title %></div> <div><input type="submit" value="追加" class="btn btn-success"></div> <% end %> <%= link_to '戻る', tasks_path %今回はform_forを使っていますがこの説明は長くなるので下記のリンクを参考にしてください!
form_forを使って「フォーム作成→データをテーブルに保存」を実装しています。
https://qiita.com/jumpyoshim/items/ee5af466ef79595671747.タスク追加処理を作っていこう!
/tasksにPOSTリクエストがあった時、タスクの追加処理を行うaddアクションを作成します。
/app/controllers/tasks_controller.rbdef add @task = Task.add(task_params) redirect_to tasks_path end private def params params.require(:task).permit(:title) endPOSTで送信された物をデータベースに登録し、その後
redirect_to tasks_path
を使ってタスク一覧画面に遷移するようにしています!またpraivateの部分ですが、Taskモデルのtitleを渡された場合のみ追加処理が実行されるようになっています。
以上で追加処理の部分は完成です!
8.タスクを編集する機能を作ろう!
/tasks/{id}/editにGETリクエストがあった時、タスク編集を表示するeditアクションと
編集した後のデータベースを更新するアクションを一緒に作っときましょう!/app/controllers/tasks_controllers.rbdef edit @task = Task.find(params[:id]) end def update @task = Task.find(params[:id]) @task.update(task_params) redirect_to tasks_url end-edit-
リクエスト部分の数値をparams[:id]で取り出しています。-update-
タスク編集画面から送信された内容を受け取り、データベースを更新します!
find
で主キーに対応するレコードを取り出します。続いて、タスク編集画面のviewファイルを作成します。
/app/views/tasks/edit.html.erb<h1>タスク編集</h1> <%= form_for(@task) do |f| %> <div><%= f.label :title %></div> <div><%= f.text_field :title %></div> <div><input type="submit" value="編集" class="btn btn-success"></div> <% end %> <%= link_to '戻る', tasks_path %>これで編集機能は終了です!
9.タスクの削除機能を作ろう!
/tasks/{id}にDELETEリクエストがあった時
idに対応するレコードをデータベースから削除するdestroyアクションを追加します。/app/controllers/tasks_controller.rbdef destroy @task = Task.find(params[:id]) @task.destroy redirect_to tasks_url endではこれまで編集機能、削除機能を作ってきたのでそれをタスク一覧画面に追加しよう!
/app/views/tasks/index.html.erb<tr> <td><%= task.title %></td> <td><%= link_to '編集', edit_task_path(task) ,class: 'btn btn-success' %></td> <td><%= link_to '削除', task_path(task), method: :delete, class: 'btn btn-danger' %></td> </tr>classはBootstrapを使っていい感じのボタンにするため設置
destroyアクションを実行するには、DELETEメソッドのリクエストを送らないとダメなので引数にmethod: deleteを指定しています!
以上で投稿、編集、削除の機能は完成です!!!
10.空の投稿や文字数制限の機能をつけよう!
空の投稿やあまりに多い文字数は色々邪魔だと思うのでこちらを規制しましょう!!
/app/models/task.rbvalidates :title, presence: true, length: { maximum: 50 }上記のように何か入力内容に規制をしたいとなった場合
validates
を使って titleに入力される内容に規制をかけます
presence
で空白禁止にして、length:{maximum:30}
で30文字までしか入力できないようにしました!/app/views/tasks/new.html.erb<h1>Task add</h1> <% if @task.errors.any? %> <div class="alert alert-warning"> <ul> <% @task.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %>を追加して、空白や文字数超えた時にはエラーを表示するように追記しましょう!
これの詳しい説明は
https://qiita.com/ryuuuuuuuuuu/items/1a1e53d062bff774d88a
を参考に!11.最後に
今回todoアプリを作って、railsでアプリを作る流れは掴めたかと思います。
けど実際にもっと複雑なWebアプリを作るってなるとまだまだ途方にくれそうなのでまずはこういう物を作ったりしてみて
もっと基礎等が掴めてきたら応用に活かせたらいいなと思いました!
https://github.com/t4k3p0n/todo-rails
↑githubです
- 投稿日:2020-02-24T19:14:18+09:00
【rails】deviseとdate_select使って歳の数だけウ●コ表示させる
「歳の数だけホニャララ」というのは何か理由をつけたい時によく使われる手法かと思います。
誕生日に歳の数だけ薔薇をプレゼントなんてのは、100本の薔薇だと予算オーバーとなるのでちょうどいい理由となりますよね。さて、今回は年齢の数だけウ●コ表示させてみようかなと思い、実装できたので紹介します。
まずは完成した状態を見てみましょう。
では、どのように作ったのか書いていきます。
[1]deviseを導入してdate_selectで誕生日を入力できるようにする
まずはdeviseをインストールし、誕生日をdata形式で入力できるよう実装します。
gem 'devise'
をgemファイルに記載し、$ bundle install
します。
↓
$ rails g devise:install
でdeviseをアプリにインストールします。
↓
$ rails g devise User
でmodelを作成しましょう。この際に誕生日を入力するためのカラムを作成します。# 2020XXXXXXXXXXX_devise_create_users.rb # frozen_string_literal: true class DeviseCreateUsers < ActiveRecord::Migration[5.2] def change create_table :users do |t| ## Database authenticatable t.string :nickname, null: false, default: "" t.date :birth_date, null: false # ←こんな感じで追加します。 t.string :email, null: false, default: "" t.string :encrypted_password, null: false, default: "" ~~ 省略 ~~ end上記のようにマイグレーションファイルにdate型のカラムを追加して、
$ rake db:migrate
します。
これで、値を入れるカラムができました。次に、入力エリアを増やしてnicknameとbirth_dateを入力できるようにします。
$ rails g devise:views
のコマンドでviewファイルを生成します。今回はhamlで書いていくので、gemfileに
gem 'haml-rails'
を記載し、$ bundle install
します。
そのあと、$ rails haml:erb2haml
でerb→hamlに変換します。hamlに変換した
/app/views/devise/registrations/new.html.haml
を下記のように編集します。%h2 Sign up = form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| = render "devise/shared/error_messages", resource: resource -# ~~~~ここから追加~~~~ .field = f.label :nickname %br/ = f.text_field :nickname, autofocus: true, autocomplete: "nickname" .field = f.label :birth_date %br/ = f.date_select :birth_date, use_month_numbers: true,start_year: 1930, end_year: (Time.now.year - 10), default: Date.new(1989, 1, 1) -# ~~~~ここまで追加~~~~ .field = f.label :email %br/ = f.email_field :email, autofocus: true, autocomplete: "email" -# ~~~~ここから下は省略~~~~上記のように追記することで、入力フォームは作成できました。
次に、カラムに保存できるように許可する記述を/app/controllers/application_controller.rb
に記載します。application_controller.rbbefore_action :configure_permitted_parameters, if: :devise_controller? def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :birth_date]) end上記のように記載すると、
nickname
とbirth_date
をカラムに入れることを許可することができました。
これで、まずは誕生日を入力して保存できるところまでできました。[2]誕生日から年齢が表示できるようにする
まずは
$ rails g controller unkos index
でunkos_controller.rb
と/views/unkos/index.html.haml
を生成します。date形式で保存された年月日から年齢を算出するための便利なgemを入れます。
gemfileにgem 'happybirthday'
を記載して$ bundle install
します。それでは
/app/controllers/unkos_controller.rb
を下記のように追記します。unkos_controller.rbclass UnkosController < ApplicationController before_action :authenticate_user! require 'happybirthday' def index birthday = Happybirthday.born_on(current_user.birth_date) @birthday = birthday.age.years_old end end
before_action :authenticate_user!
は、ログインしてなければ、ログイン画面へリダイレクトさせるメソッドです。deviseを入れると使用できるメソッドです。
require 'happybirthday'
は先ほど導入したgem 'happybirthday'
をunkos_controller.rb
で使用するための記述です。
Happybirthday.born_on(current_user.birth_date)
では、現在ログイン中のユーザの誕生日を取得します。
@birthday = birthday.age.years_old
にて、現在の年齢に置き換え@birthday
に代入しています。では、
/app/views/unkos/index.html.haml
を下記のようなコードを追記してください。index.html.haml%h2 = current_user.nickname + "さん" %string = "現在#{@birthday}歳です。"どうですか、これで年齢が表示できたでしょうか。
[3]年齢の数だけウ●コを表示させる
では、画竜点睛になりますね。ウ●コを表示させるくだりです。
/app/views/unkos/index.html.haml
に下記のような記述を追記してください。%h2 = current_user.nickname + "さん" %string = "現在#{@birthday}歳です。" %p それでは、歳の数だけウンコを表示します。 .unko_box{style: 'width: 550px; margin:0 auto'} - count = 0 - loop do - count += 1 = image_tag 'unchi.png', alt: 'unko', width: '50px', class: '' - if count == @birthday - break
loop do
で繰り返しウ●コの画像を表示させるようにしまして、
if count == @birthday
の箇所で、年齢の数でループ処理を止めています。
これで、ウ●コが年齢分繰り返しされるわけですね。応用編
ウ●コを年齢分表示させるって、一体どんなことに使うんだ?
そう思われる方もいらっしゃるかと思われますが、例えばこんな時に応用して使用できるかと思います。[応用1]歳の数だけ豆を表示する
節分の時期にどうでしょうか?
[応用2]バースデーケーキーに歳の数だけロウソクを立てる
一番実用的じゃないでしょうか?
おわりに
いかがでしたでしょうか。
年齢の数だけ●●というのは、こじづけしがちな理由なので、
ぜひプログラミングでも実装してみてくださいね!参考記事
- 投稿日:2020-02-24T19:08:32+09:00
【Tips】Rails の Minitest 実行時に想定外のデータベース名になって ConnectionError となる原因と対処法
問題
rails test
実行時にデータベース名末尾に-0
-1
などが付きアクセスが拒否されてしまう。入力
rails test
出力
ERROR["test_【テストの名前】", #<Minitest::Reporters::Suite:0x******** @name="【テストクラスの名前】">, 0.143750600022031] test_n【テストの名前】#【テストクラスの名前】 (0.14s) Minitest::UnexpectedError: Mysql2::Error::ConnectionError: Access denied for user '********'@'%' to database '【テスト用データベースに設定した名前】-0' ERROR["test_【テストの名前】", #<Minitest::Reporters::Suite:0x******** @name="【テストクラスの名前】">, 0.143750600022031] test_n【テストの名前】#【テストクラスの名前】 (0.21s) Minitest::UnexpectedError: Mysql2::Error::ConnectionError: Access denied for user '********'@'%' to database '【テスト用データベースに設定した名前】-1' ERROR["test_【テストの名前】", #<Minitest::Reporters::Suite:0x******** @name="【テストクラスの名前】">, 0.143750600022031] test_n【テストの名前】#【テストクラスの名前】 (0.31s) Minitest::UnexpectedError: Mysql2::Error::ConnectionError: Access denied for user '********'@'%' to database '【テスト用データベースに設定した名前】-2' ...環境
- Windows 10
- Ubuntu 18.04 LTS
- anyenv 1.1.1
- rbenv 1.1.2-20-g143b2c9
- ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
- Rails 6.0.2.1
- MySQL
原因
test/test_helper.rb
でマルチスレッド実行設定が行われているため複数のデータベースにアクセスされてしまう。解決方法
マルチスレッド設定をコメントアウトする。
test/test_helper.rbclass ActiveSupport::TestCase # Run tests in parallel with specified workers # parallelize(workers: :number_of_processors) # ↑をコメントアウト # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. fixtures :all # Add more helper methods to be used by all tests here... end補足
おそらく
-0
-1
などとついたデータベースを作成することでも解決可能。
- 投稿日:2020-02-24T18:49:38+09:00
bootstrap_form を使って devise の form_for を form_with に置き換える
「Rails中級チュートリアル」に取り組んでいて実践したことのメモです?
本文中では、
form_for
が使われていますが、Rails5.1 からform_with
の使用が推奨されているので、変更に挑戦!参考 : Railsガイド「form_forとform_tagのform_withへの統合」
bootstrap_form gem をインストール
Gemfilegem 'bootstrap_form'bootstrap_form の GitHub の README を見ると
form_with
での使用方法 が書かれているので、それを参考にします。(コピペすると全角記号で死ぬので注意です)
devise のフォームを bootstrap_form & form_with バージョンに変更
参考 : 【Rails】deviseのビューのform_forをform_withに置き換える
app/views/devise/sessions/new.html.erb<%= bootstrap_form_with(model: @user, url: session_path(resource_name), local: true) do |f| %> <%= f.email_field :email, autofocus: true, placeholder: 'メールアドレスを入力してください' %> <%= f.password_field :password, autocomplete: "off", placeholder: 'パスワードを入力してください' %> <% if devise_mapping.rememberable? %> <%= f.check_box :remember_me %> <% end %> <%= f.submit "ログイン" %> <% end %>?こんな感じのフォームが簡単に作成できます ✅
生成される HTML の Eメール入力欄をみてみると、
<input autofocus="autofocus" placeholder="メールアドレスを入力してください" class="form-control" type="email" value="" name="user[email]" id="user_email">となっており、クラスで
form-control
を追加しなくても勝手に付いてくれるようですね!ログインボタンにはこのようなクラスが付与されています。
<input type="submit" name="commit" value="ログイン" class="btn btn-secondary" data-disable-with="ログイン">ログインボタンのクラスを変更してみました。
<%= f.submit "ログイン", class: 'form-control btn btn-info' %>
- 投稿日:2020-02-24T16:56:24+09:00
devise token authの出力をserializerで整形する
はじめに
この記事ではdevise token authでのjsonの出力を
active_model_serializer
gemを使って整形する手順を解説するわ。実際の開発中に少し詰まったことを元にしているからゴールとして"ユーザーのログイン成功時に返されるjsonをserializerで整形する"を設定するわ。他のアクション後に返されるjsonにも応用できるように心掛けるから安心しなさい。
devise関連の導入まで含めちゃうと長くなるからそこは割愛するわ、ごめんなさいね。準備するわよの巻
まずはgemのインストールから始めるわ。
Gemfile.gem 'active_model_serializers'bundle installこれでactive_model_serializersのインストールが完了したわ。
このgem自体の説明は他の記事に譲るとしてまずは設定をするわ。
設定用のconfig/initializers/ams.rb
ファイルを手動で追加しなさい。config/initializers/ams.rbActiveModel::Serializer.config.adapter = :json_apiこの部分では出力するjsonのフォーマットを指定しているわ。オプションの詳しい説明についてはこちらの記事に詳しいわ。
Railsのactive_model_serializerについて学ぶ100DaysOfCodeチャレンジ10日目(Day10:#100DaysOfCode)
ここでは
json_api
を指定したけど、あなたの好きなように設定しなさい。さて、次はいよいよserializerのファイルを作っていくわよ。
rails generate serializer User最後の
User
の部分は整形したいモデル名を指定することね。このコマンドでapp/serializers/user_serializer.rb
ファイルが作成されたわ、早速いじいじしちゃいましょう。app/serializers/user_serializer.rbclass UserSerializer < ActiveModel::Serializer attributes :id, :name, :nickname, :image, :confirmed_at, :updated_at endここではjsonで返すモデルのカラムを指定しているわ。他にも色々設定できるけど適宜自分で調べなさい、頑張ることね。
本題に入るわよの巻
ここまでで準備は完了よ、configに追加した設定を読み込ませるためにこのあたりで一旦サーバを再起動しておくことね、ん?もうやった? 良い子ね、クマちゃんのビスケットをあげるわ。
さて、まず見て欲しいものがあるの、serializerで整形をしない場合のログイン成功時に返されるjson(ログインに成功したユーザーの情報)よ。
続いて同じjsonをserializerで整形した場合よ。
データが構造化されているのと設定したカラムのみが出力されていることが分かるわね。
ちなみに下はapp/controllers/api/v1/user_controller.rbclass Api::V1::UsersController < ApplicationController def show @user = User.find(params[:id]) render json: @user, serializer: UserSerializer end endこんな感じのコードよ。
見ての通り、deviseの方のjsonも整形しないとアプリケーション全体として返すjsonのフォーマットに統一性が取れないことが分かるわ。これはフロント側としても混乱するしメンテナンス性も大きく損なうわ。
でも、自分で一から書くアクションなら上のコードみたいに簡単に実装できるんだけどdeviseは内部で勝手にやってくれるから分かりづらいわよね。
そこで今回は
1. コントローラを継承する
2. そこで各アクションごとのレンダリングメソッドをオーバーライドしてjsonをserializerで整形するという手順でdeviseで返されるjsonの整形をするわ。
コントローラの継承をするわよ編
今回はログイン時のjsonを整形したいということで、ログイン時に呼ばれるアクションは
devise_token_auth/sessions#create
よ。ということで
devise_token_auth/sessions
コントローラを継承するわ。app/controllers/api/v1/auth/sessions_controller.rbclass Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController end新しく作ったコントローラが参照されるようにルーティングも変更よ。
私の場合はconfig/routes.rbRails.application.routes.draw do namespace :api do namespace :v1 do resources :users, only: [:show] mount_devise_token_auth_for 'User', at: 'auth', controllers: { registrations: 'api/v1/auth/registrations', # ここの部分ね sessions: 'api/v1/auth/sessions' } end end endさて、準備が整ったところでさっきの手順の2の太字になっている各アクションごとのレンダリングメソッドの説明をするわ。出力を制御する、と聞いて最初に対象のアクションをそのままオーバーライドすることを考えた子も多いと思うの。でも、出力だけを変えたいのにいちいち大元のアクションメソッドをオーバーライドするのは面倒じゃない?deviseちゃんでは特定のアクションで成功、失敗した時にjsonをレンダリングするメソッドが個別で用意されてるの。要は必要に応じてそこをいじればいいってわけね。
このメソッドちゃんたちの存在は公式ドキュメントに載ってるの。この記事で日本語訳してくださってる方がいるので貼っておくわ。
【翻訳】devise-auth-token公式ドキュメント表を見れば分かる通り、今回私が整形したいのはログインの成功時のjsonよ。つまりレンダリングメソッドで言うと
render_create_success
ね。早速オーバーライドしちゃいましょう。app/api/v1/auth/session_controller.rbclass Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController def render_create_success render json: @resource, serializer: UserSerializer end endログインが成功した時のリソース、つまりuserの情報は@resourceで取得できるわ。これをserializerで整形すると...
この通り!jsonが構造化されてカラムも設定したものしか返されていないわ!
参考文献
情報が比較的少ない中で有益な記事の存在に助けられました。心よりの感謝を申し上げます。
- 投稿日:2020-02-24T16:56:24+09:00
devise token authのjsonをserializerで整形するわよの巻
はじめに
この記事ではdevise token authでのjsonの出力を
active_model_serializer
gemを使って整形する手順を解説するわ。実際の開発中に少し詰まったことを元にしているからゴールとして"ユーザーのログイン成功時に返されるjsonをserializerで整形する"を設定するわ。他のアクション後に返されるjsonにも応用できるように心掛けるから安心しなさい。
devise関連の導入まで含めちゃうと長くなるからそこは割愛するわ、ごめんなさいね。準備するわよの巻
まずはgemのインストールから始めるわ。
Gemfile.gem 'active_model_serializers'bundle installこれでactive_model_serializersのインストールが完了したわ。
このgem自体の説明は他の記事に譲るとしてまずは設定をするわ。
設定用のconfig/initializers/ams.rb
ファイルを手動で追加しなさい。config/initializers/ams.rbActiveModel::Serializer.config.adapter = :json_apiこの部分では出力するjsonのフォーマットを指定しているわ。オプションの詳しい説明についてはこちらの記事に詳しいわ。
Railsのactive_model_serializerについて学ぶ100DaysOfCodeチャレンジ10日目(Day10:#100DaysOfCode)
ここでは
json_api
を指定したけど、あなたの好きなように設定しなさい。さて、次はいよいよserializerのファイルを作っていくわよ。
rails generate serializer User最後の
User
の部分は整形したいモデル名を指定することね。このコマンドでapp/serializers/user_serializer.rb
ファイルが作成されたわ、早速いじいじしちゃいましょう。app/serializers/user_serializer.rbclass UserSerializer < ActiveModel::Serializer attributes :id, :name, :nickname, :image, :confirmed_at, :updated_at endここではjsonで返すモデルのカラムを指定しているわ。他にも色々設定できるけど適宜自分で調べなさい、頑張ることね。
本題に入るわよの巻
ここまでで準備は完了よ、configに追加した設定を読み込ませるためにこのあたりで一旦サーバを再起動しておくことね、ん?もうやった? 良い子ね、クマちゃんのビスケットをあげるわ。
さて、まず見て欲しいものがあるの、serializerで整形をしない場合のログイン成功時に返されるjson(ログインに成功したユーザーの情報)よ。
続いて同じjsonをserializerで整形した場合よ。
データが構造化されているのと設定したカラムのみが出力されていることが分かるわね。
ちなみに下はapp/controllers/api/v1/user_controller.rbclass Api::V1::UsersController < ApplicationController def show @user = User.find(params[:id]) render json: @user, serializer: UserSerializer end endこんな感じのコードよ。
見ての通り、deviseの方のjsonも整形しないとアプリケーション全体として返すjsonのフォーマットに統一性が取れないことが分かるわ。これはフロント側としても混乱するしメンテナンス性も大きく損なうわ。
でも、自分で一から書くアクションなら上のコードみたいに簡単に実装できるんだけどdeviseは内部で勝手にやってくれるから分かりづらいわよね。
そこで今回は
1. コントローラを継承する
2. そこで各アクションごとのレンダリングメソッドをオーバーライドしてjsonをserializerで整形するという手順でdeviseで返されるjsonの整形をするわ。
コントローラの継承をするわよ編
今回はログイン時のjsonを整形したいということで、ログイン時に呼ばれるアクションは
devise_token_auth/sessions#create
よ。ということで
devise_token_auth/sessions
コントローラを継承するわ。app/controllers/api/v1/auth/sessions_controller.rbclass Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController end新しく作ったコントローラが参照されるようにルーティングも変更よ。
私の場合はconfig/routes.rbRails.application.routes.draw do namespace :api do namespace :v1 do resources :users, only: [:show] mount_devise_token_auth_for 'User', at: 'auth', controllers: { registrations: 'api/v1/auth/registrations', # ここの部分ね sessions: 'api/v1/auth/sessions' } end end endさて、準備が整ったところでさっきの手順の2の太字になっている各アクションごとのレンダリングメソッドの説明をするわ。出力を制御する、と聞いて最初に対象のアクションをそのままオーバーライドすることを考えた子も多いと思うの。でも、出力だけを変えたいのにいちいち大元のアクションメソッドをオーバーライドするのは面倒じゃない?deviseちゃんでは特定のアクションで成功、失敗した時にjsonをレンダリングするメソッドが個別で用意されてるの。要は必要に応じてそこをいじればいいってわけね。
このメソッドちゃんたちの存在は公式ドキュメントに載ってるの。この記事で日本語訳してくださってる方がいるので貼っておくわ。
【翻訳】devise-auth-token公式ドキュメント表を見れば分かる通り、今回私が整形したいのはログインの成功時のjsonよ。つまりレンダリングメソッドで言うと
render_create_success
ね。早速オーバーライドしちゃいましょう。app/api/v1/auth/session_controller.rbclass Api::V1::Auth::SessionsController < DeviseTokenAuth::SessionsController def render_create_success render json: @resource, serializer: UserSerializer end endログインが成功した時のリソース、つまりuserの情報は@resourceで取得できるわ。これをserializerで整形すると...
この通り!jsonが構造化されてカラムも設定したものしか返されていないわ!
参考文献
情報が比較的少ない中で有益な記事の存在に助けられました。心よりの感謝を申し上げます。
- 投稿日:2020-02-24T16:39:23+09:00
[font-awsomeのエラー]File to import not found or unreadable: font-awesome-sprockets.のエラーについて
1.エラーの様子
デスクトップ(裏側で製作していたファイル)では動いていたデータをホームディレクトリ(本番のファイル)に移した時上記のようなエラーが出ました。
2.エラーの原因
1.一般的な原因
・Gemfileのなかに
gem 'font-awesome-sass'
が抜けている・app/stylesheets/application.scssの中に
@import "font-awesome-sprockets"
と@import "font-awesome";
が抜けている2.見落としがち(特殊)な原因
・
@import "font-awesome-sprockets"
とするところを@import "font-awesome-compass";
としている。またはその逆。・別フォルダで作成したファイルを移すときに、
rails s
をしたままgemを追記し、bundle install
している3.解決方法
1.Gemfileのなかに
gem 'font-awesome-sass'
が抜けているGemfileに
gem 'font-awesome-sass'
を追記して下記コマンドを打ちましょう$ bundle install2.app/stylesheets/application.scssの中に
@import "font-awesome-sprockets"
と@import "font-awesome";
が抜けているapp/stylesheets/application.scssの中に下記2行を追記しましょう
@import "font-awesome-sprockets" @import "font-awesome";3.
@import "font-awesome-sprockets"
とするところを@import "font-awesome-compass";
としている。githubに記載されている公式の使用方法(readmeの部分)を読んで、どちらが自分の使用すべきコマンドか確認してみましょう。公式は下記urlです。
https://github.com/FortAwesome/font-awesome-sass
4.別フォルダで作成したファイルを移すときに、
rails s
をしたままgemを追記し、bundle install
している・Gemfilはサーバーを起動したままだと反映されないため、railsを再起動しましょう。コマンドは
controll+c
でrailsサーバーを落とし、再度rails s
をしましょう・上記でうまくいかない場合、他のもともとあったgemと干渉しあっている可能性があるためGemfile.lock(gemの実行コードが自動生成されたファイル)を全て削除し
bundle install
をしましょう。その際もサーバーを起動中の方はcontroll+c
でrailsサーバーを落とし、再度rails s
をしましょう
- 投稿日:2020-02-24T16:19:42+09:00
[Bootstrap]ドロップダウンボタンのアイコンを変更&「ドロップダウンがボタンに対して右下に出ちゃう!」と「選択肢の下に変な余白が!?」を解消
概要
表題の通りですが、長いので下記にまとめます。
1.ドロップダウンボタンのアイコンを変更する。
2.ドロップダウンがボタンに対して右下に出ちゃう!」を解消。
3.「選択肢の下に変な余白が!?」を解消。すべて簡単ですが、2.3に少しハマったのでメモを兼ねて共有させていただきます。
環境
Ruby:2.6.3
Rails:5.1.6
bootstrap:4.4.1
FontAwesome方法
1.ドロップダウンボタンのアイコンを変更する。
-button.btn.dropdown-toggleの中にFontawesome(iタグ)を通常通り配置。
-デフォルトのボタンを消す(.dropdown-toggle::after { display: none; })。2.ドロップダウンがボタンに対して右下に出ちゃう!」を解消。
div.dropdown-menuにdropdown-menu-rightクラスを追加。
→position:absolute関連のleftプロパティの値をいじっていたが、これだけでよかった。
要は、ドロップダウンメニューの起点がボタンに対して左上(デフォルト)になっているのを右上に変更する。3.「選択肢の下に変な余白が!?」を解消。
div.dropdown-item(下記link_toメソッド(HTMLではaタグ))の後にいくつかの半角スペース
→これが選択肢の内容として認識されていた為、選択肢の下の「変な余白」として反映されていた。home.html.erb<div class="dropdown"> <button class="btn dropdown-toggle" type="button" id="dropdownMenuButton", data-toggle="dropdown"> <i class="fas fa-chevron-down"></i> </button> <div class="dropdown-menu dropdown-menu-right"> <%= link_to "削除する", dreampost, class: 'dropdown-item', method: :delete, data: { confirm: "削除してよろしいですか?" } %> </div> </div>custom.scss.dropdown-toggle::after { display: none; }補足
ドロップダウンボタンのアイコンは、親要素にdisplay:flexとjustify-content:space-betweenで右端寄せしています。
ご指摘などございましたら、ぜひよろしくお願いいたします。
- 投稿日:2020-02-24T16:10:18+09:00
ActiveRecordでバリデーションを無視してデータを保存する方法
テストデータがほしいときに
rails c
してActiveRecordを使ってデータを挿入したいことがよくあるのですが、バリデーションが多く保存できるデータがかなり制限されているようなモデルの場合では、とりあえずテストデータ突っ込みたいときに結構な面倒になってしまいます。そこで、validationを通さずにsaveする方法がいくつかありそうなので試してみました。
save(validate: false)
Model.new(name: 'hoge', fuga_column: 'piyo', ... ).save(validate: false)そんな引数渡せたのか
update_attribute
Model.new.update_attribute(:name, 'test')カラムが一度に一つしか渡せないのつらい
感想
save(validate: false)
がカラムを一度設定できて楽かなあという印象でした。update_allやupdate_column(s)などはUPDATEクエリを発行するので新規作成できないという点でここでは除外しました。
参考サイト
- 投稿日:2020-02-24T15:16:36+09:00
どなたか Rails の System Test が得意な方、これをどうやったら解決できるかおしえてください
なにこれ
Docker Compose で Rails 6.0 を動かそうと思って、コードを書こうとしているのだけど、System テストがどうにもこうにも適切にうごかすことができません。おそらく System Test は Fail がきているだけなので Rails 側は適切に処理はしているのだと思いますが、Selenium 側が Rails(Puma) のサーバにアクセスできていないのではないかと思われます。もうかれこれ1日以上、この問題でスタックしております。どなたか知識をご教示ください。
コード
Dockerfile
FROM ruby:2.6-alpine WORKDIR /usr/src/app COPY Gemfile Gemfile.lock yarn.lock package.json ./ RUN apk update && \ apk upgrade && \ apk add --no-cache yarn tzdata libxml2-dev curl-dev make gcc libc-dev g++ imagemagick6-dev postgresql-client postgresql-dev chromium chromium-chromedriver udev && \ cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ gem update --system && \ bundle install && \ yarn install && \ rm -rf /usr/local/bundle/cache/* /usr/local/share/.cache/* /var/cache/* /tmp/* && \ apk del libxml2-dev curl-dev make gcc libc-dev g++ tzdataDocker compose File
version: '3' volumes: pg_data: redis_data: networks: main: services: pg: image: postgres:11-alpine restart: always networks: main: volumes: - pg_data:/var/lib/postgresql/data/ environment: TZ: Asia/Tokyo DATABASE_HOST: db POSTGRES_USER: dev POSTGRES_PASSWORD: dev POSTGRES_DB: dev redis: container_name: myapp-redis networks: main: image: redis:4.0 environment: TZ: Asia/Tokyo volumes: - redis_data:/var/lib/redis hub: image: selenium/hub:3.141.59-iron ports: - 4444:4444 environment: TZ: Asia/Tokyo networks: - main chrome: image: selenium/node-chrome:3.141.59-iron depends_on: - hub environment: TZ: Asia/Tokyo HUB_HOST: hub HUB_PORT: 4444 networks: main: web: build: context: ./ ports: - 3000:3000 volumes: - ./:/usr/src/app/ stdin_open: true tty: true environment: - TZ=Asia/Tokyo command: /bin/sh -c "rm -f /var/app/tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0' --early-hints" depends_on: - pg - redis networks: main: aliases: - webapplication_system_test_case.rb
require "test_helper" require 'selenium-webdriver' require 'capybara/rails' class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400], options: { url: "http://hub:4444/wd/hub" } endusers_test.rb
require "application_system_test_case" class UsersTest < ApplicationSystemTestCase setup do @user = users(:one) end test "visiting the index" do visit users_url assert_selector "h1", text: "Users" end end
- 投稿日:2020-02-24T14:13:30+09:00
paramsとwrap_parameters
JSONでデータを送るとき、コントローラ名と送信するパラメータのキー名(name属性のプレフィクス)の関係についての話です。
UsersControllerというコントローラがあるとします。このコントローラに対して、Ajaxを使いJSON形式かつPOSTメソッド(またはPUT、PATCH)でデータを送ります。パラメータには"user"のようなキーを付けません。
Axios.post('/users.json', { name: 'Taro', email: 'taro@example.com' });すると、コントローラのparamsには、"user"というキーが自動的に付きます(値がラップされます)。これが、ActionController::ParamsWrapperの機能です。
{"name"=>"Taro", "email"=>"taro@example.com", "user"=>{"name"=>"Taro", "email"=>"taro@example.com"}}次のようにストロングパラメータを使っていても大丈夫、というわけです。
def user_params params.require(:user).permit(:name, :email) endしかし、コントローラ名とは違うキー名を使いたい場合があります。次の例では"member"です。
Axios.post('/users.json', { member: { name: 'Taro', email: 'taro@example.com' }});すると、コントローラのparamsには、"user"というキーが付き、中は空となります。
{"member"=>{"name"=>"Taro", "email"=>"taro@example.com"}, "user"=>{}}これが気になるときは、wrap_parametersメソッドでキー名を指定します。このコントローラでラッピングに使われるキー名が"member"になります。
class UsersController < ApplicationController wrap_parameters :memberあるいは、次のようにすると、JSON形式ではラップしなくなります。
class UsersController < ApplicationController wrap_parameters format: []コントローラすべてに適用するには、initializers下の設定ファイルで指定します。配列
[:json]
を空にします。config/initializers/wrap_parameters.rbActiveSupport.on_load(:action_controller) do wrap_parameters format: [] end実際のプロジェクトでは
一番上のサンプル(キーを付けない場合)では、値が配列やハッシュの場合はラップしてくれません。ActionController::ParamsWrapperの設定をデフォルトにしたままだと混乱を招きそうです。
新規プロジェクトではinitializers下の設定でJSONを外しておくのがいいと思います。既存のプロジェクトでは、デフォルトでオフにするのはちょっとこわいので、コントローラごとに指定しておくことにします。
そのうえで、「AjaxでPOST、PATCHするときは、パラメータにキーを付けて値をラッピングして、ストロングパラメータを使うこと」というガイドラインを作っておくとよいかと。
補足
この機能いつからあったっけと調べたら、だいぶ昔で、2011年のRails 3.1からでした。
- 投稿日:2020-02-24T13:06:34+09:00
【Rails男子必見】エラー系女子との会話が弾む3つのテクニック【モテたい】
はじめに
添野です。TECH::EXPERTというプログラミングスクールに通っています。
7日目で基礎本試験を突破しました。今日は
エラー系女子にモテたい男子必見
Railsのエラー問題で苦戦中の方向けの記事です。モテる男子の会話テクニック
モテる男子がどんな会話をしているのか、渋谷のエラー系女子にインタビューしてみました。
✅ちゃんと話(エラー文)を聞いてくれて、私のことをしっかり考えてくれる(20歳 OL)
✅私が怒って(エラーを出して)も何の話をしてるのか考えてくれて、先回りで行動してくれる(17 歳JK)
✅前に話したこと(エラー)を覚えていて、何度も同じことを言わなくていいと気が楽ですね(26歳 看護師)話を聞いてくれる男子と一緒にいたいと感じるようですね。
それでは、インタビューで出た女子の意見について詳しく見ていきましょう。1. ちゃんと話を聞く「エラー文を見る」
皆さんは彼女とケンカになって、一方的に自分の意見を言ってしまった経験はありませんか?
モテる男子になるにはまず、エラー系女子の話をちゃんと聞いてあげましょう。
例えば、次のエラー文を見てください。
実はエラー文には「直すべきファイルが何か」「どう直せばいいか」が書かれているときがあります。
彼女は「あんたのここがダメだって言ってんでしょ!こうしてよ!」ってわざわざ教えてくれてます。
「showビューの6行目"user_signed_in"を"user_signed_in ? "に直せ」と書いてあるので、
これを直すだけで彼女の怒りは収まり、あなたはモテる男に生まれ変わります。とにかく、最初は彼女の言っていることをしっかり聞きましょう。
2. 何の話か考える「対象のファイルを特定する」
上記のように直すべき点を指摘してくれる場合は楽ですが、世の中親切な女の子ばかりではありません。
それでも、好きな子には振り向いて欲しいですよね。そんなアナタにとっておきの方法です。次のエラー文を見てください。
これは、pictweetアプリでログアウトボタンをクリックしたら発生しました。
これだけでは何のエラーかさっぱりですが、モテる男子はここで「あの話かな?」と先読みをします。
そして、先読みをするには「直前にあなたがとった行動」を思い出してください。
例えば、上記のエラーでは直前に「ログアウトボタン」をクリックしました。
ということは「ログアウトボタンに関係する何か」で彼女が怒っているのだと先読みできます。ログアウトボタンはapplicationビューに書かれているので、ファイルの中を見てみると、
「, method: :delete」という記述が抜けていることに気付きます。これが彼女の怒りの原因です。before <%= link_to "ログアウト", destroy_user_session_path> after <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
ここで、「記述抜けなんて、そんなの気づけなくね?」と思うかもです。
そんな時は作りたいアプリの完成形を横に並べておきましょう。補助輪を付けるんです。「そんなのダサいし勉強にならない」と思うかもしれません。ですが、プライドを捨ててください。
この方が早く成長できます。モテる男は、無駄なプライドは捨てています。
モノマネ・パクりから始めましょう。自分磨きは、その後です。こうして、モテる男は常に女の子の不満を先読みし、自分の行動を変えていきます。
3. 前に話したことを覚えている「エラーリストを作る」
これも特に多かった意見です。何度も同じことを言わせる男子はモテません。
一度指摘されたり、先読みで特定した彼女の不満をリスト化して、常にエラーに備えましょう。インタビューでは、「エラー系女子を怒らせたRails男子の行動Top14」も調査してきました。
ランキング形式で発表していきます。モテたい男子の皆さん、要チェックですよ!!第14位「検索すると全ての投稿が表示される」
「検索用パラメータ受け渡し時のキー名の記載ミス」
対象ファイル:indexビューbefore <%= form.text_field :keywords, placeholder: "投稿 検索", class: "search-input" %> after <%= form.text_field :keyword, placeholder: "投稿 検索", class: "search-input" %>第13位「ArgumentError」
「引数指定の記載漏れ」
対象ファイル:tweetモデルbefore def self.search after def self.search(search)第12位「ActionControl ler::ParameterMissing」
「form_withを使用しているのにformの記述が抜けている」
対象ファイル:showビューbefore <%= form_with(model: [@tweet,@comment], local: true) do |form| %> <textarea cols="30" name="text" placeholder="" rows="2"></textarea> <input type="submit" value="SEND"> <% end %> after <%= form_with(model: [@tweet,@comment], local: true) do |form| %> <%= form.text_area :text, placeholder: "text" , rows: "2" %> <%= form.submit "SEND" %> <% end %>第11位「リファクタリング問題」
「省略できる記述が省略せずに書かれている」
対象ファイル:indexビューbefore <% @tweets.each do |tweet| %> <%= render partial: "tweet", locals: { tweet: tweet } %> <% end %> after <%= render @tweets %>「彼氏のメールが長すぎて何を言いたいか分からない」
第10位「Undefined method」
パターン1「ログイン判定記述ミス」
対象ファイル:applicationビューbefore <% if true %> after <% if user_signed_in? %>パターン2「deviseメソッドの記述位置ミス」
対象ファイル:ルーティングファイルbefore resources :tweets devise_for :users after devise_for :users resources :tweets第9位「AcctiveRecord::RecordNotFound」
パターン1「ログアウトボタン記述ミス」
対象ファイル:applicationビューbefore <%= link_to "ログアウト", destroy_user_session_path %> after <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>パターン2「namespaceメソッドとresourcesメソッドの記述順ミス」
対象ファイル:ルーティングファイルbefore resources :tweets do resources :comments, only: :create end namespace :tweets do resources :searches, only: :index end after namespace :tweets do resources :searches, only: :index end resources :tweets do resources :comments, only: :create end第8位「NotNullViolation」
「deviseパラメータに指定しているキー名の記述ミス」
対象ファイル:applicationコントローラーbefore devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) after devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname]「イタリアンを食べに行こうって言ってデートにきたら寿司屋に連れてかれた」
第7位「空のツイートを保存できてしまう」
「バリデーションの記述がない」
対象ファイル:tweetモデルbefore after validates :text, :image, presence: true第6位「ターミナルでNo template found」
「ページ切替のリダイレクトアクション記載漏れ」
対象ファイル:commentsコントローラーbefore after redirect_to tweet_path(@comment.tweet)第5位「テキストや画像、コメントが表示されない」
「ストロングパラメーターの記述ミス」
対象ファイル:tweetsコントローラーbefore { user_id: current_user.id } after params.permit(:image, :text).merge(user_id: current_user.id)「LINEで素直な感謝の気持ちを送ったのに、未読スルー」
第4位「NoMethodError」
パターン1「renderメソッドで誤字」
対象ファイル:newビューbefore <%= render partial: "form", locals: { form: @form } %> after <%= render partial: "form", locals: { form: form } %>「デートの集合場所の住所をLINEで送ってきたのに、間違ってる」
パターン2「commentのルーティングがネストされてない」
対象ファイル:ルーティングファイルbefore resources :tweets resources :comments, only: :create after resources :tweets do resources :comments, only: :create end「デートの集合場所を、私が入ってないLINEグループにLINEしたことに気づいてない」
パターン3「コントローラーの誤字」
対象ファイル:tweetsコントローラーbefore def index @post = Post.includes(:user) end after def index @posts = Post.includes(:user) endパターン4「パス指定順のミス」
対象ファイル:showビューbefore <%= form_with(model: [@comment, @tweet], local: true) do |form| %> after <%= form_with(model: [@tweet, @comment], local: true) do |form| %>第3位「ツイート保存不可(表示されない)」
「ストロングパラメーターのrequireメソッド記述抜け」
対象ファイル:tweetsコントローラーbefore params.permit(:image, :text).merge(user_id: current_user.id) after params.require(:tweet).permit(:image, :text).merge(user_id: current_user.id)第2位「ActionView::MissingTemplate」
パターン1「ビューファイルがない/配置が間違ってる」
対象ファイル:_tweetビュー(部分テンプレート)before 部分テンプレート名が"tweet.html.erb" after 部分テンプレート名を"_tweet.html.erb"に修正「東京タワーを展望できるホテルというタレコミでデートにきたのに、東京タワーが見えない部屋を予約していた」
パターン2「renderメソッドの記述ミス」
対象ファイル:showビューbefore <%= render partial: "/post", locals: { post: post } %> after <%= render partial: "posts/post", locals: { post: post } %>第1位「Rounting Error」
対象ファイル:ルーティングファイル
パターン1 resourcesメソッドの誤字または抜け
indx→indexに修正、:createが抜けているので追加before resources :tweets, only: [:indx, :show, :new, :destroy, :edit, :update] do after resources :tweets, only: [:index, :show, :new, :create, :destroy, :edit, :update] doパターン2 rootメソッドの誤字
before root to: 'post#index' after root to: 'posts#index'「デート当日になって、デート先を決めてない/デート先を忘れた/道を間違えた」
まとめ
いかがだったでしょうか。
最後にもう一度、モテる男子の特徴をおさらいしましょう。✅ちゃんと話を聞く「エラー文を見る」
✅何の話か考える「対象のファイルを特定する」
✅前に話したことを覚えている「エラーリストを作る」大まかに理解できたら、上記でなぜモテるのかを考えて、自分を磨いていきましょう。
以上、Rails男子がエラー系女子にモテる方法でした。おすすめ記事
Rails消化のコツ
Rails用語集 基礎
Railsは"5つの属性"を意識しろ
- 投稿日:2020-02-24T00:46:35+09:00
Rails6 Access denied for user 'root'@'localhost' (using password: NO)のエラー
目的
- 記事名のエラーが出た時の筆者の解決方法をまとめる
- とりあえずエラーを回避する方法をまとめる、MySQLのrootパスワードをRailsの設定ファイルに直接記載するので個人プロダクト以上のアプリでは本方法はオススメしない。
筆者の環境
- Rails version
- 6.0.2.1
- MySQL vsersion
- Ver 8.0.18 for osx10.13 on x86_64 (Homebrew)
- OS
- macOS 10.13.6
手順概要
- MySQLのrootパスワードを確認
- RailsのDB設定ファイルにMySQLのrootアカウントのパスワードを入力
- 接続確認
手順詳細
- MySQLのrootパスワードを確認
- すでに知っている方はこの手順は飛ばす。
- パスワードを失念した場合は下記の方法に従いパスワードを再設定する。
RailsのDB設定ファイルにMySQLのrootアカウントのパスワードを入力
- 下記のファイルを開く
- アプリ名ディレクトリ/config
- database.yml
パスワードを追加する。
password:
の後ろにMySQLのrootアカウントのパスワードを記入する。# MySQL. Versions 5.5.8 and up are supported. # # Install the MySQL driver # gem install mysql2 # # Ensure the MySQL gem is defined in your Gemfile # gem 'mysql2' # # And be sure to use new-style password hashing: # https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html # default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhost接続確認
$ rails s
などを実行してローカル環境でエラーが出ないか確認する。
- 投稿日:2020-02-24T00:32:41+09:00
Rails/Heroku/Cloud9:本番pgでマイグレーションができない!
デプロイは問題なかったけど、マイグレーションで問題に直面した人向け。
- 結論
herokuにPostgreSQLのアドオンがなかった!!
なので、解決策は、
heroku addons:create heroku-postgresql
ターミナルでこれだけでした。- 経緯
rails db:migrate
は問題なかったし、
git push heroku
も問題なかったのに、
heroku run rails
で、問題発生。
PG::ConnectionBad: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
と表示され、
「サーバーに接続できない。ファイルもしくはディレクトリがないよー。ローカルでサーバー動いてて、UNIXドメインソケットの○○の接続を許諾してる?」とかなんとか。Heroku上で、gemで指定されているDBであるpgを使おうとしてんのに、heroku上では、pgなんてないっすよ。という状態だった様子。
- 参照元
macOS上で、同じ問題に遭っている人が多くいたのですが、
Cloud9上だとソースがなかなか無く、探すのに苦労しましたため、記念すべき初投稿にしました。。。
こちらの記事が参考になりました!知らない方の発信に感謝感謝。。。
[https://qiita.com/suzuki-x/items/b878723080aea1a673ed]