- 投稿日:2020-09-11T23:05:00+09:00
ユーザー管理機能をウィザード形式で実装する
概要
今回は、ユーザー管理機能をウィザード形式で実装することに関してです。
ウィザード形式とは、画面遷移しながらユーザー登録を行っていく形式です。今回、userモデルの登録要件は
nickname, grade, email, password続いて画面遷移してuser_infoモデルに
subject, school, profileを登録します。
ちなみに、user_infoは得意教科、在籍校、プロフィールとなっています。
実装
まずはdeviseをインストールして、userモデルを作成します。
emailとpasswordはデフォルトで入っているので、nicknameとgradeを追加します。
カラムを追加したので、次のようにコントローラーを編集します。
controllers.application_controller.rbclass ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :grade]) end end次に、userモデルにバリデーションをかけます(コードは省略)
そして、ビューファイルを作ります。
views.devise.registrations.new.html.erb<h2>ユーザー情報登録</h2> <%= form_for(@user, url: user_registration_path) do |f| %> <%= render "devise/shared/error_messages", resource: @user %> <div class="field"> <%= f.label :nickname %><br /> <%= f.text_field :nickname %> </div> <div class="field"> <%= f.label :grade %><br /> <%= f.text_field :grade %> </div> <div class="field"> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true, autocomplete: "email" %> </div> <div class="field"> <%= f.label :password %> <% if @minimum_password_length %> <em>(<%= @minimum_password_length %> characters minimum)</em> <% end %><br /> <%= f.password_field :password, autocomplete: "new-password" %> </div> <div class="field"> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation, autocomplete: "new-password" %> </div> <div class="actions"> <%= f.submit "Sign up" %> </div> <% end %> <%= render "devise/shared/links" %>ログイン画面を作ります。
views.home.index.html.erb<h1>トップページ</h1> <% if user_signed_in?%> <h2>ログインしています</h2> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <% else %> <h2>ログインしていません</h2> <%= link_to "新規登録", new_user_registration_path %> <%= link_to "ログイン", new_user_session_path %> <% end %>画面遷移後のuser_infoモデルを作ります。
この時、外部キーとして、user_idを紐づけるのを忘れないようにします。
その後、userモデルとuser_infoモデルのアソシエーションを組みます。
次はdeviseのコントローラーを作成。
rails g devise:controllers users次にルーティング。
routes.rbRails.application.routes.draw do devise_for :users, controllers: { registrations: 'users/registrations' } root to: "home#index" endここまできたらuser_infoを登録する実装をしていきます。
registrationsコントローラーにnewメソッドを記述し、ビューファイルにformを入れます。
views/devise/registrations/new.html.erb<%= form_for(@user, url: user_registration_path) do |f| %> <%= render "devise/shared/error_messages", resource: @user %> ---省略--- <div class="actions"> <%= f.submit "Next" %> </div> <% end %>ここからが少し記述が増えてきます。
createアクションを記述していきましょう。controllers/users/registrations_controller.rbdef create @user = User.new(sign_up_params) unless @user.valid? render :new and return end session["devise.regist_data"] = {user: @user.attributes} session["devise.regist_data"][:user]["password"] = params[:user][:password] @user_info = @user.build_user_info render :new_user_info endsessionを用いて1ページ目に記述したデータを持ってきます。
そしてattributesメソッドでデータを整形しています。build_user_infoで今回生成したインスタンス@userに紐づくUserInfoモデルのインスタンスを生成します。ここで生成したUserInfoモデルのインスタンスは、@user_infoというインスタンス変数に代入します。そして、住所情報を登録させるページを表示するnew_user_infoアクションのビューへrenderします。
user_infoを登録させるページを表示するnew_user_infoアクションと住所情報を登録するcreate_user_infoアクションのルーティングを設定しましょう。
routes.rbRails.application.routes.draw do devise_for :users, controllers: { registrations: 'users/registrations' } devise_scope :user do get 'user_infos', to: 'users/registrations#new_user_info' post 'user_infos', to: 'users/registrations#create_user_info' end resources :posts root to: "home#index" endこのルーティングに書いた通り、user_infoを登録するビューファイルを作成していきます。
views/devise/registrations/new_user_info.html.erb<h2>ユーザー情報登録</h2> <%= form_for @user_info do |f| %> <%= render "devise/shared/error_messages", resource: @user_info %> <div class="field"> <%= f.label :subject, "頑張りたい教科" %><br /> <%= f.text_field :subject %> </div> <div class="field"> <%= f.label :school, "学校名" %><br /> <%= f.text_field :school %> </div> <div class="field"> <%= f.label :profile, "自己紹介を記入しましょう" %><br /> <%= f.text_area :profile %> </div> <div class="actions"> <%= f.submit "Sign up" %> </div> <% end %> <%= render "devise/shared/links" %>このuser_infoを保存する記述をコントローラーにしましょう。
controllers/users/registrations_controller.rbdef create_user_info @user = User.new(session["devise.regist_data"]["user"]) @user_info = UserInfo.new(user_info_params) unless @user_info.valid? render :new_user_info end @user.build_user_info(@user_info.attributes) @user.save session["devise.regist_data"]["user"].clear sign_in(:user, @user) end protected def user_info_params params.require(:user_info).permit(:subject, :school, :profile) enduserをsaveした後に、.clearでsessionを削除しています。
そして、保存された後にログインされるように記述されています。最後に、create_user_infoアクションに対応するビューを作成します。
views/devise/registrations/create_user_info.html.erb<h2>登録が完了しました</h2> <%= link_to "トップへ戻る", root_path%>以上です。
感想
初めてウィザード形式の登録機能を実装しました。
本当はgradeの学年のところをactive_hashで実装したかったのですが、二時間エラーに悩まされた末に断念しました、、、
一通り実装してみて余裕があったらまたチャレンジしてみます。
日々頑張ってはいるのですが、あまり成長を感じられないです。
めちゃくちゃ記事みないと何もできません、、、頑張ります。
- 投稿日:2020-09-11T22:14:11+09:00
《コロナに負けず!!》29歳で営業職からジョブチェンジ。未経験で受託開発企業から内定を頂けました。
はじめに
昨年「エンジニアになるぞ!」と決意をし、
今年の3月に前職を退職(最終出社)、
3月下旬からプログラミングスクールに通いました。現在、29歳(今年で30歳!)です。
新卒からずっと営業職で、プログラミングは未経験。そんな自分でも、webエンジニアのスタートラインに
立つ事が出来ました。自分なりに戦略を立てて行った就活でもありましたので、
就職活動中の方の参考にして頂ければ幸いです。目次
・工夫して就活を行おうとした背景
・就活の結果
・学習開始〜内定までの流れ
・今回の転職活動でのポイント
・ポートフォリオについてのポイント
・学習方法について(おまけ)
・最後に工夫して就活を行おうとした背景
(興味ない方は読み飛ばして下さい!笑)
スクールに入った時点の私は転職に関しての認識が甘く、
「高い金額のスクールで基礎をしっかり学べば、転職はできるはず!」
「スクールからも紹介があるし!」
などと、このくらいの認識でした。ですが、この認識は間違いです!!!
少なくとも、20代前半の若い方でない限りは
エージェントからの紹介案件はごく少数になります。
※SESならいっぱいあります!企業側としてはエージェントを通して採用をすると、
その人の年収の30%程を支払う必要があります。つまり年収350万円の人材なら105万円もお金がかかります。
それならば、エージェント経由ではより若く優秀な人材だけを
選びたいですよね?そのため、エージェントから紹介される案件は
応募者の年齢や経験などが非常に大事になります。そのため、年齢が高くなるほど
そもそも紹介される案件の数は絞られます。そこに、今回はコロナによる経済打撃もあり
自分がスクールでの学習を終えた2020年6月、
「未経験」でのスクール経由の募集案件は3件のみでした。しかし、3社とも書類選考が通らず、、、涙
そこでやっと、このままでは「やばいぞ!!」と
気付かされました。。。そこで、ここから必死に情報の収集と
採用までの戦略を立てることにしました。就活結果について
《内定》
・2社(受託開発)《応募》
・企業HPからの直接応募:20社
・スクールのエージェント経由での応募:3社
・求人サイトでの応募:10社ほど
・DODAのエージェント経由での応募:20社ほど学習開始〜内定までの流れ
◇学習期間
2020年3月末月〜7月末(4ヶ月間)◇転職活動期間
2020年8月(1ヶ月間)《3月末〜5月末まで》
プログラミングスクールにて学習、卒業《6月》
1ヶ月かけて初めての自主制作アプリを作成!ですが、他の方のポートフォリオのレベルの高さを見て絶望し、
2つ目のポートフォリの作成を決意しました!《7月》
2週間程で2つ目のポートフォリを作成!
そこから2週間はインフラの環境構築やCI/CDに
挑戦していました。《8月》
企業HPからのweb応募を開始しました!
8月末に内定を獲得!今回の転職活動でのポイント
しっかり作り込んだポートフォリオを用意した
→スクール卒業後、すぐに転職活動を開始せずにポートフォリオの強化に努めました応募は企業のHPから送ることを徹底した
→書類選考の突破が重要です上記の2点が今回の就活でのポイントになります。
ポートフォリオについてのポイント
自主制作アプリ:「BestYourTitle」
このアプリは、求人広告のライター初心者や採用担当者が、
求人広告を書く際に「応募したい!」と思ってもらえるような
キャッチコピーを書けるよう、練習出来るサイトです。▼URL
https://www.bestyourtitle.com/
※かんたんログイン機能で、ゲストとしてログイン出来ます。▼GitHub
https://github.com/y-kiku1111/docker_byt
※ポートフォリオに関しての詳細は、上記Githubに記載しています内定頂いた2社とも、ポートフォリオについて
非常に高評価を頂けました。特にDocker、AWSのFargateは
印象が良かったです。ただ、実際に見て頂くと
サイト自体はレベルの高いものではないので、・モダンな技術に挑戦し、その企業で活用している技術とマッチした
・サイトデザインやインフラ構成図など、目に見える差別化を行うこの2点に尽きるのかなと思います。
また、ポートフォリオに関しましては
youtuberの勝又さんの動画やオンラインサロンで
「高評価されるポートフォリオ」がどの程度のレベルなのかを
知ることが出来、とても参考にさせて頂きました!スクールではポートフォリオに関してのアドバイスは
一切ありませんでしたので、実際に採用された初学者のポートフォリオが
数多く見れるのは、非常に有り難かったです。就職活動についてのポイント
・求人サイトを使って応募したい企業のリストアップ
・エージェントサービスを利用しての面接練習や情報の入手(応募もしましょう)
・上記を行った上でHPからの直接応募これが自分の中では、最も効率的かと思います。
リストアップに利用した求人サイト
・wantedly
・Green
・Find job!特にFindjobは、業務未経験OKの企業で絞ることが出来て
重宝しました。基本的には上記のサイトから応募するのではなく、
サイトからリストアップをして直接応募をします。なぜ直接、採用HPから応募をするかと言うと、
求人サイトによっては、エージェントと同じく
掲載は無料だが、採用すると企業にお金がかかるサイトもあるため
企業HPからの応募が、企業側にメリットが大きいためです。採用課金型でなければ、
求人サイトからの応募も一緒にした方が
良いかと思います。例えば、1日10社を目標に各企業のHPから
応募をし続けると良いと思います。
(自分は1日5社と決めていました)書類選考さえ突破すれば、あとはエージェントさんと
練習した面接だけです。しっかりと自分がエンジニアになりたい理由、
また作り込んだポートフォリについて熱弁できれば問題無いはずです!学習方法について(おまけ)
個人的には、強制的に勉強に集中し基礎を学べるスクールは
重宝しましたので、やるかやらないかなら、お勧めです。ただ、スクールはあくまで基礎を学ぶための環境にお金を出すようなイメージです。
そのため、スクール費用が高すぎると割に合わない可能性もあります!スクールを卒業するだけでは、レベルとしては確実に低いと思いますので、
例えばメンターさんを雇いながらポートフォリオのレベルを高めるなど、
基礎を身につけてからの自己学習を強く推奨します。自分はMENTAというサービスを利用していました。
(https://menta.work/about)最後に
ここまで長文を読んで頂き、
本当にありがとうございました!長くなりましたが、上記が自分の転職活動で
意識したことや、実践したことになります。少しでも、お役に立てましたら幸いです。
また、今回やっとエンジニアのひよっことして
スタートラインに立てたのは、自分の転職活動を支えて下さった
周りの方々のお陰です。無職になったのにも関わらず応援してくれた同居人や、
期待を込めて送り出して頂いた前職の上司や同僚、
心配しながらも応援して下さった両親、本当にありがとうございました!!!
就職した企業は、ひよっこではなく
成果を出す人材を期待して頂いているかと思いますので、
その期待を超えられるよう、頑張って行きます!改めまして、最後までお読み頂きありがとうございました!
- 投稿日:2020-09-11T21:59:33+09:00
[Rails]Formオブジェクト使用時にエラーメッセージが日本語化されない[locale]
概要
オリジナルアプリ制作時、formオブジェクトを利用した箇所のエラーメッセージだけ日本語化されなかったのでその備忘録を。
https://qiita.com/rytr823/items/e9fbbb16884b6f52d463
調べていたら上記の方とほとんど同じでした。感謝。前提
ja.ymlファイルの作成までは終わっている
環境
ruby 2.6.5
rails 6.0.0
gem 'rails-i18n'導入済みformオブジェクトの配置場所
app/forms/guest_data.rb
EZ図
この図のguestsテーブルとbathsテーブルとdrinksテーブルの3つをformオブジェクトを使用して保存しようとしていた。
内容
ja.ymlに記述しても日本語化が適用されない
間違ってた記述
config/locales/ja.ymlja: activerecord: attributes: guest: first_name: 苗字(全角) last_name: 名前(全角) first_name_kana: 苗字(カタカナ) last_name_kana: 名前(カタカナ) gender_id: 性別 visit1_id: 1回目の利用日 visit2_id: 2回目の利用日 description: 利用者の詳細 bath: bathing_id: 入浴の種類 infection_id: 対応が必要な感染症 timing_id: 入浴の順番 remark_bath: 入浴の備考 drink: drink_type_id: 飲み物の種類 thickness_id: とろみの量 warm: 温めるか diabetes: 糖尿病正しい記述
config/locales/ja.ymlja: activemodel: attributes: guest_data: first_name: 苗字(全角) last_name: 名前(全角) first_name_kana: 苗字(カタカナ) last_name_kana: 名前(カタカナ) gender_id: 性別 visit1_id: 1回目の利用日 visit2_id: 2回目の利用日 description: 利用者の詳細 bathing_id: 入浴の種類 infection_id: 対応が必要な感染症の有無 timing_id: 入浴の順番 remark_bath: 入浴の備考 drink_type_id: 飲み物の種類 thickness_id: とろみの量 warm: 温めるか diabetes: 糖尿病原因
記述をした
app/forms/guest_data.rb
はactiverecordではなくactivemodelを継承していたため。参考記事
https://qiita.com/rytr823/items/e9fbbb16884b6f52d463
https://qiita.com/jacoyutorius/items/e0d2cfdb61ff4c4fd1e7
https://qiita.com/astap/items/c07e0b08273fd97aaa91
- 投稿日:2020-09-11T19:09:56+09:00
Railsコンソールを使用してレコードを追加する
動機
Railsでアプリケーション開発を行っている際DBへレコードの追加をどう行うか忘れてしまうため記録
前提:コンソールの立ち上げ
$ rails cレコードの追加
レコードの追加は createメソッドを使用
[1] pry(main)> モデル名.create(カラム名: '追加したいvalue')例)
[1] pry(main)> Todo.create(title: 'Rails',content: 'Rails Practice' )他にも
・create!
何かが足りない時にエラーを返してくれる、絶対に不足しては困るものがある場合使用・save
インスタンスを作成しsaveを使用することでcreateと同じ
こちらもsave!があるインスタンス名 = モデル名.new({ カラム名: ‘文言’, カラム名: ‘文言’ }) インスタンス名.save・update
データの更新を行いたい時に使用
update!もあるモデル名.update({ カラム名: ‘文言’ })・assign_attributes
下記の使用でupdateと同じ変数名 定義 変数名.assign_attributes({ カラム名: ‘文言’ }) 変数名.save
- 投稿日:2020-09-11T18:54:38+09:00
errors.full_messagesの配列を文字に変えて出力する
起こった問題とやりたいこと
errors.full_messagesが配列なので、flashメッセージが、["hoge hoge"]が出力される
→ 文字に変えて、hogehogeと出力したいやったこと
errors.full_messagesにto_sentenceメソッドをつけるだけ
user_contorller.rbclass Users::UserController < Users::ApplicationController #中略 def update @user = user.Users flash[:alert] = @user.errors.full_messages.to_sentence end #中略 end今日もお疲れ様でした。
- 投稿日:2020-09-11T16:36:38+09:00
Railsで「一度クリックしたら二度と表示させない」を実装
今回は、ページ更新の度にDBにあるテーブルからランダムでレコードをひとつ取り出して表示。
その表示をクリックしたら、以降はクリックしたユーザー(ログインユーザー)のみ、ランダム選択のプールからクリック済みの項目が排除されるという仕様を実装します。準備
ランダムプールのテーブルをlistsとします。
usersとlistsを結びつける、user_listsテーブルを作成しておきます。(カラムはuser_idとlist_idです)deviseの導入が前提です。
実装方針
①クリックする度に、user_listsテーブルにユーザーとクリックしたlistsが保存されるようにします。
②user_listsテーブルから、ユーザーがクリックしたlistsをwhereで抽出します。
③抽出した配列を条件にwhere.notで排除していきます。
では、やってみます。#ログイン中ユーザーのidでレコードを検索し、取得したレコード群のlist_idを配列化 list_ids = UserLists.where(user_id: current_user.id).pluck(:list_id) #list_idsを条件にレコードを抽出し、order以下でさらにその中からランダムで1つ選出 @list_element = List.where.not(id: list_ids).order("rand()").limit(1)[0]これでコントローラー側は完成です。
あとはビュー側で@list_elementを使って表示すれば良いのですが、
このままだとlistsテーブルに存在する全ての項目をクリックし終えるとエラーが出てしまうので、<% if @list_element == nil %> <p> 未クリックの項目はありません </p> <% else %> <%# 以下で@list_elementを表示 %>としておくと、確実です。
- 投稿日:2020-09-11T16:12:46+09:00
【Rails】「&.」あ!それみたことある!!(意味は知らない)
「&.」とは(概要)
ぼっち演算子と呼ばれます。
Ruby
では通常、レシーバーに対してメソッドが実行された時、レシーバー(オブジェクト)がnil
だった場合にエラーを返します。しかしプログラムによっては、エラーを返したくない時があります。そんな時に使うのが「&.」(ぼっち演算子)です。
ぼっち演算子はオブジェクトが
nil
だった場合にエラーではなく、nil
を返してくれます。「&.」は何が嬉しい??
返り値が「〇〇かnil」を返すみたいなメソッドが
Ruby
にはあります。それを受け取ったレシーバーに、レシーバーに「nil
が想定されていないメソッド」を使ってしまうと、エラーが出力されてしまいます。そんな時に「&.」を使うことで、そのメソッドはエラーではなく、
nil
を返してくれるようになります。「&.」の懸念点
ぼっち演算子を使ったからと言って、確実に
nil
を返してくれるというわけではありません。そのメソッド名が存在しない(スペルミス等)場合にはNoMethodError
が出力されてしまいます。ぼっち演算子は「レシーバが
nil
でもエラーを返さない」というだけなので上記のような要因からくるエラーは防げません。基本的な使い方
オブジェクト&.メソッド基本的な形は上記の通りです。
上手な例が思いつかなかったのですが、下記の記事がいい感じだったので拝借します。
https://qiita.com/yoshi_4/items/e987b698c1978d248cfc@nickname = current_user.nickname @nickname = current_user&.nickname前者では、ログインしていない場合、エラーが出てしまいます。
currrent_user
がnilだからです。
後者では、ぼっち演算子を使っているのでエラーははかれません。まとめ
ともかく
- 「ぼっち演算子」を使うと、レシーバーが
nil
でもエラーではなく、nil
が返される- メソッドが存在しない(スペルミス)場合はエラーが出力されてしまう
という感じでしょうか。ご指摘等ありましたら、よろしくお願いします?♂️
- 投稿日:2020-09-11T15:06:22+09:00
ECサイトの店舗名を表示させたい ミスの箇所はコンソールで確認出来る
ふるさと納税のようなサイトをイメージして、サイトのTopページに商品とその商品を出品している店名表示をさせようとした所、NoMethodErrorが出てしまいました。
備忘録兼ねて、こういう所を見ると良いのかと勉強になりましたので記載致します。現状は
・itemとclientは既にモデル上でアソシエーションは構築済み。
(itemが子でclientが親)
・clientにはshop_nameのカラム持たせている。
・Adminコントローラーには@items = Items.allでを指定済み原因が思い当たらず、ターミナルにてコンソール($rails c)で確認。
表示が小さくて大変恐縮ですが
3行目に「Unpermitted parameters」という表示があります。
右記の"shop_name","shop_name_kana","last_name_kana","first_name_kana",
"telephone_number"の項目は許可されてませんよ、という意味のようです。新規登録時に関わってくるのは基本的にdeviseかapplicationコントローラーで
自身で触っていたのはapplicationコントローラーだったのでそちらをチェック。parametersの中には見事に弾かれていた項目の記載が抜けていました…。
なので、項目を追加して
コンソールで再度チェックをしてみた所、Unpermittedという言葉は消え無事に店名表示が出来ました!
コンソールのそんな所、今まで見ていなかったので記載させていただきました。
簡単ですが、以上となります。
- 投稿日:2020-09-11T14:58:30+09:00
【Rails】DBをリセットしてmigrateをやり直す方法
はじめに
Railsで作成したアプリで、一番はじめに作ったモデルのテーブルが間違っていたことに気づいたため、DBをリセットしてmigrateをやり直しました。
以下の記事を参考にやり直すことができました。
参考 Rails:migrateでDBをリセットして最初からつくり直す方法。
参考 【Rails】$rails db:rollbackしたい時の間違えない手順何が間違っていたのか
deviseでユーザー登録をさせる時に、生年月日のカラム型をstring型にしてしまっていた。このままでも登録は出来たが、生年月日の欄を入力した状態で他の部分のバリデーションに引っ掛かり、エラー文を表示させる画面に移った時に以下の表記。
ターミナルに表示されたエラーActionView::Template::Error (undefined method `day' for "{1=>1932, 2=>nil, 3=>nil}":String):ページを遷移した時に、フォームに入っていた情報がdata型では無かったのでおかしいことになってしまった様子。(string型だと、ハッシュにして、それぞれの番号を年月日に当てはめていた?)
解決策
db:reset
カラム型を変更すると、既に登録されている生年月日のデータがおかしくなるかなと思って、まずはテーブルのデータを削除しようと思い、以下の記事を見つけた。
①全てのレコードを空にしたい場合はrake db:resetを行う。
rake db:resetは全てのテーブルを dropし、"db/schema.rb"を元にテーブルの再作成を行います。②"db/migrate/" 以下の全ての migration を実行してテーブルを再作成したい場合は、rake db:migrate:reset
全てのテーブルを dropし"db/migrate/"以下の全ての migration を実行してテーブルを再作成を行うため、こちらの方が効力が強いかと思料されます。migrationファイルを編集して②やればOKだなと思ったけど、なんか怖かったのでとりあえず①でDBをリセットすると無事に無事に、DB内のデータは全て削除されていた。
データベースをリセット% rails db:reset Dropped database 'database名_development' Dropped database 'database名_test' Created database 'database名_development' Created database 'database名_test'rollback
続いて、カラム型を変更するためにmigrationファイルを修正した。
rails db:rollback
で良いのかなと思ってたけど、既にmigrationファイルが5つあったため、指定箇所までrollbackする% rails db:rollback STEP=(num) # num個前のファイルまでrollbackできるrollbackして、migrationファイルを修正して
migration% rails db:migrate一応確認すると無事に反映されていました。
ちゃんと反映されたかを確認% rails db:migrate:status Status Migration ID Migration Name -------------------------------------------------- up 20200831104449 Devise create users up 20200902085108 Create items up 20200903070748 Create active storage tablesactive storage up 20200907074332 Create orders up 20200910081458 Create addresses無事にカラム型も修正できてエラーも解決できました。
- 投稿日:2020-09-11T13:15:30+09:00
既存の.erbファイルをhamlに変換する方法
- 投稿日:2020-09-11T13:08:46+09:00
railsにVue.jsを導入しようとしたらエラーがでた物語
環境
・Ruby 2.6.6
・Rails 6.0.3.2
・Docker/docker-composeやったこと
https://qiita.com/Moo_Moo_Farm/items/afacfe4349af6a106253
参考URLを見ながらVue.jsを導入しようとすると、以下のエラーが発生。% docker-compose run web rails new . --force --no-deps --database=mysql --skip-test --webpack=vue create README.md create Rakefile create .ruby-version #~~~~~~~~~なんやらなんやら。。。~~~~~~~~~~~~~~~ Webpacker successfully installed ? ? rails webpacker:install:vue error Couldn't find an integrity file error Found 1 errors. ======================================== Your Yarn packages are out of date! Please run `yarn install --check-files` to update. ======================================== To disable this check, please change `check_yarn_integrity` to `false` in your webpacker config file (config/webpacker.yml). yarn check v1.22.5 info Visit https://yarnpkg.com/en/docs/cli/check for documentation about this command.「無事に
Webpacker successfully installed
が出たしやったー!」と思ったら、なんやらエラーが出ている。。。解決方法
Please run yarn install --check-files to update.
と言っているので、その通りに実行% docker-compose run web rails new . --force --no-deps --database=mysql --skip-test --webpack=vue Webpacker successfully installed ? ? rails webpacker:install:vue Copying vue loader to config/webpack/loaders create config/webpack/loaders/vue.js Adding vue loader plugin to config/webpack/environment.js insert config/webpack/environment.js insert config/webpack/environment.js Adding vue loader to config/webpack/environment.js insert config/webpack/environment.js insert config/webpack/environment.js Updating webpack paths to include .vue file extension insert config/webpacker.yml Copying the example entry file to /vue_app/app/javascript/packs create app/javascript/packs/hello_vue.js Copying Vue app file to /vue_app/app/javascript/packs create app/javascript/app.vue Installing all Vue dependencies run yarn add vue vue-loader vue-template-compiler from "." #~~~~~~~~~なんやらなんやら。。。~~~~~~~~~~~~~~~ Webpacker now supports Vue.js ?無事に成功。
yarn install --check-files
の役目は何?https://classic.yarnpkg.com/ja/docs/cli/install/
yarnで入ってるパッケージが古いのよ!って怒られてるからアップデートでもしてるのかしら?と思ったけど、参考URLには以下のように説明されている。node_modules に既にインストールされたファイルが削除されていないことを確認します。
う〜ん、根本的になぜ解決できたのかよく分からん。
- 投稿日:2020-09-11T12:54:10+09:00
【form_with】でcheck_boxメソッドにclassやIDを付与する
記述方法
{}のなかにまとめて記述すれば良い。
具体的な記述<%= f.check_box :diabetes ,{checked: true, class: "form-check-input", id: "diabetes", style: "transform:scale(2.0);" }, "true", "false" %>間違った例<%= f.check_box :diabetes ,{ }, "true", "false", class: "form-check-input", id: "diabetes" %>{}の中にはcheckd: :trueしか入れてはいけないと思っていたため、ハマってしまった。
備忘録として書き残しておく。
- 投稿日:2020-09-11T12:54:10+09:00
【form_with】でhtmlタグのcheck_boxにclassやIDを付与する
記述方法
{}のなかにまとめて記述すれば良い。
具体的な記述<%= f.check_box :diabetes ,{checked: true, class: "form-check-input", id: "diabetes" }, "true", "false" %>間違った例<%= f.check_box :diabetes ,{ }, "true", "false", class: "form-check-input", id: "diabetes" %>{}の中にはcheckd: :trueしか入れてはいけないと思っていたため、ハマってしまった。
備忘録として書き残しておく。
- 投稿日:2020-09-11T10:04:26+09:00
Rails 6で認証認可入り掲示板APIを構築する #6 show, create実装
←Rails 6で認証認可入り掲示板APIを構築する #5 controller, routes実装
showテストの実装
前回のindexに続き、showのテストとcontrollerを実装していきます。
showは、パラメータのidを元にfindして返すという挙動です。テストは正常にレスポンスが返ってくることと、存在しないIDの時に404が返ってくることあたりでしょうか。
spec/requests/v1/posts_controller.rb... + describe "GET /v1/posts#show" do + let(:post) do + create(:post, subject: "showテスト") + end + it "正常レスポンスコードが返ってくる" do + get v1_post_url({ id: post.id }) + expect(response.status).to eq 200 + end + it "subjectが正しく返ってくる" do + get v1_post_url({ id: post.id }) + json = JSON.parse(response.body) + expect(json["post"]["subject"]).to eq("showテスト") + end + it "存在しないidの時に404レスポンスが返ってくる" do + get v1_post_url({ id: post.id + 1 }) + expect(response.status).to eq 404 + end + end ...説明が漏れていましたが、letは呼び出された時に遅延評価されます。
つまりpostという変数が呼ばれるまでは実行されず、呼ばれた時点で実行されます。上記例だと、itブロックの中でpost.idと呼ばれた時にcreateされます。
当然、controller未実装なのでテストはコケます。showの実装
app/controllers/v1/posts_controller.rb... def show - # TODO + render json: { post: @post } end ...これで追加した3テストのうち2つは通過しますが、残り1個404エラーのテストが通過しません。
RailsでRecordNotFound例外が起き、jsonじゃないレスポンスが返っちゃっていますね。全てのcontrollerのsuperクラスであるapplication_controller.rbを修正します。
app/controller/application_controller.rb# frozen_string_literal: true # # controllerのsuperクラス # class ApplicationController < ActionController::API + rescue_from ActiveRecord::RecordNotFound, with: :render_404 + def render_404 + render status: 404, json: { message: "record not found." } + end end※無駄に2行空いているのはQiitaのシンタックスハイライトがうまく効かないだけなので、本来は1行でOKです
上記のように対応することで、レコードが見つからない(ActiveRecord::RecordNotFound)例外が投げられた時にrescueされ、
render_404
が実行されます。
そしてstatus: 404
の通り404レスポンスコードでjsonが返されます。ここまで実装するとテストも通過します。
念の為curlでも確認してみましょう。$ curl localhost:8080/v1/posts/0 {"message":"record not found."} $ curl localhost:8080/v1/posts/1 {"post":{"id":1,"subject":"hoge","body":"fuga","created_at":"2020-09-05T13:50:01.797Z","updated_at":"2020-09-05T13:50:01.797Z"}}createテストの実装
createは新しいレコードを生成するので、1レコード増えること、増えたレコードが登録時と一致すること、不正なパラメータの時に生成できないことを確認します。
spec/requests/v1/posts_controller.rb+ describe "POST /v1/posts#create" do + let(:new_post) do + attributes_for(:post, subject: "create_subjectテスト", body: "create_bodyテスト") + end + it "正常レスポンスコードが返ってくる" do + post v1_posts_url, params: new_post + expect(response.status).to eq 200 + end + it "1件増えて返ってくる" do + expect do + post v1_posts_url, params: new_post + end.to change { Post.count }.by(1) + end + it "subject, bodyが正しく返ってくる" do + post v1_posts_url, params: new_post + json = JSON.parse(response.body) + expect(json["post"]["subject"]).to eq("create_subjectテスト") + expect(json["post"]["body"]).to eq("create_bodyテスト") + end + it "不正パラメータの時にerrorsが返ってくる" do + post v1_posts_url, params: {} + json = JSON.parse(response.body) + expect(json.key?("errors")).to be true + end + end
attributes_for
を使うとbuildと同じくDBにsaveしないでオブジェクトが返ってきます。
その際にActiveRecord形式ではなくシンプルなオブジェクトとして返ってくるかつ、idやcreated_at, updated_atというpost時に不要なカラムは存在しないので便利です。なお、この際に変数名を
post
にしないようご注意ください。
筆者は記事執筆当時post
にしてしまい、post v1_posts_url, params: post
となりget, postのpostがオーバーライドされてテストが正常に動かない状態となりました…解消までかなり時間がかかりました
expect do
post v1_posts_url, params: new_post
end.to change { Post.count }.by(1)
このブロックはpostをすることでPost.countが1増加するテストとなります。expect.to eq
ではなくexpectがブロックになっているのがポイントです。createの実装
controllerを実装します。
app/controllers/v1/posts_controller.rb... def create - # TODO + post = Post.new(post_params) + if post.save + render json: { post: post } + else + render json: { errors: post.errors } + end end ...$ curl localhost:8080/v1/posts -X POST -H 'Content-Type: application/json' -d '{"subject":"moge","body":"hoge"}' {"post":{"id":3,"subject":"moge","body":"hoge","created_at":"2020-09-06T10:31:38.375Z","updated_at":"2020-09-06T10:31:38.375Z"}}rubocopとrspecが正常に動いたらcommit。
本記事においてとても参考にさせていただきました。ありがとうございます。
参考:Railsで超簡単API続き
→Rails 6で認証認可入り掲示板APIを構築する #7 update, destroy実装
【連載目次へ】
- 投稿日:2020-09-11T02:56:53+09:00
HerokuでDocker環境Rails MySQLなものを動かす。deviseかつtwitter APIを隠しながら
人に見せる用に書いていません。
自作記事のお父上、Rails+MySQL+Nginx+Unicorn+Docker+CircieCIな開発環境を作りたいえ〜の記事の続き。
上で作った環境に[Rails] deviseの使い方(rails5版)を追加し、かつTwitterAPIを
gem 'dotenv-rails'
で隠しながら、本番環境のherokuにアップロードした。①docker-compose.ymlのコマンドを変更する
docker-compose.ymlcommand: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"② gem 'dotenv-rails'を導入する
目的:TwitterAPIキーをGitHubのローカルに入れたくない
envファイルはGitの管理に入れたくないので、.gitignoreファイルに以下を追記しておきましょう。
.gitignore
に.env
を追加する。これで.envはGitの管理下から外れます。
https://pikawaka.com/rails/dotenv-rails
http://vdeep.net/rubyonrails-dotenv③ APIキーをdotenv-railsの.envで隠しながら導入する
[Rails] deviseの使い方(rails5版)の記事のtwitterAPIを追加する場所をENV[]に書き換える
config/initializer/devise.rbconfig.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['DATABASE_URL']④ Herokuの環境変数を変更する
多分、DATABASE_URLとTWIITER_API_KEY,DATABASE_URLはマスト。
herokuのGUIのSettingのConfig VarsかHerokuアプリの環境変数設定(CUIで設定)で設定する
Herokuアプリの環境変数設定
- ClearDBのURL確認
以下のコマンドで、ClearDBのURLが確認できる。$ heroku config === <アプリの名前> Config Vars CLEARDB_DATABASE_URL: mysql://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true
- 環境変数の設定
上記コマンドで表示されたそれぞれの値を変数に設定する。$ heroku config:add DB_NAME='<データベース名>' $ heroku config:add DB_USERNAME='<ユーザー名>' $ heroku config:add DB_PASSWORD='<パスワード>' $ heroku config:add DB_HOSTNAME='<ホスト名>' $ heroku config:add DB_PORT='3306' $ heroku config:add DATABASE_URL='mysql2://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true'※ RailsのGemfileで'mysql2'を使用しているので、
DATABASE_URL
はmysql2://
で始める必要がある。
設定内容を確認すると、以下のように表示される。$ heroku config === <アプリの名前> Config Vars CLEARDB_DATABASE_URL: mysql://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true DATABASE_URL: mysql2://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true DB_HOSTNAME: <ホスト名> DB_NAME: <データベース名> DB_PASSWORD: <パスワード> DB_PORT: 3306 DB_USERNAME: <ユーザー名>Herokuへデプロイ
Railsプロジェクトに必要な準備
config/environments/production.rb
に以下を追記
(この辺りの設定に関しては、後々修正します。)config.assets.compile = true config.assets.initialize_on_precompile=falseこれプラス、
gem 'dotenv-rails'
の.env
で作ったTwitterAPIをheroku側に設定する。参考
https://qiita.com/ymstshinichiro/items/d6ea229f6eb4778006c2
https://golikyua.hatenablog.com/entry/2020/01/09/135254
https://www.sejuku.net/blog/tutorial/111347
- 投稿日:2020-09-11T00:24:27+09:00
【Rails】俺のための初期設定 + Gem導入
rails newをするときに、随時設定をしたりGemを入れるのが面倒だったので、自分用にcloneするだけでいいリポジトリを作りました。
https://github.com/aiandrox/rails_appついでに作業をざっくりまとめました。
DockerやCircleCI用の設定はしていません。
実際に導入する際にはGitHubでバージョン指定や手順などを確認してください。バージョン
- Ruby 2.7.1
- Rails 6.0.3.3
- yarn 1.22.5
初期コマンドは
rails new rails_app --skip-test-unit --database=mysql
です。日本語化・時刻の設定
config/application.rb... module RailsApp class Application < Rails::Application ... # 言語・タイムゾーンを日本に設定 config.i18n.default_locale = :ja config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s] config.time_zone = 'Tokyo' config.active_record.default_timezone = :local end endGemfilegem 'rails-i18n' gem 'enum_help'ついでにモデル用の日本語データも準備しておく。
en.ymlは不要なら消してしまってもいい。config/locales/model.ja.ymlja: activerecord: # User.model_name.human models: user: ユーザー # User.human_attributes_name(:name) attributes: id: ID created_at: 作成日時 updated_at: 更新日時 user: name: 名前 enums: user: role: admin: 管理者 general: 一般 guest: ゲストリンク
- svenfuchs/rails-i18n
- rails-i18n/ja.yml at master · svenfuchs/rails-i18n
- i18nを上書きする場合はこれをコピーして書き換える。
- zmbacker/enum_help
デバッグ用のGem
binding.pry
を使いたいので、byebugを削除してpryを入れる。Gemfilegroup :development, :test do # byebugは不要なら削除してよい gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] # 以下3行を追加 gem 'bullet' gem 'pry-byebug' gem 'pry-rails' end group :development do gem 'web-console', '>= 3.3.0' gem 'listen', '~> 3.2' gem 'spring' gem 'spring-watcher-listen', '~> 2.0.0' # 以下2行を追加 gem 'better_errors' gem 'binding_of_caller' endconfig/environments/development.rbRails.application.configure do ... # bulletの設定 config.after_initialize do Bullet.enable = true Bullet.bullet_logger = true Bullet.console = true Bullet.rails_logger = true Bullet.add_footer = true end endリンク
フォーマッター
Rails Best PracticesとRubocopの導入
Gemfilegroup :development do # 以下2行を追加 gem 'rails_best_practices' gem 'rubocop', require: false endカスタマイズする場合、
.rubocop.yml
でオーバーライドする。.rubocop.yml# This file overrides https://github.com/bbatsov/rubocop/blob/master/config/default.yml AllCops: Exclude: - 'tmp/**/*' - 'vendor/**/*' - 'db/**/*' - 'bin/**/*' - 'spec/**/*' - 'node_modules/**/*' DisplayCopNames: true # 日本語でのコメントを許可 Style/AsciiComments: Enabled: false # Admin::BaseControllerのような書き方を許可 Style/ClassAndModuleChildren: Enabled: false # frozen_string_literal: trueはなくていい Style/FrozenStringLiteralComment: Enabled: false # each_key, value, transform_keys, valueを使用する Style/HashEachMethods: Enabled: true Style/HashTransformKeys: Enabled: true Style/HashTransformValues: Enabled: true # クラスにコメントを残さない Style/Documentation: Enabled: false # コントローラのメソッド名に「set_」「get_」を許可 Naming/AccessorMethodName: Exclude: - "app/controllers/**/*" # 一行の長さは100字まで。コメントは制限しない Metrics/LineLength: Max: 100 IgnoredPatterns: ['\A#'] Exclude: - "db/migrate/*.rb" # メソッドの行数を20行までにする Metrics/MethodLength: CountComments: false Max: 20 # ABC sizeは緩めにする Metrics/AbcSize: Max: 30 # default 15ついでに
bundle exec rubocop -a
で自動整形しておく。ESlintの導入
$ yarn add -D eslint eslint-loaderconfig/webpack/loaders/eslint.jsmodule.exports = { test: /\.js$/, loader: "eslint-loader", enforce: "pre", options: {}, };config/webpack/environment.jsconst { environment } = require("@rails/webpacker"); const eslint = require("./loaders/eslint"); // 追加 environment.loaders.append("eslint", eslint); // 追加 module.exports = environment;$ yarn run eslint --init ✔ How would you like to use ESLint? · problems ✔ What type of modules does your project use? · commonjs ✔ Which framework does your project use? · none ✔ Does your project use TypeScript? · No / Yes ✔ Where does your code run? · browser ✔ What format do you want your config file to be in? · JSON Successfully created .eslintrc.json file in /Users/k_end/study/rails_app ✨ Done in 92.50s.なんとなく読みながらオプションを選んでいくと
.eslintrc.json
が生成される。.eslintrc.json{ "env": { "browser": true, "commonjs": true, "es2021": true }, "extends": "eslint:recommended", "parserOptions": { "ecmaVersion": 12 }, "rules": { } }これでWebpackerのコンパイル時にESlintが走るようになる。
bin/webpack-dev-server
で確認。
yarn run eslint --fix
でESlint自動修正。リンク
RSpec, FactoryBot
test/
ディレクトリは削除する。Gemfilegroup :development, :test do # 以下2行を追加 gem "rspec-rails" gem "factory_bot_rails" end
bundle exec rails generate rspec:install
でファイルが生成される。spec/rails_helper.rb# This file is copied to spec/ when you run 'rails generate rspec:install' require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../config/environment', __dir__) # Prevent database truncation if the environment is production abort("The Rails environment is running in production mode!") if Rails.env.production? require 'factory_bot' # 追加 require 'rspec/rails' Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } # コメントアウト begin ActiveRecord::Migration.maintain_test_schema! rescue ActiveRecord::PendingMigrationError => e puts e.to_s.strip exit 1 end RSpec.configure do |config| config.use_transactional_fixtures = true config.infer_spec_type_from_file_location! config.include FactoryBot::Syntax::Methods # 追加 end
spec/spec_helper.rb
のconfig.filter_run_when_matching :focus
をコメントアウトする。.rspec--require rails_helper --format documentation
- rails_helperでspec_helperを読み込んでいる
- 素のRubyファイルをテストすることはまずない
という点から、
--require rails_helper
に変更しておく。
これにより、それぞれのspecファイルでrequire rails_helper
を付けなくてもよくなる。config/application.rbmodule RailsApp class Application < Rails::Application ... # generateで作成するファイルの制限 config.generators do |g| g.assets false g.skip_routes true g.helper false g.test_framework :rspec, view_specs: false, helper_specs: false, routing_specs: false, controller_specs: false, request_specs: true, model_spec: true, fixtures: true g.fixture_replacement :factory_bot, dir: 'spec/factories' end end endここのtrue or falseは必要に応じて変える。
リンク
seed_fu
Gemfilegem 'seed-fu'seed-fuが読み込むのは
db/fixtures/
配下のファイルなので、fixtures/
ディレクトリを作成しておく。リンク
foreman
Gemfilegroup :development do gem 'foreman' # 追加 endProcfilerails: rails s --port=3000 webpacker: bin/webpack-dev-server$ bundle exec foreman check valid procfile detected (rails, webpacker) $ bundle exec foreman startリンク
slim
Gemfilegem 'slim-rails' gem 'html2slim'
bundle exec erb2slim app/views app/views -d
で置換する。ERB 2 SLIMを使うのもあり。
置換したらhtml2slim
は不要なので削除する。config/application.rbmodule RailsApp class Application < Rails::Application ... config.generators do |g| ... g.template_engine = :slim # 追加 end end endリンク