【Rails】active_hashを使う!
フリマアプリを制作中で、active_hashを使用する機械があったので備忘録として残しておきます。これから実装する方の参考になれば幸いです。
active_hashとは?
わざわざテーブルを作成しなくても、読み込み専用情報をまとめたハッシュを扱うことができるものです。テーブルを持つほどでもない、静的なデータ(都道府県情報など不変なもの)を扱う時には便利です。 DBに変動が起きないデータをmodelに保存している場合、すぐ入れ替えることが可能でgemを導入して使用します。
導入
gemをbundleinstallします。
gem 'active_hash'
モデル(擬似モデル)を作成する
モデルを作成しますが、「rails g model~」を使用しないでモデルを手動で作成します。maigrationファイルでカラムの設定等をしない。ここが擬似モデルと言われる理由だと思います。今回はmodelに直接ファイルを作成する方法が紹介されている方法を使用します。
①appのmodelフォルダに移る
②modelフォルダ内に作成したい名前でモデルファイルを作成する
gyazo.com
モデル内の記述
①自分でモデルファイルを作成したので、当然中身は何もありません。「ActiveHash::Base」を継承して下記のようにクラスを設定します。
class Shipping < ActiveHash::Base end
②モデル内に呼び出す静的データを記述します。
{カラム名: 値, カラム名:値}をハッシュ形式で作成しています。都道府県等どれだけ多い情報でも同様の記述で対応が可能です。
class Shipping < ActiveHash::Base self.data = [ {id: 1, name: "1日〜2日で発送"}, {id: 2, name: "2日〜3日で発送"}, {id: 3, name: "4日〜7日で発送"}, ] end
③アソシエーションを組む
アソシエーションを組む時は通常とは少し違っているので注意が必要です。記述場所はそれぞれのmodelファイルで問題ありません。
1, has_manyの場合(今回はproducts.rbとアソシエーションを組んでいます)
include ActiveHash::Associations has_many :products
2, belongs_toの場合
extend ActiveHash::Associations::ActiveRecordExtensions belongs_to_active_hash :shipping
viewファイルに記述する
viewファイルにcollection_selectを使って呼び出すようにします。書き方は下記の通りです。
1、「shipping_id」: form_withで送信先で登録されるレコードのカラム名を指します。
2、「shipping.all」: 擬似モデルの全ての情報を呼び出しています。
3、 {include_blank: "○○"} : セレクトボックスの中に文字列を表示させる事ができます
4、「:id, :name」 : 表示させるidとnameらしいですが、書き方として覚えてます。
5、「{class: '〇〇'}」 : クラスを設定する時は{}をつけるようにします。
= form.collection_select :shipping_id, Shipping.all, :id, :name, {include_blank: "選択してください"}, {class: '〇〇'}
【Rails × jQuery】モーダルウィンドウの実装の仕方について
レビュー(口コミ)機能を実装しましたが、見た目にださかったこともあり
簡易的なモーダル機能を使ってそれっぽくしてみました。参考になれば幸いです。
実装後
ボタンを押すとモーダルが立ち上がり、「よかった点」と「わるかった点」を書いて投稿が
できるというものです。Ajaxはすでに実装しているのでモーダルのコードを記述するだけで
結構簡単にできました
gyazo.com
コントローラー
respnd_to doを使って非同期の処理をしています。
class ReviewsController < ApplicationController def create @review = Review.create(review_params) respond_to do |format| format.html { redirect_to "/matches/#{@review.job_id}.reviews" } format.json end end end
ビューファイル(実装前)
.Review-wrapper__form =form_with model: [match, review], id: "new-comment", local: true do |form| .Review-box .Review-box__good 【よかった点】 = form.text_area :good, maxlength: 250, class: 'Review-box__text', placeholder: 'ここに文章を入力してください' .Review-box__bad 【わるかった点】 = form.text_area :bad, maxlength: 250, class: 'Review-box__text', placeholder: 'ここに文章を入力してください' .Review-button = form.submit '投稿する', class: 'Review-button__submit'
ビューファイル(実装後)
最下部にテンプしている記事を参考に次のようにコードを記入しています。モーダルのテンプレートの中にform_withを入れるだけで簡単にできます。
記事だとbootstrapも導入していますが、私の場合自分でcsswo書いていたので今回は
bootstrapの記述は省いて記載しました。
参考にした記事のコード
gyazo.com
%button{"data-target" => "#post", "data-toggle" => "modal", :type => "button"} つぶやきを投稿する #post.modal.fade{"aria-hidden" => "true", :role => "dialog", :tabindex => "-1"} .modal-dialog{:role => "document"} .modal-content -#↓ここに任意のform_withを記入する =form_with model: [match, review], id: "new-comment", local: true do |form| .Review-wrapper__form .Review-post .Review-box .Review-box__good 【よかった点】 = form.text_area :good, maxlength: 250, class: 'Review-box__text', placeholder: 'ここに文章を入力してください' .Review-box__bad 【わるかった点】 = form.text_area :bad, maxlength: 250, class: 'Review-box__text', placeholder: 'ここに文章を入力してください' .Review-button = form.submit '投稿する', class: 'Review-button__submit' -#↓閉じるボタンは記事からそのままコピーする %button{"data-dismiss" => "modal", :type => "button", class: 'Review-button__close'} 閉じる
これでモーダルができました!
bootstrapを使用すればもっとよかったとは思いますのでこれから勉強していきます。
参考記事
www.techry.net
【Rails】 ページネーションの実装 (ページングしても内容が重複して表示されてうまくページングができない場合の解決法)
railsでページネーションを実装しています。
他の記事でも紹介されていたのを参考に、自分でも実装をしてみましたが、実装したページングのページをめくっても同じ画面が表示されてしまいました。
簡単ですが、そんな時の解決法を紹介します。ページネーションの実装の方法は他に記事が多くありますので最下部に参考がありますのでそちらをご参照ください。
1 kaminariジェムのインストール
gem 'kaminari'
2 bundle installを入力してインストールします。
% bundle install
3 view画面に「= paginate matches」を記入します。
(今回はhamlで記入、部分テンプレートを使用しているので@matchesではなくmatchで使用しています。)
.Under-wrapper .Bar-left .Bar-left__upper .Bar-left__upper--title 応募可能な全てのお仕事を公開しています .Bar-left__upper--text = paginate pages ←ここを追加します
3-1該当するコントローラーにコードを追加します。←ここがポイントでした
記事を参考に私が書いたコードです。@pagesの部分がページングで必要なコードです。
class MatchesController < ApplicationController def index @matches = Job.all.order("created_at DESC") @pages = Job.all.page(params[:page]) end
確かにこれでも下記のように表示はされますが,いざページをめくってみても表示される項目は一緒(重複)の状態でした.....
3-2私の場合すでに@matchesでJobの一覧を表示していましたが、インスタンス変数をもう一つ作成(@pages)して値を呼ぼうとしていました。これが間違いで@matchesで作成したものに「.page(params[:page])」を追加すれば無事にページングもしてくれるようになりました。
class MatchesController < ApplicationController def index @matches = Job.all.order("created_at DESC").page(params[:page]).per(3) end
ローカル変数も「pages」から「matches」に変更します。
.Under-wrapper .Bar-left .Bar-left__upper .Bar-left__upper--title 応募可能な全てのお仕事を公開しています .Bar-left__upper--text = paginate matches ←ここを追加します
これで解決しました!
.per()などの説明は下記の参考記事等をご覧ください。
ページングのデザインの変更方法も記事をご覧ください。
参考記事
公式:
github.com
わかりやすいページネーションの実装の仕方
qiita.com
設定変更のあれこれ
nekorails.hatenablog.com
間違いに気付いた記事
stackoverflow.com
■
アプリを作成後、rails sを押した時にこんなエラーがでてしまったので
備忘録として残しておきます。
エラー内容は下記の通り。
ActiveRecord::PendingMigrationError ( Migrations are pending. To resolve this issue, run: rails db:migrate RAILS_ENV=development ):
指定された、コマンドを打っても解決しない、、、、、、どうするべきか?
まずDBのステータスをみます。(rails db:migrate:status)
chat-space % rails db:migrate:status database: chat_space_development Status Migration ID Migration Name -------------------------------------------------- down 20200726062225 Devise create users down 20200728052202 Create groups down 20200728053005 Create group users down 20200731034659 Create messages up 20200822044159 ********** NO FILE ********** up 20200825150117 ********** NO FILE ********** up 20200825150130 ********** NO FILE ********** up 20200826133011 ********** NO FILE **********
なんじゃこれ?となってしまいましたが、
ここで「rails db:reset」コマンドを入力します。
このコマンドを押すと、DBの中のデータが全て消えてしまうので注意が必要。
hat-space % rails db:migrate:status database: chat_space_development Status Migration ID Migration Name -------------------------------------------------- up 20200726062225 Devise create users up 20200728052202 Create groups up 20200728053005 Create group users up 20200731034659 Create messages
結果としてdownの状態になっていたものがUpに変更になりました。
これでrails sを押してサーバーを立ち上げることができました!
rails db:migrate実行時にreferencesを使った外部キー制約ができない時の対処法について
個人アプリを制作している時にmySQLでテーブルを作成しようとすると
rails で外部キー制約をかける時にエラーが発生したので、その対処法についてご紹介します。
外部キーの設定をしようとした時に、referencesを使用してrails db:migrateをかけたところエラーが発生しました。1対多と多対多のリレーションでも同じようなエラーが発生します。
class CreatePrJobs < ActiveRecord::Migration[6.0] def change create_table :pr_jobs do |t| t.references :pr, foreign_key: true t.references :job, foreign_key: true t.timestamps end end end
エラー内容
== 20200905041353 CreatePrJobs: migrating ===================================== -- create_table(:pr_jobs) rails aborted! StandardError: An error has occurred, all later migrations canceled: Column `pr_id` on table `pr_jobs` does not match column `id` on `prs`, which has type `bigint(20)`. To resolve this issue, change the type of the `pr_id` column on `pr_jobs` to be :bigint. (For example `t.bigint :pr_id`). Original message: Mysql2::Error: Cannot add foreign key constraint /Users/shunjiro/rails-self-project/Dispatch-site/db/migrate/20200905041353_create_pr_jobs.rb:3:in `change' /Users/shunjiro/rails-self-project/Dispatch-site/bin/rails:9:in `<top (required)>' /Users/shunjiro/rails-self-project/Dispatch-site/bin/spring:15:in `<top (required)>' bin/rails:3:in `load' bin/rails:3:in `<main>'
色々と調べると下記が原因とわかりました。
原因
- デフォルトのidカラムはinteger型で作成されるが、rails5.1以降からはbignit型で作成される
- referencesをつかった書き方だと型が合致せず、エラーとなるので揃えてやる必要がある。
対処方法
- referencesをつかう時にidキーをinteger型に変更する
- referencesを使わない外部キー設定にする (参考記事をご参考ください)
2番目の方法を試すとがなぜかダメでした、仕方なく1番目のreferencesを使わない書き方で
rails db:migrateを実行したところ解決しました!
class CreatePrJobs < ActiveRecord::Migration[6.0] def change create_table :pr_jobs do |t| t.integer :pr_id, foreign_key: true t.integer :job_id, foreign_key: true t.timestamps end end end
今までreferencesで設定できていましたが突然できなくなってしまったので、
勝手にバージョンを上げてしまったことが原因だと思います。
参考記事:
qiita.com