- 投稿日:2020-12-12T21:40:45+09:00
ActiveRecordで生SQLを実行して結果を配列にキャストする
※ Railsのバージョンは5.2を想定
何はともあれ生SQLを実行するコードを書く
result = ActiveRecord::Base.connection.select_all('SELECT x_id as id FROM users')取得結果から配列にしたいSELECT結果を指定して抜き出し、新たな配列を生成する
ids = result.map { |h| h['id'] } pp ids # [1, 2, 3, 4, 5, 6, 7]
- 投稿日:2020-12-12T21:31:46+09:00
groupdateを使った際にGroupdate::Errorが出た話
はじめに
今回railsで簡単なグラフを作成する際にchartkickなどと一緒に使うgemのgroupdateを使った際に
出たエラー解決を備忘録として残します。
初学者のため間違えばあればご指摘頂けると幸いです。Groupdate::Errorが出た
chartkickとgroupdateを無事導入しいざ実装と思った時にGroupdate::Errorの文字が、、、
bundleの確認やサーバーの再起動を試したが特に変化なし。エラーが出た理由
エラー文を詳しく確認してみると
Groupdate::Error - Be sure to install time zone support - https://github.com/ankane/groupdate#for-mysql:
これはタイムゾーンサポートをこのURLからインストールしろと言われてました。解決策
URL先でタイムゾーンサポートについての記述があり、そこで指定された以下のコマンドをターミナルで実行
$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql最後に
無事エラーは解消されグラフ機能を実装する事ができました!
エラー文は苦手意識があるのですが、しっかり読解しようとすれば案外解決方法を提示してくれてる場合が多いので今後はしっかりエラーと向き合っていきます!!
- 投稿日:2020-12-12T20:46:05+09:00
yamlファイルとは
はじめに
現在Railsを勉強中です。
アプリケーションを作成する上で、モデルやカラム、その他メッセージ等を日本語で出力したり扱いたい場面が必ずあると思います。自分の場合、すぐに忘れてしまうためその都度ググって、書き方合ってたかを確認しています。
ぶっちゃけYAMLファイルの仕様等を詳細に把握していなくても、問題なく作業が進むので今までないがしろにしてきましたが、今回は基本的な部分を調べて、アウトプットしようと思います。YAMLファイルの特徴
分かりやすさ
構造化されたデータを扱うためのフォーマットであり、目的はXML等と似ているが、「読みやすい」「書きやすい」「わかりやすい」という利点がある。
構造
インデントによって、階層の構造を表現している
YAMLファイルで扱うデータ型
- スカラー(文字列・数値・真偽値 etc)
- シーケンス(配列)
- マッピング(ハッシュ)
YAMLファイルの書き方
スカラー
YAMLはデータ型を自動的に判別してくれる
数字を文字列で扱いたい場合は'(シングルクォート)もしくは"(ダブルクォート)で囲むと強制的に文字列として認識してくれる#数値 int1: 2 int2: 123,456 #浮動小数点 float1: 0.1 #NULL nil1: nil nil2: ~ #Boolean bool1: true bool2: false bool3: yes bool4: no bool5: on bool6: of #日付 birthday: 1990-01-01 #タイムスタンプ stamp: 2020-12-01 10:00:00 + 0900 #文字列 str1:hoge str2:'true' str3:"333"配列
行頭に
-をいれることで、配列として扱うことが出来る。このときに-と値の間には半角スペースをいれること- Ruby - Java - PHP出力用メソッド
以降の出力例でも同様のものを使用
require 'yaml' p YAML.load_file('test.yml')出力結果
yaml_test.rb["Ruby", "Java", "PHP"]半角スペースでインデントを入れると、配列をネストさせることが出来る
- parent1 - - children1.1 - children1.2 - children1.3 - - grandchild1.3.1 - grandchild1.3.2 - grandchild1.3.3 - parent2出力結果
["parent1", ["children1.1", "children1.2", "children1.3", ["grandchild1.3.1", "grandchild1.3.2", "grandchild1.3.3"]], "parent2"]ハッシュ
:で「キー:値」のように区切って記述する
おそらくこれが、railsで扱う中で一番多いパターンだと思います。name: 名前 age: 年齢 gender: 性別 address: 住所出力結果
{"name"=>"名前", "age"=>"年齢", "gender"=>"性別", "address"=>"住所"}ハッシュに関しても半角スペースでインデントすることで、ネストさせることが可能
music: rock: ロック pop: ポップス jaz: ジャズ出力結果
{"music"=>{"rock"=>"ロック", "pop"=>"ポップス", "jaz"=>"ジャズ"}}アンカーとエイリアス
YAMLではアンカーとエイリアスを仕様することで、対象の構造に対して参照することが出来る
&nameでアンカーをつけ、*nameで参照することができる。Railsの
database.ymlなどではデフォルトで使われているdefault: &default adapter: postgresql encoding: unicode development: <<: *defaultちなみにここで登場している
<<を用いることでハッシュをマージ出来る。{"default"=>{"adapter"=>"postgresql", "encoding"=>"unicode"}, "development"=>{"adapter"=>"postgresql", "encoding"=>"unicode"}}参考文献
- 投稿日:2020-12-12T20:46:05+09:00
yamlファイルの書き方やと特徴
はじめに
現在Railsを勉強中です。
アプリケーションを作成する上で、モデルやカラム、その他メッセージ等を日本語で出力したり扱いたい場面が必ずあると思います。自分の場合、すぐに忘れてしまうためその都度ググって、書き方合ってたかを確認しています。
ぶっちゃけYAMLファイルの仕様等を詳細に把握していなくても、問題なく作業が進むので今までないがしろにしてきましたが、今回は基本的な部分を調べて、アウトプットしようと思います。YAMLファイルの特徴
分かりやすさ
構造化されたデータを扱うためのフォーマットであり、目的はXML等と似ているが、「読みやすい」「書きやすい」「わかりやすい」という利点がある。
構造
インデントによって、階層の構造を表現している
YAMLファイルで扱うデータ型
- スカラー(文字列・数値・真偽値 etc)
- シーケンス(配列)
- マッピング(ハッシュ)
YAMLファイルの書き方
スカラー
YAMLはデータ型を自動的に判別してくれる
数字を文字列で扱いたい場合は'(シングルクォート)もしくは"(ダブルクォート)で囲むと強制的に文字列として認識してくれる#数値 int1: 2 int2: 123,456 #浮動小数点 float1: 0.1 #NULL nil1: nil nil2: ~ #Boolean bool1: true bool2: false bool3: yes bool4: no bool5: on bool6: of #日付 birthday: 1990-01-01 #タイムスタンプ stamp: 2020-12-01 10:00:00 + 0900 #文字列 str1:hoge str2:'true' str3:"333"配列
行頭に
-をいれることで、配列として扱うことが出来る。このときに-と値の間には半角スペースをいれること- Ruby - Java - PHP出力用メソッド
以降の出力例でも同様のものを使用
require 'yaml' p YAML.load_file('test.yml')出力結果
yaml_test.rb["Ruby", "Java", "PHP"]半角スペースでインデントを入れると、配列をネストさせることが出来る
- parent1 - - children1.1 - children1.2 - children1.3 - - grandchild1.3.1 - grandchild1.3.2 - grandchild1.3.3 - parent2出力結果
["parent1", ["children1.1", "children1.2", "children1.3", ["grandchild1.3.1", "grandchild1.3.2", "grandchild1.3.3"]], "parent2"]ハッシュ
:で「キー:値」のように区切って記述する
おそらくこれが、railsで扱う中で一番多いパターンだと思います。name: 名前 age: 年齢 gender: 性別 address: 住所出力結果
{"name"=>"名前", "age"=>"年齢", "gender"=>"性別", "address"=>"住所"}ハッシュに関しても半角スペースでインデントすることで、ネストさせることが可能
music: rock: ロック pop: ポップス jaz: ジャズ出力結果
{"music"=>{"rock"=>"ロック", "pop"=>"ポップス", "jaz"=>"ジャズ"}}アンカーとエイリアス
YAMLではアンカーとエイリアスを仕様することで、対象の構造に対して参照することが出来る
&nameでアンカーをつけ、*nameで参照することができる。Railsの
database.ymlなどではデフォルトで使われているdefault: &default adapter: postgresql encoding: unicode development: <<: *defaultちなみにここで登場している
<<を用いることでハッシュをマージ出来る。{"default"=>{"adapter"=>"postgresql", "encoding"=>"unicode"}, "development"=>{"adapter"=>"postgresql", "encoding"=>"unicode"}}参考文献
- 投稿日:2020-12-12T17:57:00+09:00
ストロングパラメーターに外部キーを渡す方法
概要
ポートフォリオに投稿機能を実装中、ストロングパラメーターを用いて値を渡そうとしたのですが
何度やっても投稿が保存されませんでした。def create @post = Post.new(post_params) binding.pry if @post.save flash[:success] = "投稿しました" redirect_to posts_path else render action: :new end endbinding.pryを差し込んでデバッグしたみたのですが結果は
permitted: trueじゃあなんで投稿できない。。
調べたところ単純な記述ミスでした。
軽くハマってしまったので自分の備忘録も兼ねての投稿です。
開発環境
- Rails 6.0.3.4
- ruby 2.6.3
実装方法
元々のコード
def post_params params.require(:post).permit(:user_id, :title, :content, :price, :img) end正しいコード
def post_params params.require(:post).permit(:title, :content, :price, :img).merge(user_id: current_user.id) end
外部キーのuser_idを渡す時にmergeメソッドを使ったら投稿できるようになりました!!
- 投稿日:2020-12-12T17:44:31+09:00
【Active Job】shoryuken + Amazon SQSを動かしてみた
Railsの非同期処理をActive Job + shoryuken + SQSで実装したのでメモを残します。※RailsアプリケーションはDocker環境で構築済みの前提です。環境構築はこちら。
※Active Jobとバックエンドの比較はこちら。環境
- Ruby 2.7.2
- Rails 6.0.3.4
- MySQL 8.0.20
- shoryuken 5.0.5
- Docker version 19.03.13
1. SQSの設定
まずAWSコンソールにログインし、画面上でSQSの設定をしていきます。
Amazon Simple Queue Service (SQS) は、完全マネージド型のメッセージキューイングサービスです。
画面や設定等は2020/11時点のものです。キューを作成します。
ここでSQSの詳細な設定は割愛しますが、要件に応じて様々な設定はできそうです。
キューの名前だけ指定し、その他はデフォルト値で設定します。これでSQS側の設定は完了です。
あとはローカル環境からアクセスするためのアクセスキーをIAMで発行しました。2. shoryukenの設定
まずGemを入れていきます。
Gemfilegem 'aws-sdk-sqs' gem 'shoryuken'
bundle installを実行し、shoryukenの設定ファイルも追加します。
AWSへの接続情報として、発行したアクセスキー等を環境変数に設定して利用します。
キーの管理はcredentialsでも良いかなと思いました。(プロダクトの方針次第)config/shoryuken.ymlaws: access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> region: <%= ENV["AWS_REGION"] %> concurrency: 1 logfile: ./log/shoryuken.log :queues: - development_default3. Active Jobの設定
Active Jobで非同期処理を実装していきます。
config/application.rbrequire "active_job/railtie" module App class Application < Rails::Application ... config.active_job.queue_adapter = :shoryuken ... end end4. ジョブの作成と動作確認
ようやくジョブを作成します。
rails g job shoryuken_sampleapp/jobs/shoryuken_sample_job.rbclass ShoryukenSampleJob < ApplicationJob queue_as :default def perform puts '--------------------------------' puts '----------- 昇龍拳 ------------' puts '--------------------------------' end end続いて動作確認を行います。
$ bundle exec shoryuken -C config/shoryuken.yml(↑僕の環境では特にコマンド実行後、特に何も表示されませんでしたが、キュイーイングしたら動きました。)
別タブのターミナルでRailsコンソールからShoryukenSampleJobをキューイングしてみます。$ rails c Loading development environment (Rails 6.0.3.4) > ShoryukenSampleJob.set(wait: 5.second).perform_later Enqueued ShoryukenSampleJob (Job ID: ad754d56-8f50-4864-8b24-69479ef5c7f7) to Shoryuken(development_default) at 2020-11-25 11:32:39 UTC => #<ShoryukenSampleJob:0x000055821986c0b8 @arguments=[], @exception_executions={}, @executions=0, @job_id="ad754d56-8f50-4864-8b24-69479ef5c7f7", @priority=nil, @queue_name="development_default", @scheduled_at=1606303959.7208154>キューイングすると先ほど起動したshoryuken側でジョブが実行されたことが確認できました。
-------------------------------- ----------- 昇龍拳 ------------ --------------------------------
- 投稿日:2020-12-12T17:43:38+09:00
投稿アプリに基本的な検索機能を実装
概要
検索機能を実装する方法をまとめました。
例として、写真投稿アプリに基本的な検索機能を実装する方法を紹介します。
初学者なので、間違いがあればご指摘いただきたいです。
参照
以下のページを参照しました。ありがとうございました。
Railsで検索機能を実装する方法を現役エンジニアが解説【初心者向け】
完成イメージ
環境
- macOS Catalina 10.15.7
- ruby 2.6.5
- Rails 6.0.3.4
実装の流れ
- ルーティングを追加
- コントローラーにsearchメソッドを作成
- 検索フォームを作成
- 検索結果表示画面を作成
今回のコード
1. ルーティングを追加
routes.rbresources :photos do resources :comments, only: :create collection do get 'search' end end
- photosコントローラーにsearchアクションを追加します。
- collectionとすることで:idを含まないルーティングになります。
ちなみに、memberとすると:idを含むルーティングになります。
参照:https://qiita.com/k152744/items/141345e34fc0095217fe2. コントローラーにsearchメソッドを作成
photos_controller.rbdef search if params[:keyword].present? @photos = Photo.where('caption LIKE ?', "%#{params[:keyword]}%") @keyword = params[:keyword] else @photos = Photo.all end end
- 検索ボタンをクリックするとsearchアクションが呼び出され、入力した検索ワードをparams[:keyword]で取得できます。:keywordでなくとも好きなキー名をつけることができますが、今回は:keywordとしました。
- 今回は写真のキャプションで検索するため、Photo.where('caption LIKE ?', "%#{params[:keyword]}%")としました。これで、入力した検索ワードがキャプション内に含まれる写真をすべて取得できます。whereメソッドの使い方については、以下をご参照ください。https://techacademy.jp/magazine/22330
- 何も入力せずに検索ボタンをクリックした場合は、Photo.allですべての写真を取得することとしました。
- 入力した検索ワードを取得して検索結果表示画面で使用するため、@keyword = params[:keyword]としました。
3. 検索フォームを作成
index.html.erb# クラス名などは省略してあります <%= form_with url: search_photos_path, local: true, method: :get do |form| %> <%= form.text_field :keyword %> <%= form.submit "検索" %> <% end %>
- form.text_field :keywordとすることで、検索ボタンをクリックした後、:keywordキーに、入力した検索ワードが値として設定されます。コントローラーのsearchメソッドでparams[:keyword]と設定すると、その値を取得することができます。
4. 検索結果表示画面を作成
search.html.erb## クラス名などは省略してあります <h2>検索結果 "<%= @keyword %>"</h2> <ul> <% @photos.each do |photo| %> <li> <%= link_to photo_path(photo.id) do %> <%= image_tag photo.image.variant(gravity: :center, resize:"640x640^", crop:"640x640+0+0"), if photo.image.attached? %> <% end %> </li> <% end %> </ul>
- 上記のとおり、コントローラーのsearchメソッドで、検索ワードが含まれる写真を@photosに格納しました。@photos.each do |photo|で、それらひとつひとつの写真を取り出し、画面に表示させます。
- <%= @keyword %>で、入力した検索ワードも表示させました。
おわりに
以上が、今回行った基本的な検索機能実装の方法です。
ハッシュタグ検索など、より高度な検索も今後挑戦してみたいですね。
- 投稿日:2020-12-12T17:23:41+09:00
railsのmigrateファイルと仲良くなる
はじめに
現在、某プログラミングスクールに通い、Railsを学び初めて4ヶ月ほどの初学者です
個人開発、チーム開発でいつも同じところでRubyのRailから外れてしまうので、道標を残します
初めての投稿なので誤字脱字あったらすいません開発環境、他
IDE : Cloud9
Ruby : 2.6.3
Ruby on Rails : 5.2.4.4
rails new〜 でなんらかのアプリケーション作成済
テーブル作成済
sample_appという名前で作った簡易写真投稿アプリケーションでmigrateあたりをまとめていこうと思いますカラムの追加・削除・変更
カラムの追加
ここに"hoge"というカラムをstring型で追加するとします
ターミナルrails g migration AddhogeToLists hoge:stringdb/migrate/日時addhoge_to_lists.rb というファイルが作成されます
addcolumn :テーブル名, :カラム名, :データ型
こんな感じに書いてあげて、ターミナルrails db:migrateしっかりいてます
追加できました(上2行は気にしないでください)カラムの削除
次は先ほど追加したものを削除します
ターミナルrails g migration RemovehogeToLists hoge:stringターミナルrails db:migrateカラムの変更
上から2行目のbodyカラムのデータ型をstringからtextに変更しようと思いますターミナルrails g migration change_data_body_to_listsカラム追加・削除と同じように
db/migrate/日時_addhoge_to_lists.rb というファイルが作成されるので、
ターミナルrails db:migrateまとめます
カラム追加→rails g migration Addカラム名To複数形テーブル名 (なくてもok)カラム名:データ型
rails db:migrate
カラム削除→rails g migration Removeカラム名To複数形テーブル名 (なくてもok)カラム名:データ型
rails db:migrate
カラム変更→rails g migration change_data_カラム名to複数形テーブル名
rails db:migratemigrateファイルを削除する
原則migrateファイルは削除しません
テーブル内容の変更削除をする場合、上記のようにmigrateファイルを作って反映の繰り返しです
(migrateだけファイルの量膨大になる)
でも個人開発の時やgitにpush前で自分が作ったmigrateファイルの時を戻したいと思うこともあるはず…
今回は上記で作った3つのmigrateファイルがいらないので無かったことにしたいと思います今のmigrateファイルってどんな感じ?
ターミナルrails db:migrate:status
下3行目からが今さっき追加したファイルですね
Statusがupになっているのでバッチリ反映されていますrollbackの出番
ファイルがupの状態だと、schemaに反映されているのでファイルを削除するとエラーは起こりませんがデータベース問題でややこしくなります
下から2行目を消してみました
確かにmigrateフォルダからは消え去っているのですが、migrate statusには残っています
チーム開発の場合、このままだとデータベースの相違問題が起こるし、何より気持ち悪いのでファイルを直で消すのはやめましょう
schema
hogeカラムも復活してないのでやめましょうStatusをdownにすると消しても問題ありません
(down状態だとファイルの内容はどこにも反映されていない状態)では戻してみましょう
ターミナルrails db:rollbackこれで一つ前のmigrateファイルが巻き戻り、downに戻ります
でも今回は複数のファイルを巻き戻したいので複数行指定します
ターミナルrails db:rollback STEP=nnには巻き戻したい行数を入れます。
今回は3ですね
*巻き戻したぶん、全部downになりますが、最後にrails db:migrateをすると全部反映してくれるので問題ありません
やってみみました
…エラーかよ(´༎ຶོρ༎ຶོ`)
「migrationにchange_columnがあるから巻き戻せません
巻き戻すには
1、#changeメソッドのところを#upか#downにしてね
2、#reversibleメソッドを使ってね」
ということなので、changeをupに変えていざ実行
rollbackしてみる
できました
ステータス確認!
schema確認!
全てもとに戻りました
ファイルを消して、再びステータス確認!!
いい感じですね( ˊ̱˂˃ˋ̱ )
ぐちゃぐちゃになったmigrateファイルはリセットしましょう
ターミナルrails db:migrate:resetその後に
ターミナルrails db:migrateデータベースがまっさらになるので最初から投稿し直しになります
(もしseedファイルにデータを入れている場合、rails db:seedをやってあげてください)まとめます
migrateファイルを巻き戻す場合はrails db:rollbackを使う
複数行ならrails db:rollback STEP=n
def changeの場合だと巻き戻らないのでupやdownに変えてあげる
巻き戻したmigrateファイルをいじって、rails db:migrate
migrateファイルがぐちゃぐちゃになったり、データ投稿した内容を一旦リセットしたくなったら(投稿物が”テスト”ばかりとか)rails db:migrate:resetをやってみる終わりに
migrate周辺でいつも迷子になるのでまとめました
カラム名を打ち間違えてそのままmigrateとかやってしまうので、そういうところ改善したいですね
記念すべき1記事目を最後までご覧いただきましてありがとうございました
間違えてるところ、おかしなところがあれば教えてください参考
https://qiita.com/azusanakano/items/a2847e4e582b9a627e3a
https://qiita.com/yana_dev/items/c96594bbea3329ef0fec
- 投稿日:2020-12-12T16:12:54+09:00
Railsチュートリアル(第6版)攻略 〜アカウント作成編〜
本記事の目的
本記事の目的はRailsチュートリアルの学習をしている未経験エンジニアの学習・理解を支援することです。本記事では、Railsチュートリアルに沿って開発していくアプリの動作をテーマに区切って概説します。Railsチュートリアルを初めて走行する方にとっては、完成したアプリの動作全体をあらかじめ理解しておくことで、現在自分がチュートリアルのどの部分を学習しているのか、学習進捗の現在地を把握するマップとしてご活用いただけると思います。また、Railsチュートリアルを1周走破した方にとっては、自身が開発したアプリの動作全体像を振り返ることで、復習と理解の一助としてご活用いただければ幸いです。
アカウント作成の流れ
概要
ユーザー操作の観点で見ると、アカウント新規作成は下記3stepで進みます。
- ユーザーがサインアップへのリンクを踏み、新規ユーザー登録のための入力フォームが表示される。
- ユーザーがフォームに必要情報を入力して送信ボタンを押すと、入力フォームに記入したMailアドレスへ向けてアカウント有効化メールが送信される。
- ユーザーがアカウント有効化メールに記載されたリンクを踏むと、アカウントが有効化され、ユーザーの新規作成が完了する。
詳細
概要で説明した3stepでそれぞれでのアプリ動作の詳細を以下に説明します。
- ユーザーが/signupパスへのリンクをクリックすると、クライアント(Webブラウザ)からサーバーへ/signupパスへのGETリクエストが送信され、Usersコントローラ内のnewアクションが実行される。newアクションでは、Userモデルのインスタンスが新規作成され、newアクションに対応したview(new.html.erb)をRailsが自動で表示する。このとき、新規作成したuserインスタンスはviewへ渡される。なお、new.html.erbは新規ユーザー登録の入力フォームである。
- Railsは、new.html.erbへ渡されたuserインスタンスが空であるかどうか自動で判定を行う。空であった場合にRailsはユーザーの新規作成であると判断し、ユーザーが入力フォームの送信ボタンをクリックすると、/signupパスへのPOSTリクエストがサーバー側へ送信され、Usersコントローラ内のcreateアクションが実行される。このcreateアクション実行の直前にはアカウント有効化トークンが発行され、かつ、トークンがダイジェスト化され、ダイジェスト化したアカウント有効化トークン(アカウント有効化ダイジェスト)がDBに保存される。createアクションでは、フォームの入力情報を受け取り、受け取った情報から許可されたキーに対応した値のみを新規作成されたuserインスタンスに格納し、DBへの保存を試みる。そして、新規作成したユーザーのDB保存に成功すると、そのユーザーに向けてアカウント有効化メールを送信する。このアカウント有効化メールには、アカウント有効化のためのURLが添付されている。
- 新規ユーザーがアカウント有効化のURLをクリックすると、AccountActivationコントローラのeditアクションが実行される。また,当該URLにはアカウント有効化トークンとユーザーのemailアドレスが仕込まれており、サーバー側はGETリクエストを受けるとURLに仕込まれたemailアドレスを手がかりにしてDBから該当ユーザーの検索を行う。そして、検索にヒットしたユーザーが存在し、かつ、そのユーザーが未だアカウント有効化されておらず、加えて、受け取ったアカウント有効化トークンをダイジェスト化した値がDBに保存されていたアカウント有効化ダイジェストと一致した場合に、アカウントを有効化してセッションを立ててログインする。最後にuserのホーム画面へリダイレクトを行い、StaticPagesコントローラ内のhomeアクションを実行して、アクションに対応したview(home.html.erb)を表示する。
- 投稿日:2020-12-12T15:18:40+09:00
deviseのcontroller#createをいじったけどエラーでた時のメモ
app/contoller/customers/registrations_controller.rbclass Customers::RegistrationsController < Devise::RegistrationsController before_action :configure_sign_up_params, only: [:create] ... def create super @customer.company_id = params[:company_id] binding.pry if @customer.save CustomerStatus.create(paid: false, room_plus: false, dozen_sessions: false, numbers_of_contractnt: 0, customer_id: @customer.id) end end ... protected def configure_sign_up_params devise_parameter_sanitizer.permit(:sign_up, keys: [:company_id]) enddeviseはbelongs_to をしたら新規登録でうまくいかなくなるみたいなので、気をつけましょうというメモです。
解決法
7行目の部分です
以上!
- 投稿日:2020-12-12T14:43:37+09:00
N + 1問題 - Railsで解説!
はじめに
Ruby on RailsなどDB(データベース)を使用するサーバーサイド言語で必ず上がる「N + 1問題」。
主に1対多のアソシエーション関係がある時に起こる問題です。
Railsでは一覧表示機能を含む1対多の関係が不可欠な機能が実装されるので、N + 1問題は理解しておくべきかと思います。対象者
rails tutorialを学習済みの方
SQL初学者の方使用環境
・ruby 2.6.4
・Rails 5.2.3
・MySQL 5.4N+1問題とは
一言で表すと、
「テーブル参照のSQLが大量に発行されてしまうこと」
実際に見ていきましょう。
今回は掲示板投稿機能を実装するためのrailsのファイルを使用します。まず、N + 1問題を引き起こす投稿機能モデルのコントローラーとビューのファイルの中身です。
app/controllers/boards_controller.rb(コントローラー)
class BoardsController < ApplicationController def index @boards = Board.all end endapp/views/boards/index.html.erb(ビュー)
<div class="row"> <div class="col-12"> <div class="row"> <% if @boards.present? %> <%= render @boards %> <% else %> <p><%= t('.no_board') %></p> <% end %> </div> </div> </div>/render @boards/
これによってrailsはファイルの同じディレクトリにある_board.html.erbファイルをパーシャルとして読み込んでくれる仕様になっています。
(よしなにやってくれるrailsの特徴ですね)同時にコントローラーで取得した@boardsを繰り返し処理で1つずつboardとしてパーシャルに渡します。
(長いですが、一言で言うと掲示板の投稿が1つずつ作成されているコードです)app/views/boards/_board.html.erb(ビュー)
<div class="col-sm-12 col-lg-4 mb-3"> <div id="board-id-<%= board.id %>"> <div class="card"> <%= image_tag 'board_placeholder.png', class: 'card-img-top', width: 300, height: 200 %> <div class="card-body"> <h4 class="card-title"> <%= link_to board.title, "#" %> </h4> <div class='mr10 float-right'> <%= link_to '#', id: 'button-edit-#{board.id}' do %> <%= icon 'fa', 'pen' %> <% end %> <%= link_to '#', id: 'button-delete-#{board.id}', method: :delete, data: {confirm: ''} do %> <%= icon 'fas', 'trash' %> <% end %> </div> <ul class="list-inline"> <li class="list-inline-item"><i class="far fa-user"></i> <%= board.user.decorate.full_name %> </li> <li class="list-inline-item"><i class="far fa-calendar"></i> <%= l board.created_at, format: :short %> </li> </ul> <p class="card-text"> <%= board.body %> </p> </div> </div> </div> </div>この掲示板一覧を表示するタイミングで発行されるSQL文が以下になります。
Rendering boards/index.html.erb within layouts/application Board Load (1.6ms) SELECT "boards".* FROM "boards" ↳ app/views/boards/index.html.erb:16 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/views/boards/_board.html.erb:19 CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]めちゃくちゃ長い、、、
これrails tutorialではマイクロポストで投稿一覧を表示しますが、同じように長いSQL文が発行されます。なぜこのようなことが起きるのか?
諸悪の根源はたった一文です@boards = Board.allん?この部分はrails tutorialで習った通りじゃないですか?
何が問題かというと、@boardsに格納されている投稿(board)が呼び出される度に、そのboardがどのuserのものであるかを検索してい状態です。
つまり、投稿画面に遷移する時に、掲示板の全ての投稿を取得するために
Boardテーブル全体を参照するSQL文が1回発行される
Board Load (1.6ms) SELECT "boards".* FROM "boards"そして、のUsersテーブルを参照するSQLの文章が
掲示板の投稿の数(N回)だけ発行されている状態
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]この投稿数の数(N) + 最初の全体参照(1)が"N + 1問題"です。
解決方法
しかし、このN + 1問題は問題の文を以下のように書き換えるだけで簡単に解決できてしまいます。
@boards = Board.all.includes(:user)includesメソッドによりBoardテーブル参照時に、(boardの外部参照のためのuser_idカラムを元に)Userテーブルも同時に参照するようにしています。
よってテーブル参照回数も2回となります!!
(たとえ掲示板の投稿が増えたとしても)Board Load (3.0ms) SELECT "boards".* FROM "boards" ORDER BY "boards"."created_at" DESC ↳ app/views/boards/index.html.erb:16 User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (?, ?, ?) [["id", 2], ["id", 1], ["id", 3]] ↳ app/views/boards/index.html.erb:16SQL文の発行も2回で済みます。
1対多のアソシエーション関係を持つモデルを扱う場合は是非覚えておきましょう!
- 投稿日:2020-12-12T14:28:58+09:00
Active Adminの検索条件にenum値が反映されない時の対処方法
Active Adminの検索条件にenum値が反映されない現象が発生する。
現象詳細
enum値は以下の通り。
enum status: { not_started: 0, in_progress: 1, done: 9 }Active Admin内のfilter設定は以下の通り。(enum値の日本語化対応も込み)
filter :status, as: :select, collection:Inquiry.statuses_i18n.invertこの時に検索条件にenum値の選択項目が表示されるものの、絞り込みが動作しない現象が発生する。
原因
activeadminの検索にはransack gemを使用してが、ransackがうまくenumに対応できていないことが原因。
以下のように変更すると正しく動作する。filter :status, as: :select, collection:Inquiry.statuses_i18n.invert.map{ |k, v| [k, Inquiry.statuses[v]]}原因詳細
filter :status, as: :select, collection:Inquiry.statuses_i18n.invert上記フィルターを指定した際に、サーバへ送付されるパラメータは以下のようになる。
{"q"=>{"status_eq"=>"in_progress"}, "commit"=>"絞り込む", "order"=>"id_desc"}これを受けて、本来は、in_prgressに対応した1で検索をしてほしいが、実際のSQLを見ると以下のように'status'=0となっている。
SELECT COUNT(*) FROM (SELECT 1 AS one FROM `inquiries` WHERE `inquiries`.`status` = 0 LIMIT 30 OFFSET 0) subquery_for_countつまりransack側でin_progress → 1という変換を期待してたがenumの値をとってくれず、
数値にカラムに文字列を指定したので、0が指定された。解決方法
filterに指定したcollection:以降の部分は、コンソールで叩くと以下のようになる。
>Inquiry.statuses_i18n.invert {"未着手"=>"not_started", "進行中"=>"in_progress", "完了"=>"done"}collectionではkeyが表示内容、valueがサーバへ送信される値なので、ハッシュを以下のような形にできれば、ransackで正しく検索できる様になる。
{"未着手"=>0, "進行中"=>1, "完了"=>9}そのため、collectionに読み込ませる値を以下のようにすると、ransackでも読み取れる値にできる(arrayでもcollectionは問題なく読み込んでくれる模様)
Inquiry.statuses_i18n.invert.map{ |key, value| [key, Inquiry.statuses[value]]} > [["未着手", 0], ["進行中", 1], ["完了", 9]]参照:RansackはRailsのenumに対応していないっぽい
https://www.tom08.net/entry/2016/12/05/121746
- 投稿日:2020-12-12T14:14:26+09:00
【Ruby on Rails】Railsコマンドまとめ
はじめに
Rails 初心者用。
よく使うコマンドをまとめてみた。コマンド一覧
rails new
railsで新しいアプリケーションを作成する際に使用するコマンド
rails new [アプリケーション名] -オプションrails generate controller
ページを表示する為に必要なファイルを生成する。
コントローラーとかビュー。それに伴ってルーティングも作成される。
()内は指定しなくても大丈夫。後からファイルに指定すれば。
※「generate」の部分は「g」と省略可能。 → rails g controllerrails g controller [コントローラー名] ([アクション名])rails generate migration
マイグレーションファイルを生成する。
マイグレーションファイルとは、データベースのテーブルの情報を変更する際に使用するファイル。
※「generate」の部分は「g」と省略可能。 → rails g migrationrails g controller [マイグレーションファイル名]rails generate model
モデルファイルを生成する。
モデルファイルは、コントローラから受け取ったデータをデータベースに渡したり、反対にデータベースからの情報をコントローラに渡したりする役割がある。
※「generate」の部分は「g」と省略可能。 → rails g modelrails g model [モデル名]rails server
rails サーバーを起動する。
※「server」の部分は「s」と省略可能。 → rails srails srails console
コンソールを起動することができる。
オプションで「--sandbox」をつけると、データベースに変更を与えないようにすることができる。
※「console」の部分は「c」と省略可能。 → rails crails c
- 投稿日:2020-12-12T13:57:09+09:00
Active Adminで設定した心当たりのない検索条件が表示される。
Active Adminで設定した心当たりのない検索条件が表示される現象が発生した。
BOOKMARK
FACILITIES
BOOKMARK FACILITIESなんてパラメータ知らない。。。選択項目に変な値が出るし。。。
結論
Active Admin内でfilterの設定を行なっていないことが原因。
filterで検索条件を指定しておかないと全てのパラメータの検索条件が表示される。検索条件を明示したいなら、filterの設定を行う必要ある。
app/admin/users.rb # 絞り込み条件の項目設定 filter :email filter :nickname filter :birth_year filter :sex, as: :select, collection:User.sexes_i18n.invert.map{|key,value| [key,User.sexes[value]]}
- 投稿日:2020-12-12T13:20:52+09:00
【Rails Colorpicker】カラーピッカーの選択色を特定要素の色と連動させる
【Rails Colorpicker】カラーピッカーの選択色を特定要素の色と連動させる
この記事でできるようになること
以下のGIFのように、カラーピッカーで選択した色がリアルタイムで、何か特定の要素の持つ色と連動させることができるようになる!
GIFではちょっとわかりにくいですが、今回はFontawesomeで用意したピンの色と、カラーピッカーでの選択色とをリアルタイムで連携させてます。考え方
以下のことをやっていくとなんかいけそうだとまず考える。
①カラーピッカーで選択している色を取得する
②その選択色をもってして、ピンのcolorを変更するんー簡単そう。
とりあえず、やってみよあ、ちなみにカラーピッカーはHTML5の標準搭載の機能でした
めっちゃすごない???!!
これだけでカラーピッカー実装できるんですよ?。。。index.html<input type="color">実装コーディング
index.html.erb<%# ↓これがアイコン %> <i class="fas fa-location-arrow" id="arrow-icon"></i> <%# ↓これがカラーピッカー %> <input type="color" class="arrow-icon-color-selector" id="arrow-icon-colorーselector" value="#e66465">index.js// まずカラーピッカーの要素をcolorpickerという変数に入れる const colorpicker = document.querySelector('.arrow-icon-color-selector'); // 次に、ピンの要素をarrowiconという変数に入れる const arrowicon = document.getElementById('arrow-icon'); colorpicker.addEventListener('input', function(e) { // カラーピッカーの入力値(inputの値)が変更されたら{}内の処理を実行する arrowicon.style.color = e.target.value; // アイコンのCSSのcolorプロパティの値を右辺の値にする。右辺の値とはすなわち、カラーピッカーでの選択値である。 });コーディングもめっちゃシンプルでした。。。。
応用すれば、画面の背景を変えたりできるので是非に!例えばこんな感じにしたかったら
index.jsconst colorpicker = document.querySelector('.arrow-icon-color-selector'); const arrowicon = document.getElementById('arrow-icon'); colorpicker.addEventListener('input', function(e) { document.body.style.backgroundColor = e.target.value; });以上です!!
お疲れ様でした!!
- 投稿日:2020-12-12T12:41:15+09:00
VagrantでRuby2.7.2 (Ruby on Rails5.1.7)のローカル環境の構築
記事の目的
- 自分のメモ用
- dotinstallにおけるローカル環境構築講座に躓いた方に参考にしてもらう
初投稿になりますので、至らぬ所多々あると思いますがご了承下さい
PC環境
- macOS Catalina 10.15.7
- MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)
- プロセッサ 1.4 GHz クアッドコアIntel Core i5
- メモリ 8GB
バージョン
- CentOs version: 7
- Ruby version: 2.7.2 (x86_64-linux)
- Rails version: 5.1.7
記事の内容
- Virtual Box, Vagrantのインストール
- Vagrant で Cent OS7 (Linux) をインストール
- CentOSの起動と停止方法
- Cyberduckをインストール
- rbenv をインストール
- ruby-buildプラグイン を追加
- Ruby をインストール
- Bundler のインストール
- Ruby on Rails のインストール
- Ruby on Rails の接続
構築手順
私は下記記事を参照に基本的には環境構築を実施した。
ただしCent OS内のフォルダーを見える化(操作しやすく)するため、上記記事に描かれていない、Cyberduckのインストールも合わせて実施した。
こちらの手順はドットインストールを参照いただきたいが、エラーがでた場合な下記記事を参考にして欲しい。
エラー
環境構築を実施していく中で、2点詰まったエラーがあったのでメモしておく
1. gem 'listen'が見つかりません
Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile (LoadError)解決法
cybetduckからGemfileを見つけて開き、下記をコード内に追加
group :development do
gem 'listen'
end
Gemfileは下記のようになるはずsource "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails", "~> 5.1.0" group :development do gem 'listen' end2. gem 'sqlite3'が見つかりません
Add `gem 'sqlite3'` to your Gemfile解決法
先ほどと同様にcybetduckからGemfileを見つけて開き、下記をコード内に追加
gem 'sqlite3', '~> 1.3.6'
Gemfileは下記のようになるはずsource "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails", "~> 5.1.0" gem 'sqlite3', '~> 1.3.6' group :development do gem 'listen' end3. Ruby on Rails の接続時エラー
最終接続時につながらずエラーが出る場合は下記記事を参照
私はNo.2までの処理を実行し、接続できた最後に
私自身、初学者であり、コマンドラインの使い方も分からずにインストール、アンインストールを繰り返してかなり苦労した。
参考サイトをご覧いただき、少しでも困っている方々の助けになればと思い投稿しました。
初投稿でもありますので、温かい目で見てください笑
- 投稿日:2020-12-12T12:19:08+09:00
[Rails]twilioでSMSを送信する
tiwilioでサインアップする
https://jp.twilio.com/try-twilio
まずは会員登録をしましょう。
テストであれば無料で使えます。必要な情報を入手
TRIAL NUMBER、アカウントSID、AUTHTOKENを入手しましょう!
(consoleのトップ画面に表示されています。)gemをインストール
gem 'twilio-ruby'コード作成
モデルを作成
message.rbclass Message def initialize(tel:) @tel = tel end def hello(user:) @message = "#{user.name}さんこんにちは" send end private def send @tel = "+81" + @tel.slice(1..11) account_sid = ENV['TWILLIO_ACCOUNT_SID'] auth_token = ENV['TWILLIO_AUTH_TOKEN'] @client = Twilio::REST::Client.new account_sid, auth_token @client.messages.create( from: ENV['TWILLIO_PHONE_NUMBER'], # TRIAL NUMBERを入力 to: @tel, body: @message ) end endコントローラーを設定
users_controller.rbdef send_sms user = User.first message = Message.new(tel: ENV['YOUR_PHONE_NUMBER']) # twilioに登録した電話番号 message.hello(user: user) end完成です!
- 投稿日:2020-12-12T12:18:08+09:00
Ruby on Railsのbundle installで躓いたときの解決法
はじめに
Ruby on Railsチュートリアルにて初めてのアプリケーションを作成していたところ、bundle installが上手くいかずエラーが出ました
ある方法を試したところ、無事この画面に辿り着けました!
今回、私が試した方法をご紹介します。何があった
Ruby on Railsチュートリアル第1章で、hello_appディレクトリにbundleをインストールしようとしたところ
$ bundle install The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for.と出てしまい、インストールされなかった模様。
どうする?
色々探してみた結果、今回はこちらのサイトを参考に、
Gemfile.lockのファイルを削除する
という方法を取ってみることにしました。ざっくりまとめると、バージョンのちょっとした違いによってかかってしまうlockを一旦解除する、ということなのかなと解釈しました。
どうやった?
Gemfile.lockはファイルナビゲーターのhello_appディレクトリ内にありましたので、右クリック→ Deleteで削除。
これだけです。
ちなみにGemfile.lockに関しては削除しても再度bundleをインストールするとまた作成されるとのことです。無惨様かよ。
こうなった
そして改めて
$ bundle installすると・・・
$ bundle install Fetching gem metadata from https://rubygems.org/............おぉっ!さっきとは文章が変わった!!
そしてPreview → Preview Running Appricationで
画面を表示させてみると・・・はい、出ました!
パチパチ
まとめ
bundle install 時のエラーは、Gemfile.lockファイルを削除することで解消できる場合がある。
です。
間違ってたらごめんなさいw
- 投稿日:2020-12-12T12:11:03+09:00
if文について
最初に
カレンダー企画2020の12日目
プログラミングの勉強を始めて3ヵ月程経ったので学んだことのメモをアウトプットとして記事に残します。
これからプログラミングの世界に入る人の手助けになれたら嬉しい限りです。
間違っていたり、言葉が違っていたり、誤解されるような言葉があったら教えてください^^
言葉を長々と読みづらかったら申し訳ありません。少しずつなれてがんばります。if文についてまとめてみる
if文??
if文とは、「もしAならBを実行、AでないならCを実行」といったように、条件や状況に応じて実行内容を変える条件分岐で使用するもの
書き方と言葉で表すと、、、
if 条件 処理 endこれは
条件に当てはまる(true)なら処理の内容が実行されます。
条件に当てはまらない(false)なら処理の内容は行われない。ここで条件を記述する上でさまざまな条件をつける為に「比較演算子」「論理演算子」があるのでまとめていきます。
比較演算子
< #右辺の方が大きい <= #右辺の方が大きい、または等しい( "≦" これと同じだと私は認識しています。) > #左辺の方が大きい >= #左辺の方が大きい、または等しい( "≧" これと同じだと私は認識しています。)右辺と左辺を比較してそれに伴って処理を変える時に使う。
論理演算子
! #否定 && #両方の条件が正しいならtrue( "and" という意味ですね。) || #片方の条件が正しいならtrue( "or" という意味ですね。) == #右辺と左辺が等しい(数学でいう "=" という意味ですね。) != #右辺と左辺が等しくない(数学でいう "≠" という意味ですね。)私は比較演算子や論理演算子を自分の認識(カッコ内)で置き換えて少し覚えやすくしました!
elsif / else
これはifを記述する時によく出てくるもので意味としては、
if文の条件に合わなかった時(false)で行う処理を設定できる。if 条件 処理A else 処理B end「条件がtrueならば処理Aを行う。falseならば処理Bを行う。」
if 条件1 処理A elsif 条件2 処理B elsif 条件3 処理C . . . elsif 条件n 処理x else 処理z endelseでは1つの条件に対して条件分岐を行いましたが、
elsifでは条件を無限に書くことができます。(感覚的にif文をたくさんつなげて1つにまとめた!みたな)最後に
if文についてまとめてみました。他にも条件分岐という観点ではたくさん書き方があるようです。
個人的にif文が苦手で使いこなせるまで時間がかかったのでまとめて整理しました。
- 投稿日:2020-12-12T10:22:01+09:00
【rails】ActiveSupportの期間指定メソッドを使ってコードがスッキリした話
お久しぶりです。スージーです。
今日はrailsでスパゲッティコードを便利メソッドでキレイにしたよという話です。環境
- ruby 2.6.6
- rails 5.2.3
参考
【知らずに損した】ActiveSupportの期間指定メソッドall_day, all_week, all_month, all_year
Active Support コア拡張機能今週の日曜日〜土曜日の期間でデータを取得したい時
使うメソッドとしては
beginning_of_weekとend_of_weekを使って今週の日曜日と今週の土曜日を取得してみましょう。# 今週日曜日(日曜始まり)を取得するメソッド rb(main):001:0> Date.today.beginning_of_week => Mon, 07 Dec 2020 # これだと月曜始まりで取得してしまうので-1します rb(main):002:0> Date.today.beginning_of_week - 1 => Sun, 06 Dec 2020 # 日曜日が取れました!同じように土曜日を取得しましょう
# 今週土曜日を取得するメソッド rb(main):003:0> Date.today.end_of_week - 1 => Sat, 12 Dec 2020 # 土曜日が取れました!次に日曜日〜土曜日までのデータを取得してみる
今回はStudyモデルというTBLに
id,time,total,user_id,created_atカラムを持つ学習時間を記録するTBLを例に考えます
カラム タイプ id digint time float total float user_id integer created_at datetime このテーブルに以下のデータが入っていると想定します
irb(main):002:0> Study.all Study Load (0.6ms) SELECT `studies`.* FROM `studies` LIMIT 11 => #<ActiveRecord::Relation [#<Study id: 2, time: 0.5, total: 0.5, user_id: nil, created_at: "2020-12-05 11:09:38", updated_at: "2020-12-05 11:09:38">, #<Study id: 3, time: 1.5, total: 2.0, user_id: nil, created_at: "2020-12-07 11:09:42", updated_at: "2020-12-07 11:09:42">, #<Study id: 4, time: 2.0, total: 4.0, user_id: nil, created_at: "2020-12-07 11:09:49", updated_at: "2020-12-07 11:09:49">, #<Study id: 5, time: 0.5, total: 4.5, user_id: nil, created_at: "2020-12-07 11:26:38", updated_at: "2020-12-07 11:26:38">, #<Study id: 6, time: 1.0, total: 5.5, user_id: nil, created_at: "2020-12-07 11:27:31", updated_at: "2020-12-07 11:27:31">, #<Study id: 7, time: 0.5, total: 6.0, user_id: nil, created_at: "2020-12-07 23:16:04", updated_at: "2020-12-07 23:16:04">, #<Study id: 8, time: 1.5, total: 7.5, user_id: nil, created_at: "2020-12-07 23:18:49", updated_at: "2020-12-07 23:18:49">]>id2~8までの7件のレコードが存在しています(id1が歯抜けしているのは無視して下さいw)
このデータがある状態で先程のメソッドを使って期間を今週に絞ってデータを取得してみたいと思います。
irb(main):003:0> Study.where(created_at: Date.today.beginning_of_week - 1..Date.today.end_of_week - 1).sum(:time) (4.1ms) SELECT SUM(`studies`.`time`) FROM `studies` WHERE `studies`.`created_at` BETWEEN '2020-12-06' AND '2020-12-12' => 7.0whereでcreated_atが今週日曜日(12/6)〜今週土曜日(12/12)までの7日間のデータを取得して、sumメソッドでtimeカラムの合計を計算します
スパゲッティコードを書く
まず私が最初に書いたスパゲッティコードで書きますw
# studies_controller.rb ~省略~ def index @today = Date.today @this_week_total_time = Study.where(created_at: @today.beginning_of_week - 1..@today.end_of_week - 1).sum(:time) end ~省略~controllerにこんな書いてたらどんどんfatになっていく予感しかしないですし、汚いコードですね
リファクタリング1
モデルメソッドを使ってcontrollerの見通しをよくします
# studies_controller.rb ~省略~ def index @this_week_total_time = Study.this_week_total end ~省略~ # models / study.rb ~省略~ def this_week_total @today = Date.today self.where(created_at: @today.beginning_of_week - 1..@today.end_of_week - 1).sum(:time) end ~省略~ロジック部分をモデルに移行したので、コントローラーがスッキリしました!
本題railsの便利メソッドを使う
コントローラーはキレイになりましたが、モデルメソッドが冗長です
そこでrailsが用意してくれているall_weekメソッドを使ってリファクタリングしましょう# models / study.rb ~省略~ def this_week_total @today = Date.today +@range = @today.all_week(:sunday) ← 追加 self.where(created_at: @range).sum(:time) end ~省略~all_weekは引数を取ることで任意の曜日始まりにできます.今回は日曜始まりにしたいので
(:sunday)を渡します
最初のコードに比べると大分キレイなコードになりました!
以前のコードだとbeginning_of_week - 1なので、「週の始まりの日付を取得しているけど、-1しているから~えーっと、結局何曜日なの!?」って何ヶ月後の自分が見たら思うでしょうw
リファクタリングした@range = @today.all_week(:sunday)であれば「日曜始まりで期間が今週なんだな」と直感的に分かるようになりました念の為、確認してみましょう
irb(main):006:0> @today = Date.today => Wed, 09 Dec 2020 irb(main):007:0> @range = @today.all_week(:sunday) => Sun, 06 Dec 2020..Sat, 12 Dec 2020 irb(main):008:0> Study.where(created_at: @range).sum(:time) (0.5ms) SELECT SUM(`studies`.`time`) FROM `studies` WHERE `studies`.`created_at` BETWEEN '2020-12-06' AND '2020-12-12' => 7.0ちゃんと指定した期間のデータを取得する事ができました!
公式リファレンスに詳しく書いているので、こちらも合わせて読んでみて下さい!!終わり
- 投稿日:2020-12-12T06:38:15+09:00
Homebrew の初期化ができない場合
本記事の内容
Homebrewの初期化をする際のエラーを共有し、初学者の方に役立てればと思い作成しました。
エラーコード
initdb: error: directory "/usr/local/var/postgres" exists but is not empty If you want to create a new database system, either remove or empty the directory "/usr/local/var/postgres" or run initdb with an argument other than "/usr/local/var/postgres". Data page checksums are disabled.エラーコードの意味
ディレクトリ "/usr/local/var/postgres" は存在しますが、空ではありません。
新しいデータベースシステムを作成したい場合は
ディレクトリ"/usr/local/var/postgres "を指定するか、initdbを実行します。
に"/usr/local/var/postgres "以外の引数を指定してください。解決方法
rm -rf /usr/local/var/postgresを実行した後に再度、initdb /usr/local/var/postgres -E utf8を実行すると、、、Success. You can now start the database server using:
- 投稿日:2020-12-12T06:38:15+09:00
PostgreSQL の初期化ができない場合
本記事の内容
PostgreSQLの初期化をする際のエラーを共有し、初学者の方に役立てればと思い作成しました。
エラーコード
initdb: error: directory "/usr/local/var/postgres" exists but is not empty If you want to create a new database system, either remove or empty the directory "/usr/local/var/postgres" or run initdb with an argument other than "/usr/local/var/postgres". Data page checksums are disabled.エラーコードの意味
ディレクトリ "/usr/local/var/postgres" は存在しますが、空ではありません。
新しいデータベースシステムを作成したい場合は
ディレクトリ"/usr/local/var/postgres "を指定するか、initdbを実行します。
に"/usr/local/var/postgres "以外の引数を指定してください。解決方法
rm -rf /usr/local/var/postgresを実行.initdb /usr/local/var/postgres -E utf8を実行。Success. You can now start the database server using:
- 投稿日:2020-12-12T01:43:27+09:00
RailsのHTTPステータス
分類
- 情報レスポンス (
100~199)- 成功レスポンス (
200~299)- リダイレクト (
300~399)- クライアントエラー (
400~499)- サーバエラー (
500~599)↓下記サイトで適宜確認する
MDN web docs - HTTP レスポンスステータスコード書き方
# シンボルを使う render json: @user, status: 201 or render json: @user, status: :created render status: 500 or render status: :internal_server_errorステータスコードのみ返す# リクエストが正常に処理された head :ok # リクエエストが不正 head :bad_request def destroy @user.destroy head 204 endコンソールで確認
pp Rack::Utils::SYMBOL_TO_STATUS_CODE {:continue=>100, :switching_protocols=>101, :processing=>102, :early_hints=>103, :ok=>200, :created=>201, :accepted=>202, :non_authoritative_information=>203, :no_content=>204, :reset_content=>205, :partial_content=>206, :multi_status=>207, :already_reported=>208, :im_used=>226, :multiple_choices=>300, :moved_permanently=>301, :found=>302, :see_other=>303, :not_modified=>304, :use_proxy=>305, :"(unused)"=>306, :temporary_redirect=>307, :permanent_redirect=>308, :bad_request=>400, :unauthorized=>401, :payment_required=>402, :forbidden=>403, :not_found=>404, :method_not_allowed=>405, :not_acceptable=>406, :proxy_authentication_required=>407, :request_timeout=>408, :conflict=>409, :gone=>410, :length_required=>411, :precondition_failed=>412, :payload_too_large=>413, :uri_too_long=>414, :unsupported_media_type=>415, :range_not_satisfiable=>416, :expectation_failed=>417, :misdirected_request=>421, :unprocessable_entity=>422, :locked=>423, :failed_dependency=>424, :too_early=>425, :upgrade_required=>426, :precondition_required=>428, :too_many_requests=>429, :request_header_fields_too_large=>431, :unavailable_for_legal_reasons=>451, :internal_server_error=>500, :not_implemented=>501, :bad_gateway=>502, :service_unavailable=>503, :gateway_timeout=>504, :http_version_not_supported=>505, :variant_also_negotiates=>506, :insufficient_storage=>507, :loop_detected=>508, :bandwidth_limit_exceeded=>509, :not_extended=>510, :network_authentication_required=>511}参考URL
- 投稿日:2020-12-12T01:05:58+09:00
【React】Railsでsaveされた時に、Reactでサクセスメッセージを表示
個人のブログで、ReactとRailsでDBとやりとりする記事を作りました
フロントReact、バックRailsでデータベースに保存する
某プログラミングスクール(◯MM)で課題で出されたものをReactで作ってみて、そこにサクセスメッセージを出そう、と言うのが今回の目的です。
メモ書き程度で書いていきます。
完成後の動作
Reactでサクセスメッセージを出せるようにしました pic.twitter.com/TjBkS0008y
— きたやまかつや (@kitakatsu1992) December 11, 2020フォーム内容の保存に成功するとサクセスメッセージが呼び出されます。
流れとしては、
- stateを作る
- createが呼ばれsaveされたらstateを変更する
- stateをコンポーネントに渡してメッセージを表示させる
こんな感じです。
stateを作る
state = { books: [], successCreate: false }successCreateと言うstateを作りました。
ここは初期値はfalseとして、createが呼ばれたらtrueとします。createが呼ばれsaveされたらstateを変更する
createBook = (title, body) => { axios .post('http://localhost:3001/books', { title: title, body: body}) .then((response) => { const newData = update(this.state.books, { $push: [response.data]}) this.setState({books: newData, successCreate: true}) }) }Rails側でbooksコントローラーのcreateを呼び出し、保存されたデータはbooksに追加し、successCreateはtureに変更します。
ちなみにbooksにはBookモデルのデータが全て入っています。stateをコンポーネントに渡してメッセージを表示させる
このsuccessCreateの値をコンポーネントに渡します。
<BookCreateForm createBook={this.createBook} successCreate={this.state.successCreate} />受け取った先で、stateがtrueの時にメッセージを表示するよう記述します。
{this.props.successCreate && ( <p style={{color: '#16de69', fontSize: 6}}>Book was successfully created.</p> )}これでBookがcreateされ、stateが変更した時にメッセージが出るようになりました。
react側とrails側でバリデーションをかけてより安全性を高めれば、思いがけないメッセージの表示はなくなるかと。
忘備録的なものなのでとりあえず動いた時点で記事にしております、あしからずです。
- 投稿日:2020-12-12T00:58:53+09:00






























