- 投稿日:2021-03-21T23:30:03+09:00
【Rails】現在使用しているgemの中身を見る方法
gemの中身を見たい意図
- Rubyの勉強のため、gemの中身を見てみたい。
- でも中の見方がわからない。GitHub上で見ても、個別のファイルごとになっているので見辛い。エディタで表示されるように見たい。
バージョンの状況
- ruby 3.0.0
- rails 6.1.3
- homebrewをインストール済
今回勉強するために見たかったgem
結論
% bundle open gem名
見るまでにエラーが出た?解消までの経緯(参考)
まずは準備(Railsアプリ上で、見たいgemをインストール)
Gemfilegem 'gimei'terminal% bundle install
カレントディレクトリにて、実行したところエラー発生
⚠️開きたいなら、エディターをセットしてね!
terminal% bundle open gimei To open a bundled gem, set $EDITOR or $BUNDLER_EDITOR解決策
Homebrew-cask
と呼ばれるmacのGUIをコマンドでインストール出来る拡張機能を使った。Homebrew-cask
内にあるsublime-text
というエディターをインストールし、環境変数に設定したところopenコマンドで見られるようになった!terminal# (ホームディレクトリに移動して)tapコマンドで、caskを追加 % brew tap homebrew/cask # brew内に、sublime-textがあるか探す・・ % brew search subl => Casks subler sublercli sublime-merge sublime-text # sublime-textをインストール % brew install sublime-text # 環境変数に設定 % export EDITOR='subl -w' # (gimeiをインストールしていたアプリに移動して) % bundle open gimeiすごくコードが綺麗?
また複数のクラスがあるRubyコードを見たのが初めてだった。
(やっと見れるようになったので、勉強のため詳細はこれから見ようと思います!!)
見るまでに戸惑ったので、誰かの役に立てば幸いです。
誤っている部分などありましたら教えてください?♀️
- 投稿日:2021-03-21T22:34:50+09:00
Railsのコントローラー上で.envを使った環境変数を読み込めなかった時の対応
実現したいこと:
Railsのコントローラー上で、
.envのファイルに設定した環境変数を読み込んでAPIを取得したい。環境:
Ruby 2.6.6
Rails 6.0.3.4
gemのdotenv-railsをインストール済状況:
Ruby-on-RailsでSNSのアプリケーションを作成中にNewsApiを使用し、
Newsの情報を取得し表示する機能を実装していた。
APIKEYを.envファイルにて環境変数に置き換えて使用したかったが、
エラーが発生して読み込めなかった。ニュース機能の実装で参考にした記事:
https://qiita.com/UTOG/items/f6438420e81b6488a508
上記執筆者様の実装方法を参考にNewsApiへ登録し、
APIKEYを取得し環境変数として設定後、記載されている実装コードを活用しファイル作成。(ニュースカテゴリー等の設定は変更)対象ファイル:
app/controller/news_Controller.rbclass NewsController < ApplicationController def index end def data uri = URI.parse('http://newsapi.org/v2/top-headlines?country=jp&category=business&pageSize=15&apiKey=<%="#{ENV['API_KEY']}"%>') json = Net::HTTP.get(uri) moments = JSON.parse(json) @data = moments['articles'].to_json end end.envAPI_KEY='この中に取得したAPI_KEYを入力'上記コードでは下記のようなエラーが発生。
エラー文:
syntax error, unexpected tCONSTANT, expecting ')'
...ze=15&apiKey=<%="#{ENV['API_KEY']}"%>')
... ^~~~~~~
/app/controllers/news_controller.rb:6: syntax error, unexpected ')', expecting end
...iKey=<%="#{ENV['API_KEY']}"%>')
調べたところ閉じタグがないと警告が出ており、
どうやら環境変数が読み込めていないため、
そこでコードの読み込みが止まってしまっているようあった。試したこと:
1.環境変数を挿入していた該当のURLに取得したAPIKEYをベタ打ちで挿入
→ニュースが問題なく表示される。2.コンソール上で環境変数を実行( 実行コード:
$ ENV['API_KEY']
)
→.env内に記載していたAPIKEYが問題なく表示される。→この時点で、
①ニュースを表示すること
②.env内での環境変数の設定はできていると予想。
コントローラーへの環境変数の組み込み方に問題があるのではと仮定。2.環境変数の挿入方法を変更
(news.controller.rb 6行目を下記のパターンで変更 ※対象箇所周辺コードのみ抜粋)country=jp&category=business&pageSize=15&apiKey=<%="#{ENV['API_KEY']}"%>') country=jp&category=business&pageSize=15&apiKey=<%=ENV['API_KEY']%>') country=jp&category=business&pageSize=15&apiKey=<"#{ENV['API_KEY']}"') country=jp&category=business&pageSize=15&apiKey=ENV['API_KEY']')→検索しながら上記色々なパターンを実行したものの、エラー等で読み込めない状況は変わらず。。
原因:
<% %>や<%= %>の記述はerbファイル内で使える記述であり、
erb上でRubyコードを実行したり、Rubyで定義した変数などをHTMLとして出力したりする際に利用するとのことであり、コントローラー内では記述方法は異なるとのこと。解決策:
下記、コードを修正。
ダブルクォーテーション(")とシングルクォーテーション(')の使い方にも間違いがあった模様。app/controller/news_Controller.rbclass NewsController < ApplicationController def index end def data uri = URI.parse("http://newsapi.org/v2/top-headlines?country=jp&category=business&pageSize=15&apiKey=#{ENV['API_KEY']}") json = Net::HTTP.get(uri) moments = JSON.parse(json) @data = moments['articles'].to_json end end今回、エラーにハマっていたところを質問サイトにて回答を頂いたため、
同じ状況の方のご参考になればと思い、共有させて頂きます。まだまだ未熟なため説明不足な点もございますが、
今後修正等加えて参りますので気になる点がございましたらぜひ、
ご指導、ご鞭撻のほどよろしくお願いいたします。
- 投稿日:2021-03-21T22:06:51+09:00
Tips: Rubyでresponse bodyをstreamで受け取ってNoMemoryErrorを回避する
RubyやRailsなどでHTTPリクエストを行う場合に、response bodyをstreamで受け取る方法を紹介します。
単純にリクエストをするとレスポンスの結果を全てメモリに載せてしまうので、メモリの節約や巨大なデータを取得するとNoMemoryError
が発生してしまいます。
今回の手法はこのエラーになってしまう状態を回避する方法として有効です。Net::HTTPの場合
にある通り、
read_body
というメソッドを用いることでstreamでデータの受け取りを行うことができます。ファイルに書き出すことでメモリを圧迫せずにデータを取得できます。require 'net/http' uri = URI.parse('http://example.com/') Net::HTTP.start(uri.host, uri.port) do |http| http.request_get(uri.path) do |response| File.open("file_path", "w") do |file| response.read_body do |chunk| file.write(chunk) end end end endまた、streamで取得したデータの累計サイズを記録しておくことで、特定のサイズでデータの取得を打ち切るようなこともできます。
require 'net/http' uri = URI.parse('http://example.com/') response_body = '' total_size = 0 Net::HTTP.start(uri.host, uri.port) do |http| http.request_get(uri.path) do |response| response.read_body do |chunk| response_body += chunk if total_size <= 1000000 # 1Mバイトまでのデータまで受け取る total_size += chunk.bytesize end end endFaradayの場合
にある通り、
on_data
というオプションにprocを渡すことでread_body
と同じようなことができます(このオプションが使えるのはNet::HTTP
をアダプタにしている場合のみです)require 'faraday' connection = Faraday.new(url: 'http://example.com/') response_body = '' connection.get('/') do |request| request.options.on_data = proc do |chunk, overall_received_bytes| puts "Received #{overall_received_bytes} characters" response_body += chunk end endまた、
Net::HTTP
と同じようにファイルに書き出すこともできますし、切り捨ても行えます。require 'faraday' connection = Faraday.new(url: 'http://example.com/') connection.get('/') do |request| request.options.on_data = proc do |chunk, overall_received_bytes| puts "Received #{overall_received_bytes} characters" File.open("file_path", "w") do |file| file.write(chunk) end end endrequire 'faraday' connection = Faraday.new(url: 'http://example.com/') response_body = '' connection.get('/') do |request| request.options.on_data = proc do |chunk, overall_received_bytes| puts "Received #{overall_received_bytes} characters" response_body += chunk if overall_received_bytes <= 1000000 # 1Mバイトまでのデータまで受け取る end end
- 投稿日:2021-03-21T21:17:41+09:00
RSpecデータリクエストを削減してテスト実行時間を削減した話
はじめに
私はエンジニアインターンで主にサーバーサイドの開発を担当させていただいています。
機能実装の際はRSpecでテストケースを書いてから実装していて、コミットする前に全体のテストを通してバグを見つけているのですが
実行時間が長い!
ということで、RSpecのリファクタリングを行いテストの実行時間を削減して見ましたので、一部紹介したいと思います。
1. 従来のRSpecでのデータリクエスト状況
現状、RSpecでは以下のように、
let
を使用してデータの作成を行っています。require 'spec_helper' describe User do let!(:user) { FactoryBot.create(:user) } it 'anything' do # userのテスト end it 'anything' do # userのテスト end it 'anything' do # userのテスト end endこれではexampleが3回行われる度に
User
モデルが作成されてしまう。
これをどうにか1回のレコード作成に留められないか...2. gem "test-prof"の導入
そこで
test-prof
を導入します。Gemfilegem "test-prof"bundle install変更後テストケース
require 'spec_helper' describe User do let_it_be(:user) { FactoryBot.create(:user) } it 'anything' do # userのテスト end it 'anything' do # userのテスト end it 'anything' do # userのテスト end endこのようにtest-profは
let_it_be
というヘルパーメソッドを提供してくれるgemになります。そうするとRailsのトランザクションテスト機能を利用してレコードを最初に1回だけ作成して、テストが終了したら該当データを削除してくれるようになります。
3. ベンチマーク
変更したテストファイル数は全体の3割ほどですが、約1分のテスト実行時間の削減に繋がりました。
let_it_be使用前
let_it_be使用後
おわりに
画期的にテストの実行時間を削減できた訳ではありませんが、長期的に見て効果のある対処法なのではないかと思います。
参考
- 投稿日:2021-03-21T21:14:20+09:00
Railsチュートリアル10章まとめ
10.1 ユーザーを更新する
ユーザーを更新する行為は、新規ユーザーの作成に似ている。
アクション リクエストに応答 新規作成 new POSTに対してcreate 更新 edit PATCHに対してupdate 10.1.1編集フォーム
まずやるべきは、Usersコントローラーにeditアクションを追加し、それに対応するeditビューを実装。
ルーティングはresources :users
のおかげで有効になっている。Railsチュートリアル 表7.1を確認すると、ユーザー編集ページのURLは
/users/1/edit
となっている。
ここで、ユーザーidを取得するために用いるのが、params[:id]
paramとは、Railsで送られてきた値を取得するメソッドapp/controllers/users_controller.rbdef edit @user = User.find(params[:id]) endユーザーのeditアクション
app/views/users/edit.html.erb<% provide(:title, "Edit user") %> <h1>Update your profile</h1> <div class="row"> <div class="col-md-6 col-md-offset-3"> <%= form_with(model: @user, local: true) do |f| %> <%= render 'shared/error_messages' %> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> <%= f.label :email %> <%= f.email_field :email, class: 'form-control' %> <%= f.label :password %> <%= f.password_field :password, class: 'form-control' %> <%= f.label :password_confirmation, "Confirmation" %> <%= f.password_field :password_confirmation, class: 'form-control' %> <%= f.submit "Save changes", class: "btn btn-primary" %> <% end %> <div class="gravatar_edit"> <%= gravatar_for @user %> <a href="https://gravatar.com/emails" target="_blank">change</a> </div> </div> </div>ユーザーのeditビュー
ここでは、formの部分で、大部分がユーザー作成画面とかぶっているので、パーシャルでまとめるのが良い。また、@userインスタンス変数を使って、idを取得し編集ページを表示している。
HTML<form accept-charset="UTF-8" action="/users/1" class="edit_user" id="edit_user_1" method="post"> <input name="_method" type="hidden" value="patch" /> . . . </form>WebブラウザではそのままではPATCHリクエストを送信できない。
そこで以下のコードで「偽装」している。<input name="_method" type="hidden" value="patch" />リスト 10.2のform_with(@user)のコードは、リスト 7.15のコードと完全に同じである。
ここでは、Active Record
のnew_record
論理値メソッドでPOSTリクエストとPATCHリクエストを区別している。$ rails console >> User.new.new_record? => true >> User.first.new_record? => falsetrue→POST
false→PATCH最後に、ナビゲーションのリンクを実装
<%= link_to "Settings", edit_user_path(current_user) %>
edit_user_path
もUsersリソースのおかげで使用可能。
current_userはヘルパーメソッド(9章で実装)10.1.2 編集の失敗
ゴールはupdateメソッドの実装。
app/controllers/users_controller.rbdef update @user = User.find(params[:id]) if @user.update(user_params) # 更新に成功した場合を扱う。 else render 'edit' end end抑えておきたいのは、updateの呼び出しにuser_paramsを使っている点。
これはStrong Parameters
というテクニックuser_paramsメソッドはx Usersコントローラー内部でのみ実行され、Web経由で外部ユーザーに晒される心配はなし。属性の許可を制限することで管理者権限を乗っ取られることを防ぐ。
(詳しくは7.3.2参照)private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation) end end10.1.3 編集失敗時のテスト
統合テストを行う
$ rails generate integration_test users_edit invoke test_unit create test/integration/users_edit_test.rbコマンドで統合テストを生成
まずは、編集失敗時のテストから。
流れとしては、編集ページにアクセス→editビューが描画されるか確認→無効な情報を送信→再度editビューが描画されるtest/integration/users_edit_test.rbrequire 'test_helper' class UsersEditTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) end test "unsuccessful edit" do get edit_user_path(@user) assert_template 'users/edit' patch user_path(@user), params: { user: { name: "", email: "foo@invalid", password: "foo", password_confirmation: "bar" } } assert_template 'users/edit' end endここでPATCHリクエストを送るために
patchメソッド
を使用している。
これはget
,post
メソッド等と同様に、HTTPリクエストを送るためのもの。
(HTTPリクエストとは、クライアント側からWebサーバーにリクエストする際送信するもの)
- 投稿日:2021-03-21T21:03:46+09:00
ActiveModelに対してエラーメッセージ日本語化 ja.yml書き方
投稿記事にタグ付けをするため、1つのフォーム送信で複数のモデルを更新できるというFormオブジェクトを使用しました。
app/models/posts_tag.rbclass PostsTag include ActiveModel::Model attr_accessor :title,:text,:answer,:user_id,:image, :name with_options presence: true do validates :title validates :text validates :name end def save post = Post.create(title: title,text: text,answer: answer,user_id: user_id,image: image) tag = Tag.where(name: name).first_or_initialize tag.save PostTagRelation.create(post_id: post.id, tag_id: tag.id) end endそして投稿時にエラーが発生した際に日本語でエラーメッセージが表示されるようにja.ymlを作成したのですが、英語から日本語に変換してくれませんでした。><
↓はダメだった書き方です。config/locales/ja.ymlja: activerecord: attributes: user: nickname: ニックネーム post: title: 投稿タイトル text: 投稿内容 image: 画像 name: タグ名そこから下記のように修正したところ日本語に変換してくれました!
config/locales/ja.ymlja: activerecord: attributes: user: nickname: ニックネーム activemodel: attributes: posts_tag: title: 投稿タイトル text: 投稿内容 image: 画像 name: タグ名activerecordとactivemodelの違いも分かっていないプログラミング初学者ですが、
とても良い経験となりました。おわり
- 投稿日:2021-03-21T18:30:00+09:00
RubyをMacにインストールするときのエラー
はじめに
Rubyの勉強がしたいと思い、MacbookAirにRubyをインストールしようとしたときの試行錯誤の備忘録です。
Macには標準でRubyがインストールされているのですが、Rubyの参考書を進めていくうちに権限の問題で追加したいライブラリを追加できない。
自身の手でMacにRubyをインストールすれば、権限問題は解消するそうです。rbenvのインストール
Rubyをインストールするまでの道のりはざっくり4段階あります。
1. Xcodeインストール
2. Homebrewインストール
3. rbenvインストール
4. Rubyインストール1と2はなんとかできた。
しかし3でエラーが出始める。Permission denied @ dir_s_mkdir - /private/tmp/homebrew...
brew install rbenvを実行するとエラー出現。
なにこれ?と思いコピーしてGoogle検索するとprivate/tmpフォルダの権限不足でrootユーザしか書き込みできない。ls -lコマンドで確認すると確かにそうなっている。
こちらのサイトによると
sudo chown -R 'username'/private/tmp/
で解決できるとのこと。Thank you.Interrupted system call @ dir_initialize - /usr/local/Cellar/rbenv/1.1.2
つぎに出たエラー。グーグルで検索してもよくわからない。
とりあえずターミナルを再起動して再度brew install rbenvを実行するとエラーはなくrbenvのインストールに成功した。BUILD FAILED
rbenv install 3.0.0を実行するとエラーが出る。
Installing ruby-3.0.0...
ruby-build: using readline from homebrew
BUILD FAILED (macOS 11.0.1 using ruby-build 20210309)
こちらのページによるとcurlとopensslが古いバージョンのため。らしいとのことなので対策する。
対策でやったこと。
・opensslとcurlがinstallされていなかったので再インストール
・opensslとcurlがanaconda3のPATHだったので.bash_profileからPATHを削除して/usr/bin/配下のopensslとcurlに通す。インストール成功
rbenv install 3.0.0を再度実行するもまたしてもBUILD FAILEDが出る。
ならばRubyのバージョンを変えてみたらどうか、と思いrbenv install 2.7.2を実行するとなんと成功。
Windowsばかり使ってきていたので今回PATHやシェルの勉強を予期せずできてよかった。Rubyがんばるぞー。
- 投稿日:2021-03-21T17:48:41+09:00
【Rails】 dependent: :destroy とは
どんな機能なの?
結論から言うと、dependent: :destroyを使いことによって
親モデルのレコードを削除する際に、それに紐づく子モデルのレコードも同時に削除されます。具体的な使い方
dependent: :destroyはモデルのアソシエーションで使います。
例えば下記のようにユーザーとマイクロポストのアソシエーションを定義します。user.rbhas_many :mictropostsこれだけではユーザーが退会した時、そのユーザーのマイクロポストは残ってしまいます。
そのような場合に下記のようにdependent: :destroyを追加します。user.rbhas_many :mictroposts, dependent: :destroyこうすることでユーザー退会時には、そのユーザーのマイクロポストも同時に削除されます。
最後に
この機能は他に、いいね機能(いいねした投稿、された投稿が削除された場合、LikeModelのレコードも削除する。)やフォロー機能(フォローしたユーザー、されたユーザーが削除された場合、RelationshipModelのレコードも削除する。)など、アソシエーションをいじる場面でよく出てくるので必ず覚えておきたいですね!
また基本、応用関係なくなるほどと思ったことについて日記感覚で投稿していきます!
ありがとうございました!
- 投稿日:2021-03-21T17:42:35+09:00
RubyとRailsの個人的によく使うメソッドをまとめてみた
今回はタイトルにもある通り、個人的によく使うメソッドをまとめてみました。
初学者なので間違いがあれば指摘していただけると嬉しいです。そもそもメソッドとは?
メソッド = 処理。
- 自分で作るメソッド
- Rubyがあらかじめ用意してくれているメソッド
のふたつがある。
今回はRubyがあらかじめ用意してくれている便利メソッドを紹介します。putsメソッド
ターミナルに値を出力するメソッド。putsの後に値を記述することで出力できる。
puts "Helloworld" => Helloworldgetsメソッド
ターミナルに値の入力機能を起動するメソッド。入力された値は文字列としてプログラムに渡される。
また文字列として扱う際、getsで取得した値の後は、出力の際に改行され、gets.to_iで数値として扱う場合は改行されない。name = gets puts "こんにちわ、" + name + "さん!" => 好きな文字列を入力する(今回は太郎) => こんにちわ、太郎 さん!上記の通り、このままだと改行がされてしまうのでそんな時はchompメソッドを合わせて使うと良い。
chompメソッド
文字列の末尾に存在する改行を取り除くメソッド。
name = gets.chomp puts "こんにちわ、" + name + "さん!" => 好きな文字列を入力する(今回も太郎) => こんにちは、太郎さん!となって改行されるのを防いでくれる。
lengthメソッド(文字列)
文字列の文字数を数えるメソッド。その際、半角スペースも文字数として数えられる。
出力する際は数値として出力される。
a = "Helloworld".length puts a => 10ちなみにこんな感じで配列にくっつければ要素数を数えてくれる。
a = ["Hello","World"].length puts a => 2to_sメソッド
整数 → 文字列に変換するメソッド。
通常、整数(Integer)型と文字列(String)型による足し算はできないが、こうして型を換えることで可能になる。puts 20.to_s + "歳" => 20歳ただ、下記のように文字列に対して掛け算をすることは整数(Integer)型に変換しなくても可能。
puts "歳" * 10 => 歳歳歳歳歳歳歳歳歳歳歳to_iメソッド
文字列(String) → 整数(Integer)に変換するメソッド。
a = "10".to_i puts 20 + a => 30ちなみに文字列をto_iで変換し、整数型と四則演算すると、全て0として変換されるらしい。
冷静に考えたら当たり前なのだが、最近まで知らなかった。理想↓↓
a = "歳".to_i puts 20 + a => 20歳現実↓↓
a = "歳".to_i puts 20 + a => 20getsメソッドと合わせて使うと応用が効いて便利。
ちなみにgetsのsはstring(文字列)型のsらしいです。
(複数形だと思ってたなんて口が裂けても言えない....)input = gets.to_i puts 100 + input => 好きな数値を入力(今回は100を入力する) 200その他類似の変換系メソッド
個人的にはまだ活用できていないが、使い方を理解できると便利であろう変換系のメソッド。
メソッド 効果 to_f Floatクラス(浮動小数点数)に変換 to_sym シンボルに変換 to_h ハッシュオブジェクトに変換 to_a 配列オブジェクトに変換 requireメソッド
外部ファイルを読み込むためのメソッド。require "外部ファイル名"で読み込める。
ただしカレントディレクトリから読み込む場合はrequire "./外部ファイル名"で読み込む。日付や時間を取得する際に便利なメソッド
Dateクラス
Rubyの標準ライブラリの機能で日付を扱うためのクラスのこと。
require "date"という一文をコード内に記述することで使用できる。todayメソッド
本日の日付を取得するメソッド。
例)Date.today 今日の日付を取得するwdayメソッド
0~6の数値で曜日を取得するメソッド。
0:日曜日、1:月曜日、2:火曜日、3:水曜日、4:木曜日、5:金曜日、6:土曜日を表す。例)Date.today.wday 今日の曜日を数値で取得する
strftimeメソッド
日時データを指定したフォーマットで文字列に変換するメソッド。
例)message.created_at.strftime("%Y年%m月%d日 %H時%M分") 保存された日時を文字列で取得する
eachメソッド
配列や範囲オブジェクトなどで用意されているメソッドであり、オブジェクトに含まれている要素を順に取り出し、変数に格納します。
オブジェクト.each do |変数| 実行する処理1 実行する処理2 end↓↓↓↓
@posts = Post.all だとここでは認識しておいてください。
<% @posts.each do |post| %> タイトル:<% post.title %> 投稿者:<% post.user %> 投稿内容:<% post.product %> <% end %>each_with_indexメソッド
each(要素の繰り返し処理)と同時に、その要素が何番目に処理されたかを表すメソッド。デフォルトだと処理番号は0から割り当てられる。
僕はランキング機能を作成するさいに用いました。オブジェクト.each.with_index do |変数1,変数2| 実行する処理1 実行する処理2 end↓↓↓↓
<% @posts.each.with_index(1) do |post, i| %> 第<%= i %>位 <% post.title %> <% end %>@postsの中身と指定した数字(1)が |post, i|にそれぞれ格納され、「第◯位」と「投稿のタイトル」に割り振られる。
include?メソッド
指定した要素が配列や文字列内に含まれているかを判定するメソッド。
number = [100, 200, 300 , 400 , 500] puts number.include?(200) => truesplitメソッド
指定した区切り文字で対象となる文字列を分割して配列にする。
fruit = "apple,strawberry,grape,banana" puts fruit.split(',') => ["apple", "strawberry", "grape", "banana"]sliceメソッド
配列や文字列から指定した要素を取り出すことができるメソッド。
文字列の要素を指定する際は数字を用い、先頭の文字列は0から指定する。また第二引数として、取り出す要素の数も指定したい場合は指定することもできる。number = [100, 200, 300 , 400 , 500] puts number.slice(3,2) => [400 , 500]エクスクラメーションマーク(!)
末尾につけることにより破壊的メソッドになり、もとの配列や文字列を変化させるメソッド。
scanメソッド
対象の要素から引数で指定した文字列を数え、配列として返すメソッド。
puts "ワン!ワンッ!ワンワンッ!".scan("ワ") => [ワ, ワ, ワ, ワ]lengthと組み合わせると含まれている"ワ"の数で返ってくる。
puts "ワン!ワンッ!ワンワン!".scan("ワ").length => 4ただ、下記にcountというメソッドもあるのでそっちの方が使いやすい。
countメソッド
特定の文字列の中に指定した文字列がいくつ含まれているかを数えたり、配列の要素数を数えるメソッド。
puts "ワン!ワンッ!ワンワン!".count("ワ") => 4firstメソッド
配列から最初の要素を取得するメソッド。
引数がある場合は配列の最初の要素からその引数分の要素を配列で取得するname = ["太朗", "花子", "二郎"] puts name.first(2) => ["太朗", "花子"]lastメソッド
配列から最後の要素を取得するメソッド。
引数がある場合は配列の最後の要素からその引数分の要素を配列で取得するname = ["太朗", "花子", "二郎"] puts name.last(2) => ["花子", "二郎"]sortメソッド
配列の要素を一定の規則(アルファベット、数値の降順、昇順など)で並び替えるメソッド。
fruit = ["apple", "strawberry", "grape", "banana"] puts fruit.sort => ["apple", "banana", "grape", "strawberry"]joinメソッド
配列内の要素と要素を連結させるメソッド。
引数を渡すことで区切ることもできる。fruit = ["apple", "strawberry", "grape", "banana"] puts fruit.join(",") => apple,strawberry,grape,bananapushメソッド
配列の末尾に要素を連結する
fruit = ["apple", "strawberry", "grape", "banana"] puts fruit.push("orange") => ["apple", "strawberry", "grape", "banana","orange"]unshiftメソッド
配列の先頭に要素を追加する。
fruit = ["apple", "strawberry", "grape", "banana"] puts fruit.unshift("orange") => ["orange", "apple", "strawberry", "grape", "banana"]shiftメソッド
配列の先頭の要素を削除する。または配列の先頭の要素を取り出す。
fruit = ["apple", "strawberry", "grape", "banana"] puts fruit.shift => ["Apple"]pluckメソッド
引数に指定したカラムの配列を返す(Railsのメソッド)
#Fruitモデルのnameカラムに "Apple" "grape" "banana" が入っている場合 => Fruit.pluck(:name) => ["Apple","grape","banana"]最後に
まだまだ足りないメソッドだらけで、適切に使えているかどうかも定かではありませんが、使える技が増えればそれだけ自分の中のアイデアを形にすることができると思います。
また、思い付いたらこれから追加していく予定です。
誰かの手助けになれればいいなと思います。
間違いや指摘があればコメントに残していただけると幸いです。
- 投稿日:2021-03-21T17:15:05+09:00
/dev/loopに容量が圧迫されてrails testができない問題...
cloud9のterminalでrails testを実行しようとしたら何と12ものエラーが...
備忘録として、またその他どなたかのお役に立てればと思い、記事を書いていきます。
キャプチャを失念しており、ほとんど文章での説明になりわかりにくいかと思いますが、ご容赦のほどお願いいたします。
では、書いていきます!【1.状況】
AWSでrails testの実行時に12ものエラーが発生し、以下のメッセージが登場。
⇒ Error:「No spacd left on device」
【2.状況分析】
→ 上記1.について色々調べていくと、どうにも容量不足のようです。容量不足とは、主に以下2つのいずれかを指します。
① ディスク容量の不足
② 「inode」の容量不足ここで、「inode」とは要するに、ファイル情報(誰が、いつetc...などのプロパティ的な
情報)を管理するためのデータであるとのこと。従って、この2つの内、どちらが原因であるのかを見極めることが必要です。
それぞれ、以下に示すコマンドをterminalで実行すれば、容量が確認できます。
・ ①の場合
2-1) $ df
・ ②の場合
2-2) $ df -i
その結果、私の場合、②のパターンであることが分かりました。内容を見ていくと、以下5つのディレクトリが使用率100%と判明。。。
・/dev/xvda1
・/dev/loop1
・/dev/loop2
・/dev/loop3
・/dev/loop4と分かれば、これらディレクトリを消去すればよいことになります。
【3.対策】
ターミナルで以下コマンドを実行すれば、ディレクトリを消去できます。$ sudo rm -d ディレクトリ名
今回の場合、/dev以下の階層を消去すれば良いので、
3-1) $ sudo rm -d /dev
を実行。 ※ rmはremove、dは(おそらく)ディレクトリの略これで、完了…と思いきや/devに格納されている全部のファイルに
以下のエラー発生。
Error:Operation not Permittedこの事象について調べていくと、どうにも上記2.の/devディレクトリに
ファイルを実行する権限が与えられていないことが原因であるとのこと。そこで、/devディレクトリにファイルの実行権限を与える操作を行います。
そのためのコマンドを以下示します。
$ sudo chmod モード ファイル名(ディレクトリ名)ここでいう、モードとは3桁の数字abcであるとのこと。
a:「所有者」の権限
b:「所有グループ」の権限
c:「その他」ここで、abcの各桁には以下数字の合計値が入ります。
モード(数字) モード(アルファベット) 権限
4 r 読み取り
2 w 書き込み
1 x 実行つまり、実行だけが必要なら1、読み取りと実行が必要なら4+1=5、
何も必要なければ、0が入ります。今回は、「所有者」と「その他」に全機能を付与したかったので、707としました。
従って、以下3-2)のコマンドをターミナルで実行しました。
3-2) $ sudo chmod 707 /devそして、再び3-1)を実行した後に2-1)を実行し、
フォルダ内を確認します。以下の画像のように/devが消去され、容量が開放されたと思われます。
エラーがなくなり、晴れて問題が解消されました。
以上となります、イメージがつきにくかったかもしれませんが、ご参考になりますと幸いです。
それでは、また!参照先
https://qiita.com/shisama/items/5f4c4fa768642aad9e06
https://mem-archive.com/2019/07/28/post-1976/
https://itojisan.xyz/trouble/15772/#2_inode
https://www.souichi.club/aws/out-of-disk-space/
- 投稿日:2021-03-21T16:50:35+09:00
【Rails】古いデータベースが影響してエラーが出た話
概要
以前作成したRailsアプリを削除して、再び同じ名前で同様のアプリ作成しました。
そしてrails db:migrate
実行後、ActiveRecord::PendingMigrationError
が発生した。結論から言うと、過去アプリのデータベースが残っており
作成したアプリ上のdb/migrateディレクトリ内
のファイルをコマンドdb:migrate
にて反映させようとした際、ファイルのバージョンが異なるためエラーが発生しました。
開発環境
・データベース:PostgreSQL
・railsのバージョン:6.1.3
・PC:macbook proエラー発生から解決までの流れ
- 元々あったrailsアプリを削除する。(rails db:create,rails db migrate実行済み)
- 元々あったrailsアプリと同じ名前のrailsアプリを再び作成する。(rails db:create実行済み)
rails db:migrate
を実行後、rails s
にてサーバを立ち上げてブラウザを見ると、ActiveRecord::PendingMigrationError
が発生する。rails db:version
を実行すると、terminal上のファイルとアプリmigrationファイル(db/migrate)のバージョンが異なる。rails db:reset
を実行してrails db:migrate
を行うと、問題なくアプリケーションを実行できる。
また、rails db:version
にてファイルを確認すると、terminal上とrailsアプリのmigrationファイルが一致していることが確認できた。rails db:migrate
を行ってアプリを起動してみると、問題なく動作した。![]()
エラーが発生した原因
原因は私の理解不足によるもので、アプリファイルを削除すると一緒にデータベースも消すことができると思っていたためです。
(アプリファイルとデータベースは、同一の場所にあると思っていた)
実際は、下記ディレクトリにデータベースが保存されています。
また、データベース削除とversion確認コマンドは、下記になります。PostgreSQL:… /usr/local/var/postgres 内
MySQL:… /usr/local/var/mysql 内データベース削除:
rails db:reset
(データベース内の情報は消えるので注意!)
データベースversion確認:rails db:version
最後に
正直なところ、データベースについてまだまだわかっていない点がたくさんあります。
もし間違っている点等がある場合、ご指摘頂けると大変ありがたいです。
最後まで読んで頂きありがとうございました。
- 投稿日:2021-03-21T15:37:59+09:00
投稿機能 統合テストの実装
今回ポートフォリオ作成中にでたエラーの解決策を備忘録も含め、同じところでつまづかれている方などいましたら、ご参考にして頂けましたら幸いです。
投稿機能では画像つきの機能を取り入れてまして、
でたエラーに関してが、Capybara::ElementNotFound: Unable to find field "post[images][]" that is not disabled from /Users/takuya/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/capybara-3.35.3/lib/capybara/node/finders.rb:303:in `block in synced_resolve'上記のエラーでした。
アウトプットの前に、
rspec
factory.bot
上記は導入済みで、進めさせていただきます。ちなみにかなり時間を取られました?
投稿機能統合テスト記述
RSpec.describe '写真テキスト投稿', type: :system do before do @user = FactoryBot.create(:user) @post_name = Faker::Lorem.sentence end context '写真テキスト投稿ができるとき'do it 'ログインしたユーザーは新規投稿できる' do # トップページに移動する visit root_path # トップページにログインページへ遷移するボタンがあることを確認する expect(page).to have_content('LOGIN') # ログインページへ遷移する visit new_user_session_path # 正しいユーザー情報を入力する fill_in 'Eメール', with: @user.email fill_in 'パスワード', with: @user.password # ログインボタンを押す find('input[name="commit"]').click # トップページへ遷移することを確認する expect(current_path).to eq(root_path) # 写真投稿一覧ページに移動する visit posts_path # 新規投稿ページへのリンクがあることを確認する expect(page).to have_content('PUSH 投稿') # 投稿ページに移動する visit new_post_path # フォームに情報を入力する fill_in 'post[images][]', with: "public/images/test_image.jpg" fill_in 'post[name]', with: @post_name # 送信するとPostモデルのカウントが1上がることを確認する expect{ find('input[name="commit"]').click }.to change { Post.count }.by(1) # 写真投稿一覧ページに移動する visit posts_path # 写真投稿一覧ページには先ほど投稿した内容の写真テキストが存在することを確認する(画像) expect(page).to have_selector("img[src$='test_image.png']") # 写真投稿一覧ぺージには先ほど投稿した内容の写真テキストが存在することを確認する(テキスト) expect(page).to have_content(@post_name) end end context '写真投稿ができないとき'do it 'ログインしていないと新規投稿ページに遷移できない' do # 写真投稿一覧ページに移動する visit posts_path # 新規投稿ページへのリンクがない expect(page).to have_no_content('nPUSH 投稿') end end end
fill_in 'post[images][]', with: "public/images/test_image.jpg"
の上にbinding.pry
を入れて、上記コードを入力すると画像が挿入できない状態でした。要素中にinputタグのname要素を入れ込んでいるのになぜエラーが出るのかと四苦八苦していました。
一度頭を整理して、
fill_in
意外にも画像挿入する方法はないかと調べたところ、
attach_file
というメソットが引っかかりました。
そこで
fill_in
を削除してattach_file
メソットの記述を行いました。変更前
# フォームに情報を入力する fill_in 'post[images][]', with: "public/images/test_image.jpg" fill_in 'post[name]', with: @post_name変更後
# フォームに情報を入力する attach_file('post[images][]', image_path, make_visible: true) fill_in 'post[name]', with: @post_name上記を記述変更を行い、今すぐにでも実装を行いたかったのですが、焦ってはいけませんでした
変更後の記述の中に
image_path
を代入していることから、
フォームに情報を入力する
の統合テストを行う前に、添付する画像を定義する記述を行いました。
そうしないとなんの画像を指定しているのかわからないためですそして、
# 添付する画像を定義する image_path = Rails.root.join('public/test_image.png') # フォームに情報を入力する attach_file('post[images][]', image_path, make_visible: true) fill_in 'post[name]', with: @post_nameフォーム情報を入力するの前に、画像を定義する記述を行い、無事テストが行える状況になりました。
実装を行うと、問題なく統合テストを行うことができました
完成コード
RSpec.describe '写真テキスト投稿', type: :system do before do @user = FactoryBot.create(:user) @post_name = Faker::Lorem.sentence end context '写真テキスト投稿ができるとき'do it 'ログインしたユーザーは新規投稿できる' do # トップページに移動する visit root_path # トップページにログインページへ遷移するボタンがあることを確認する expect(page).to have_content('LOGIN') # ログインページへ遷移する visit new_user_session_path # 正しいユーザー情報を入力する fill_in 'Eメール', with: @user.email fill_in 'パスワード', with: @user.password # ログインボタンを押す find('input[name="commit"]').click # トップページへ遷移することを確認する expect(current_path).to eq(root_path) # 写真投稿一覧ページに移動する visit posts_path # 新規投稿ページへのリンクがあることを確認する expect(page).to have_content('PUSH 投稿') # 投稿ページに移動する visit new_post_path # 添付する画像を定義する image_path = Rails.root.join('public/test_image.png') # フォームに情報を入力する attach_file('post[images][]', image_path, make_visible: true) fill_in 'post[name]', with: @post_name # 送信するとPostモデルのカウントが1上がることを確認する expect{ find('input[name="commit"]').click }.to change { Post.count }.by(1) # 写真投稿一覧ページに移動する visit posts_path # 写真投稿一覧ページには先ほど投稿した内容の写真テキストが存在することを確認する(画像) expect(page).to have_selector("img[src$='test_image.png']") # 写真投稿一覧ぺージには先ほど投稿した内容の写真テキストが存在することを確認する(テキスト) expect(page).to have_content(@post_name) end end context '写真投稿ができないとき'do it 'ログインしていないと新規投稿ページに遷移できない' do # 写真投稿一覧ページに移動する visit posts_path # 新規投稿ページへのリンクがない expect(page).to have_no_content('nPUSH 投稿') end end end画像挿入するだけのことでしたがかなり時間を使ってしまいました。
冷静に頭を整理して、根本のところから他に定義するメソットはないのという発想で成功することができました。
もし似たような内容で詰まっている方などいましたら、ご参考にして頂けましたら幸いです。
宜しくお願いします!!
- 投稿日:2021-03-21T15:31:46+09:00
リンク先のを別タブで表示させる方法
はじめに
外部リンクを貼り付ける際
リンクから飛ぶと戻るのがめんどくさい!
他のサイトを見ると、別タブに表示してくれる
そっちの方が都合が良いと言うことで、
今回はそのことに付いて書いて行きます?参考サイト
実装
target: :_blank
と言うのをaタグ
なりlink_to
に記載します<%= link_to "SNS", "#",target: :_blank ,class: "burger-nav-link" %>こちらでも別タブで表示してはくれます。
ですが、いくつかサイトを見ると悪用
フィッシング詐欺
などと
強めのワードが目につきます。そこで
rel: "noopener noreferrer"
をつけると大丈夫みたいで。<%= link_to "SNS", "#",target: :_blank, rel: "noopener noreferrer",class: "burger-nav-link" %>これで対策できました! 笑
終わりに
些細なことでも疑問に思った点
解決した点など更新して行きます?
- 投稿日:2021-03-21T15:10:01+09:00
rails urlパス変更
コントローラー名とは違う命名でルーティングを指定したい!
そんなことが起きた時に使えるコマンドを紹介します。resourcesとネスト
Railsのルーティング記法の基本は、複数形のresourcesメソッドと単数形のresourceメソッドです。また、Railsのルーティングにはネストを含む多くのオプションがあり、自由度が飛躍的に高まっています。
始めに
resources :notifications, only: [:show]notificationコントローラーのshowアクションにと、ごく普通の記述です。
/notifications/:id
の部分を違う名前に変更したいと思い。
path
オプションを使用する。resources :notifications, only: [:show], :path => "articles"おわりに
些細なことでも疑問に思った点
解決した点など更新して行きます?
- 投稿日:2021-03-21T15:07:53+09:00
実はJrubyはgradleだけで管理できる
はじめに
Jruby覚えてますか?JRubyはまだ現役です。こういう言語を扱うと必ずと言っていいほど、「javaでいいじゃん」と言われます。確かにJRubyでできることはJVMでできることです。
現状ではRubyが好きな人がたまに使うといった感覚でしょうか。ですが、私はJrubyでJava開発のテストを書いてます。理由は生産性が高いからです。
この記事では普段Java使いのみなさんがJrubyで楽できるtipsを紹介します。
依存環境
- gradle
- Jruby
- jruby-gradle-plugin
- http://jruby-gradle.org/ これだけです。
ですが、全て意識なくていいです。管理はすべてgradleで行います。ここでは一旦、jrubyのコマンドも忘れてしまいましょう。
初期プロジェクトを立ち上げる
必要なのは2つのファイルだけです。
terminalmkdir sample cd sample nvim build.gradle #neovimはいいぞ nvim main.rbbuild.gradle/* * This is sample programs under the jruby. *@ak.f */ buildscript { repositories { jcenter() } dependencies { classpath 'com.github.jruby-gradle:jruby-gradle-plugin:2.0.0' classpath 'com.github.jruby-gradle:jruby-gradle-jar-plugin:2.0.0' classpath 'com.github.jengelman.gradle.plugins:shadow:5.0.0' } } apply plugin: 'com.github.jruby-gradle.jar' repositories { jcenter() ruby.gems() } dependencies { jrubyJar 'org.slf4j:slf4j-simple:1.7.12' jrubyJar "rubygems:colorize:0.7.7+" } jrubyJar { initScript "./main.rb" } task jrubyRun(type: Exec){ dependsOn jrubyJar workingDir "./build/libs" commandLine 'java', '-jar', jrubyJar.outputs.files.singleFile.absolutePath }main.rbrequire 'colorize' java_import 'org.slf4j.Logger' java_import 'org.slf4j.LoggerFactory' logger = LoggerFactory.getLogger('demo') puts "-" * 20 logger.info "Ruby version: #{RUBY_VERSION}" logger.info "Ruby platform: #{RUBY_PLATFORM}" logger.info "Current file: #{__FILE__}" puts "-" * 20 puts "Roses are red".red puts "Violets are blue".blue puts "I can use JRuby/Gradle".green puts "And now you can too!".yellow以上がサンプルプロジェクトになります。
自分の管理するJavaライブラリを呼び出す場合は、
repositories {
jcenter()
ruby.gems()
maven {url 'mavenリポジトリのURL'}}
dependencies {
jrubyJar 'xxx.org:name:version'
}
として参照してやればgradleが全部やってくれます。コマンドチートシート
- とりあえず実行する
gradle jrubyRun
- jarファイルにビルドする
gradle jrubyJar
- ビルドファイルを削除する
gradle clean
- ビルドしたものを実行する
java -jar build/libs/sample-jruby.jar
最後に
今どきのJRubyでした。
最近は日本語に記事であまり話題に上がらないですが、実務ではjavaライブラリのテストケースや、使い捨てのメインクラスを作成するぐらいなら私はJrubyで書くようになりました。
gradleで管理できるのが最高です。ほとんど、http://jruby-gradle.org/ で紹介されているとおりですが、
build.gradleにはjrubyRunのタスクを定義してあります。
- 投稿日:2021-03-21T14:06:27+09:00
attr_accessor
①エラーが起きるパターン
user.rb
class User
def initialize(name, age)
@name = name
@age = age
end
endtanaka = User.new('田中太郎', 18)
tanaka.name=> undefined method `name' for # (NoMethodError)
tanaka.age = 33
=> undefined method `age=' for # (NoMethodError)
②attr_accessorメソッド を使ったパターン
user.rb
class User
# 以下の記述でクラス外部から@name,@ageにアクセスが可能になる
attr_accessor :name, :agedef initialize(name, age)
@name = name
@age = age
end
endtanaka = User.new('田中太郎', 18)
p tanaka.age #=> 18tanaka.age = 33
p tanaka.age # => 33このように、attr_accessorメソッドはインスタンス変数にアクセスするためのメソッドを裏側で定義してくれる。attr_accessorメソッドに指定されたインスタンス変数は、クラス外部から参照と変更の両方を行う事が出来るようになる。
- 投稿日:2021-03-21T13:45:33+09:00
inquiry
TL;DR
文字列等価のチェックで
'hoge' == 'hoge'
という書き方以外の方法があります。
Rails AcctiveSupportにはStringオブジェクトの拡張でinquiryというメソッドが定義されています。word = 'hoge'.inquiry word # => 'hoge' word.hoge? # => true word.fuga? # => falseどう定義されてる?
active_support/core_ext/string/inquiry.rb
で定義されてます。lib/active_support/core_ext/string/inquiry.rbrequire "active_support/string_inquirer" class String def inquiry ActiveSupport::StringInquirer.new(self) end endでは
ActiveSupport::StringInquirer
は何者?次で定義されてます。
lib/active_support/string_inquirer.rbmodule ActiveSupport class StringInquirer < String ... def method_missing(method_name, *arguments) if method_name.end_with?("?") self == method_name[0..-2] else super end end def respond_to_missing?(method_name, include_private = false) method_name.end_with?("?") || super end end endmethod_missingの部分がinquiryメソッドの核になってます。
メソッド名の最後に?
がついている場合、そのメソッド名の?
を除いた部分がインスタンス名と一致するかの真偽値を返します。ちなみに...
method_missingは呼び出したメソッドが定義されていなかった時に呼び出されるRuby組み込みのメソッドです。一つ目の引数に呼び出しに失敗したメソッド名、その引数が第二引数に渡されます。
つまりこんな感じclass String def method_missing(method_name, *args) puts "method named #{method_name} is not defined!" end end 'hoge'.fuga # => method named fuga is not defined!またrespond_to_missing?も同じくRuby組み込みのメソッドです。method_missingを呼び出すに該当するメソッドがrespond_to?で呼び出された際に応答します。
class String def method_missing(method_name, *args) puts "method named #{method_name} is not defined!" end def respond_to_missing?(method_name, include_private) method_name.end_with?("?") || super end end 'hoge'.respond_to?(:fuga?) # => true 'hoge'.respond_to?(:piyo) # => false終わり
参考
- https://github.com/rails/rails/blob/main/activesupport/lib/active_support/string_inquirer.rb
- https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/string/inquiry.rb
- https://docs.ruby-lang.org/ja/latest/method/BasicObject/i/method_missing.html
- https://docs.ruby-lang.org/ja/latest/method/Object/i/respond_to_missing=3f.html
- 投稿日:2021-03-21T11:59:53+09:00
scope使い方(Rails)
modelの中にscopeを書く
複数使う場合はスコープで書いた方がコードが読みやすくなりますし、
単体テスト書くことが可能になるため積極的に使った方がいいです。item.rbscope :published, -> { where(private: true) }users_controller.rbdef show if !@user.me?(current_user) @items = @user.items.published else @items = @user.items end endモデルで
{ where(private: true) }
定義することで
コントローラの記述が少なくなります。おまけ
user.rbdef me?(user_id) id == user_id end
current_user
と@user
が一致しているか
モデルに書くことで可能になります。users_controll.rbif !@user.me?(current_user)
- 投稿日:2021-03-21T08:18:43+09:00
画像がアップデートされない。。
refile(Gem)を使って画像投稿をしていて、
マイページでプロフィール画像の編集できるようにしたが、
なぜか画像が更新されない。editアクション、updateアクションもやっている。
def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) @user.update(user_params) redirect_to user_path(@user.id) endviewもこんな感じ
<%= attachment_image_tag @user, :profile_image, :fill, 60, 60, class: "img-circle pull-left profile-thumb", fallback: "no_image.jpg"%>
環境
・docker
・Rails試したこと
・ブラウザにキャッシュされているのかな?と思いキャッシュを削除。
・fillの部分をsizeに変更してみましたが出来ない。解決
docker-compose runをしてみたら、なぜか出来た。
⇨新しいコンテナが作られたからかな?
⇨最初、docker-copose up -d で放置していて、それから新しいコンテナを作っていなかったから?
⇨まだ頭のモヤモヤが。。。とりあえず、解決したので、進みます。もやもやがありますが、、、
- 投稿日:2021-03-21T07:47:30+09:00
アソシエーションしてbuildするときの1対多と1対1の記述の仕方の違いについて
buildの使い方
アソシエーションによって記述の仕方に違いがあるが、まとっているサイトがなかったので書きました。
1対多
# User.rb class User < ApplicationRecord has_many :posts end # Post.rb class Post < ApplicationRecord belongs_to :user end # Posts_controller.rb def new @post = @user.posts.build end1対1
# User.rb class User < ApplicationRecord has_one :account end # Account.rb class Account belongs_to :user end # Accounts_controller.rb def new @account = @user.build_account end参考
- 投稿日:2021-03-21T07:42:37+09:00
【Rails】deviseでのユーザ名ログイン機能の実装
目標
deviseのユーザー登録/ログイン方法は、デフォルトでメールアドレスとパスワード。
これをユーザ名で登録/ログインできるように変更する。準備
deviseをインストール
Gemfileにgem 'devise'
追記 +$ bundle install
初期設定
rails g devise:install
モデル作成 *モデル名は任意(今回はUser)
rails g devise User
View作成
rails g devise:views users
実装
ユーザ登録(Sign Up)
- ユーザ名カラムを追加 +
rails db:migrate
- ユーザ登録画面にユーザ名入力フォームを追加(views/devise/registrations/new.html.erb)
- ストロングパラメータを設定し、ユーザ名データの操作を許可
application_controller.rbbefore_action :configure_permitted_parameters, if: :devise_controller? # deviseの機能が使われる前に、configure_permitted_parametersを実行 protected def configure_permitted_parameter devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) # sign_up時にユーザ名の操作を許可 endログイン(Sign In)
- ログイン画面にフォームを追加(views/devise/sessions/new.html.erb)
- 認証キーをemail→nameに変更 *コメントアウトは外す
config/initializers/devise.rbconfig.authentication_keys = [:name]