- 投稿日:2019-12-21T23:00:30+09:00
[Rails]特定のインスタンスに対して前後のレコードを取得したりランダムで取得したりするあれを試してみた
はじめに
こんにちはどうも、pirikaraです。
髪の毛を切りました。特定の投稿(今回はitemの出品)に関して、DBから前後のレコードを取得して表示させたりリンクを飛ばす感じのあれです。
あとDBからランダムにレコードを取得して表示させたりリンク飛ばしたりする感じのあれです。まずは特定の投稿に関してDBから前後レコードを取得する奴から実装していきます。
Rails標準のAPIでは見つからなかったので、今回はmodelに対してメソッドを書き込んでいきます。いざ、実装
今回はItemクラスのインスタンスに関して、その前後レコードを取得するメソッドをmodels/item.rbに記述していきます。
前のレコードを取得するメソッドを『previous』
後のレコードを取得するメソッドを『next』
としてmodelに定義していきます。item.rbclass Item < ApplicationRecord #......省略 def previous Item.where("id < ?", self.id).order("id DESC").first end def next Item.where("id > ?", self.id).order("id ASC").first end end現在のインスタンス(self)のidより大きいか小さいかで前後レコードを判定・取得します。
作成したメソッドをview側で呼び出します。items/show.haml#......省略 - if @item.previous.present? =link_to item_path(@item.previous.id) do = @item.previous.name - else - else .none - if @item.next.present? =link_to item_path(@item.next.id) do = @item.next.name - else .none #......省略controller側で@item = Item.find(params[:id])などとし、Itemのshow画面に遷移。
@itemに対して『previous』 『next』メソッドを使用することで、@itemの前後レコードを取得できます。また、前後レコードがない場合(最新のレコード、もしくは最古のレコードの場合)にリンクを表示しないよう『present?』メソッドによって真偽判定、条件分けしています。
左右感がちょっと気持ち悪いですが、実装できました。(あとで直します。)
変化球
前後レコードではなく、DB内のデータをランダムで取得するあれを実装を試みてみます。
ネットサーフィンしながらいくつか方法を見つけたので試してみます。1. RAND()関数
MySQLのネイティブ関数RAND()を使用してみます。
items_controller.rbdef show #......省略 @random1 = Item.order("RAND()").limit(1) @random2 = Item.order("RAND()").limit(1) #......省略 end左右のリンクがあるので、それぞれ@random1、 @random2として変数をインスタンス変数を定義してみました。
viewはこちらitems/show.haml- if @random1.present? =link_to item_path(@random1.ids) do - @random1.each do |random1| = random1.name - else .none - if @random2.present? =link_to item_path(@random2.ids) do - @random2.each do |random2| = random2.name - else .noneRAND()関数で取得したデータにlimitつけてましたが、配列で取得されるみたいなので『ids』としないとid取れませんでした。
また、nameについてもeach文で取り出してあげないと表示されませんでした悲しい。そして結果がこちら。
......ねこもうさぎも被りました。このあと何回もページ遷移してみました。
確かにランダムで表示されるようにはなったようですが、左右の値が毎回同じでした。
実際にDBテーブル内に存在する値からランダムに取得してくれるのはありがたいですが、
randam1とrandam2で別々に値を取得してくれるなんてそんな都合よく世界はできていなかったようです。別の方法を試します。
2. Model.all.sample
モデルから全てのレコードを取得した上で1件抽出する感じ。
ゴリ押ししてみます。items_controller.rbdef show #......省略 @random1 = Item.all.sample @random2 = Item.all.sample #......省略 enditems/show.haml- if @random1.present? =link_to item_path(@random1.id) do = @random1.name - else .none - if @random2.present? =link_to item_path(@random2.id) do = @random2.name - else .none今回は配列でなくデータ単体を取ってこれたので、idsとかeach文なんてまどろっこしいことをせずに済みました。やったね。
気になる結果は......
で!!!け!!!た!!!
random1とrandom2で別々の値が取ってこれてます。さすがゴリ押し。
これにて実装完了......と思ったその時。見つけてしまいました。ActiveRecord でランダムなレコードが欲しい(1件、複数件)
『全件取ってランダムに1件取り出すのはダサい』
.........ダサい???
確かに全部とってランダムに1件はメモリやらなんやらに理解の浅い僕でも効率が悪いのは理解できます。
こういう時にindexが便利なのか......?とにかくダサいのは嫌なので別の方法を試します。(終わりが見えない)
3. Model.offset(rand(Model.count)).limit(1)
記事の方法をパクり...参考にさせていただきました。ありがとうございます。
レコード未満のランダム生成された整数をoffsetでレコード取得の開始位置とし、1個だけデータを取ってくる感じです。items_controller.rbdef show #......省略 @random1 = Item.offset( rand(Item.count) ).limit(1) @random2 = Item.offset( rand(Item.count) ).limit(1) #......省略 enditems/show.haml- if @random1.present? =link_to item_path(@random1.ids) do - @random1.each do |random1| = random1.name - else .none - if @random2.present? =link_to item_path(@random2.ids) do - @random2.each do |random2| = random2.name - else .none......each文でないと取り出せませんでした......idsも復活しました......
しかしoffsetで開始を指定している分、Model.all.sampleの時よりはスマートなデータ取得ができている気がします。
さて結果は......
......ランダムなってるやん。
さすがスマート。『自分のデータは除いて......』の実装はしていないのでGIFでは可愛いうさぎが延々と出現してしまっていますが、
きちんとランダムにリンクが生成されています。これで終わりにしようと思いましたが、僕は根に持つタイプなのでダサくない方法をもう一つ考えてみます。
4. Model.where('id >= ?', rand(Model.first.id..Model.last.id)).limit(1)
offset、 limitを使った書き方の書き換えとしてwhereに置き換える方法が紹介されていたので、試してみます。
randの引数でランダム数値生成の範囲指定を行いますが、今回は先頭レコードと最終レコードのidを範囲として指定しています。Rails: データベースのパフォーマンスを損なう3つの書き方(翻訳)
items_controller.rbdef show #......省略 @random1 = Item.where('id >= ?', rand(Item.first.id..Item.last.id)).limit(1) @random2 = Item.where('id >= ?', rand(Item.first.id..Item.last.id)).limit(1) #......省略 enditems/show.haml- if @random1.present? =link_to item_path(@random1.ids) do - @random1.each do |random1| = random1.name - else .none - if @random2.present? =link_to item_path(@random2.ids) do - @random2.each do |random2| = random2.name - else .noneこちらもeach文、idsを用いて配列からデータを取り出して出力しています。
結果は......
ランダムになってました。満足。
比較
rails consoleからSQL文とSQL発行の所要時間が確認できるので、
上記4つのものを確認・比較してみます。......DBにデータが7つしかないので速さは大差ないですね。そりゃそうか。
SQL文は4個目では3回発行されています。あまりよろしくないですね......
スマートな実装としては3個目推奨でしょうか。という訳でseeds.rbを読み込んでデータを1000件作ってみました。
seeds.rb1000.times do |index| Item.create!(name: "アイテム#{index}", seller_id: 1, description: "内容#{index}", category_id: index, condition_id: index, prefecture_id: index, sendingmethod_id: index, postageburden_id: index, shippingday_id: index, price: index, profit: index) endSQL発行の所要時間に大きく差が出ました。
1個目、2個目は3個目、4個目に比べて10倍以上の時間がかかってしまっています。
クエリ文が3回発行されてしまっていることを考えると、
今回試した手法の中ではoffsetを用いた3番目の方法がベストプラクティスとなります。おわりに
今回はSQLについて理解を深めることができました。
Indexを用いた検索でも検証を行ってみたいですね。
大規模なWebアプリケーションになればなるほど『どんな手法で検索をするか』で処理スピードに大きな差が生まれてしまうことを実感できました。また気が向いたらなんか書きます。
おわり。
- 投稿日:2019-12-21T21:55:53+09:00
Railsチュートリアル 第13章 ユーザーのマイクロポスト - 「マイクロポストが投稿日時の降順(=新しい順)に表示されるようにする」という実装を、Micropostモデルに追加する
マイクロポストの順序付けに対するテスト
まず、「最も新しいマイクロポストが、RDBから最初に取り出されるようにする」を確認するためのテストを書いていきます。
まず準備段階として、「fixture上に存在する、
most_recent
という識別子を持ったマイクロポストが最初に表示されるようにする」というテストを実装します。test "order should be most recent first" do assert_equal microposts(:most_recent), Micropost.first end必要なfixtureが定義されていないため、現時点でテストは成功しない
上記テストを実装した時点でテストを実行してみます。
# rails test test/models/micropost_test.rb Running via Spring preloader in process 1532 Started with run options --seed 54438 ERROR["test_order_should_be_most_recent_first", MicropostTest, 0.8859796000033384] test_order_should_be_most_recent_first#MicropostTest (0.89s) StandardError: StandardError: No fixture named 'most_recent' found for fixture set 'microposts' test/models/micropost_test.rb:29:in `block in <class:MicropostTest>' 5/5: [===================================] 100% Time: 00:00:00, Time: 00:00:00 Finished in 0.89262s 5 tests, 4 assertions, 0 failures, 1 errors, 0 skipsStandardError: No fixture named 'most_recent' found for fixture set 'microposts'「
most_recent
という名前のfixtureが存在しない」というエラーメッセージですね。必要なfixtureを定義する
まずは、必要なfixtureを定義する必要があります。対象のファイルは
test/fixtures/microposts.yml
です。test/fixtures/microposts.ymlorange: content: "I just ate an orange!" created_at: <%= 10.minutes.ago %> tau_manifesto: content: "Check out the @tauday site by @mhartl: http://tauday.com" created_at: <%= 3.years.ago %> cat_video: content: "Sad cats are sad: http://youtu.be/PKffm2uI4dk" created_at: <%= 2.hours.ago %> most_recent: content: "Writing a short test" created_at: <%= Time.zone.now %>「
most_recent
という識別子を持ったマイクロポストが、最も新しいcreated_at
の値を持つ」という内容になっていますね。fixture内では、マジックカラムの値を手動で更新することができる
「埋め込みRubyを使って
created_at
に直接値を設定している」というのは、test/fixtures/microposts.yml
における重要なポイントです。通常、
created_at
やupdated_at
といったマジックカラムには、直接値を設定することはできません。これらの属性に対する値は、通常はRailsによって自動設定されるものです。しかしながら、fixtureファイル中においては、これらの属性に対する値を直接設定することが可能なのです。必要なfixtureを定義したところで、再びテストを実行してみる
# rails test test/models/micropost_test.rb Running via Spring preloader in process 1559 Started with run options --seed 16916 FAIL["test_order_should_be_most_recent_first", MicropostTest, 0.3459459000005154] test_order_should_be_most_recent_first#MicropostTest (0.35s) --- expected +++ actual @@ -1 +1 @@ -#<Micropost id: 941832919, content: "Writing a short test", user_id: nil, created_at: "2019-12-21 09:08:30", updated_at: "2019-12-21 09:08:30"> +#<Micropost id: 12348100, content: "Sad cats are sad: http://youtu.be/PKffm2uI4dk", user_id: nil, created_at: "2019-12-21 07:08:30", updated_at: "2019-12-21 09:08:30"> test/models/micropost_test.rb:29:in `block in <class:MicropostTest>' 5/5: [===================================] 100% Time: 00:00:00, Time: 00:00:00 Finished in 0.94467s 5 tests, 5 assertions, 1 failures, 0 errors, 0 skipsテスト失敗時のメッセージに変化がありました。「最も新しいマイクロポストが、最初に取り出されていない」という趣旨のメッセージが出力されています。
「最も新しいマイクロポストが、RDBから最初に取り出されるようにする」という実装
Railsの
default_scope
メソッドをMicropostモデルで呼び出せば、マイクロポストを常に特定の順番で取り出せるようになります。「新しい順に取り出す」という場合は、「created_at
の降順に取り出す」ようにします。4.0以降のRailsでは、以下のように記述すれば、「
created_at
の降順に取り出す」という取り出し順序を実現できます。default_scope -> { order(created_at: :desc) }「ラムダ式(もしくは無名関数)」なる文法要素
Rubyにおいて、
->
(もしくはlambda
)というのは、「与えられたブロックから手続きオブジェクト(Procのインスタンス)を生成して返す」という関数です(Rubyリファレンスマニュアルより)。>> -> { puts "foo" } => #<Proc:0x00007f086c61bba8@(irb):1 (lambda)> >> -> { puts "foo" }.call foo => nil重要なのは以下の点でしょうか。
-> { puts "foo" }
という呼び出しは、Procオブジェクトを返す- Procオブジェクトの
call
メソッドを呼ぶと、ブロック内の処理が評価されるProcとかラムダ式とかクロージャーとか、このあたりの背景については全く理解できていないので、改めて学習する必要があると考えています。
default_scope
の引数として、ラムダ式が使われている「引数としてラムダ式が使われている」というのは、
default_scope
の大きな特徴です。-> { hogehoge(fuga) }
default_scope
におけるラムダ式の使い方としては、「order(created_at: :desc)
というメソッドそのものを引数として取る」というところでしょうか。Micropostモデルに
default_scope
を追加した時点でのテストの結果上記実装をMicropostモデルに追加したところで、
test/models/micropost_test.rb
に対するテストを再び実行します。# rails test test/models/micropost_test.rb Running via Spring preloader in process 1584 Started with run options --seed 38140 5/5: [===================================] 100% Time: 00:00:00, Time: 00:00:00 Finished in 0.78921s 5 tests, 5 assertions, 0 failures, 0 errors, 0 skips今度はテストが成功しました。
- 投稿日:2019-12-21T21:29:43+09:00
Fast JSON API をつかって得た、JSON:APIの知見
もう話題になってから、2年くらいの月日がたってしまったと考えると、時の速さを感じます。
そんな時の速さと同じくらい、早くserializeできるというFast JSON APIをつかって、今年の前半期でサービスを作ったので、得た知見を残しておこうと想います。ざっくりとした内容は、6月の表参道.rb で少し話させてもらいました!
今回紹介するのは、fast_jsonapiをつかったRubyのコードの書き方というよりは、
fast_jsonapiに使われている、JSON:APIというフォーマットについて書こうと思います。動機、経緯
新サービスのjsonを返す、APIをRailsで作ることになったので、serializerを選定してました。
以前のサービスは、jbuilderをつかっていたのですが、jsonの管理にとてもとても苦しい思いをしたので辞めました。
Railsのserializerを選定するとなった時、当時も現在も AMS(active_model_serializers) か fast_jsonapiの2択になるのかなと思います。
エンジニアとしては、新しい技術をいれたくなるのはやまやまなのですが、以下の点を検討したあと、道入を決めました。
- 知見の確保先
- JSON:APIにフロント側が対応できるか
- JSON:API対応させるか、どこまで対応させるか
- 最悪の場合、AMSに乗り換えられるか
入れてみた雑感として、fast_jsonapi ですこし大変になってきそうなのが、JSON:API への対応だと思います。
自由に形を変えられる、jbuilderを考えると、天と地くらいあります。
結構特殊な、形をしているため、クライアントサイドとのすり合わせも必用です。fast_jsonapiをいれる上で、Rails上で工夫した点等はいくつかあるのですが、其のへんのベストプラクティスがまとまる前に開発が終わってしまました。(TT)
ということで、今回はJSON:APIについて、現在僕が調べているところをざっくばらんに紹介していこうと思います。
JSON:APIとは
jsonの構造の規約を定めたものです。
以下に公式のページがあります。
jsonapi.orgJSON:APIがどのような立ち位置なのかといと、こちら
で紹介されているのですが、GraphQLとREST の中間的な立ち位置になっています。
JSON:APIをリサーチした雑感でいうと、悪く書いている記事はほとんどありませんでした。JSON:APIのフォーマット
JSON:APIのフォーマットについて。jsonapi.org とっぷにサンプルの構造がバンとはってありますが、すべてこのような感じのjsonで返します。
よくあるweb APIをつくるとなると、以下のようなフォーマットがおおくなるのではとおもいます。{ "data": [{ "type": "articles", "id": "1", "attributes": { "title": "JSON:API paints my bikeshed!", "body": "The shortest article. Ever.", "created": "2015-05-22T14:56:29.000Z", "updated": "2015-05-22T14:56:28.000Z" }, "relationships": { "author": { "data": {"id": "42", "type": "people"} } } }], "included": [ { "type": "people", "id": "42", "attributes": { "name": "John", "age": 80, "gender": "male" } } ] }特徴的なのが、
type
,relationships
included
といったところでしょうか。
type
はリソースの名前が入ります。僕はModelの名前をいれていました。
relationships
はリレーションが組んである、idとtypeが入ります。もし、関連データでidしかいらないとなった場合と、included
からデータをもってくるときにつかいます、
included
は、リレーションが組んである、データの詳細を返しているという感じですね。この構造をみたときに、思うのが、
パース面倒そうじゃない???
です。
そうです。ここがちょっと苦労したところです。
公式 ではクライアント向けのライブラリーが何個も紹介されています。
この辺をつかえば、良い感じにうまくいきそうな気はしてました。
しかし、ここは僕の知見外になってしまうのですが、iOS側(Swift) のライブラリはうまくいかなかったパースが何個かあったみたいです。
なので、クライアント側のひとと相談が大切です。また、POSTなどするときも、JSON:APIで定められている規約を使いたいです。
其の際の、Rails側でのパースはNetflix製の
restful-jsonapi
を使わせてもらいました。こちらは特に苦労はなかったと思います。
JSON:APIへの対応
JSON:APIをつかう上で、若干失敗したなと思ったのが、パラメータの既約を初期に設定しなかったことです。
ここは、僕の調査不足もあったのですが、前述したとおり、JSON:API はGraphQLとRESTの中間の立ち位置になります。
JSON:APIはGraphQLもどきのようなことができることも推奨しています。 公式 RecommendationsGET /comments?filter[post]=1,2&filter[author]=12 HTTP/1.1このように パラメータでfilterしたり、includeできたりすることを推奨しています。
このような部分はなるだけ実装したいものです。クライアント側に伝えられず、途中から実装という形にしていきました。また、この機能はfast_jsonapiに実装されているわけではなく、自分で良い感じに実装しないといけません。
そこも、なかなか大変だとおもいました。まとめ
今回は、fast_jsonapiというより、JSON:APIについて、所感をまとめました。
サービスが途中で終了してしまったため、運用上の知見をまとめあげるまではいけませんでした。
日本では、この辺の知見は落ちてないため、基本海外から引っ張ってくる形になるとおもいます。
海外だと、fast_jsonapiに関しても、JSON:APIに関しても悪い事は書かれていないように感じます。JSON:APIの形式自体は、AMSも対応しているということもあり、RailsでREST APIをつくる上で、検討すべき点に入ってきます。
知見がすくないのも否めないので、実際に導入して、運用しているところの意見があれば、聞きたいです!個人的には、このJSON:APIの規約どおりに、コードをまとめることができれば、運用は良い方向になるのではと思っています。
参考資料
Netflix medium
https://medium.com/netflix-techblog/fast-json-api-serialization-with-ruby-on-rails-7c06578ad17fNetflix github
https://github.com/Netflix/restful-jsonapiError Serializer について
https://blog.codeship.com/the-json-api-spec/AMS VS fast_jsonapi
https://medium.com/soundstripe-engineering/greener-pastures-migrating-a-production-api-from-activemodel-serializers-to-fast-json-api-9627be51c64AMS VS fast_jsonapi
https://driggl.com/blog/a/from-activemodel-serializers-to-fast-jsonapiJSON:API について喋っている動画
https://nordicapis.com/the-benefits-of-using-json-api/
- 投稿日:2019-12-21T19:18:38+09:00
[Ruby on Rails]slickの矢印の画像を変更する方法[JQuery]
実現したいこと
slickの画像(スライド)を次に送るための両側の矢印の画像を好きなものにする。
色々参考にしたがうまくいかなかったので、自分がうまくいったやり方を残しておきます。
前提
Ruby on Railsで開発を行っています。slickは導入できているものとします。
Rails 5.2.4
ruby 2.5.1
jquery-rails 4.3.5手順
画像の用意
矢印にしたい画像をapp/asset/imagesフォルダに入れます。
矢印のデフォルト画像の変更
おそらく\2190と\2192の部分が、矢印のデフォルトの画像を指定している部分だと思います。なので、この部分を任意の矢印の画像に取り替えます。
slick-theme.scss変更前 $slick-prev-character: "\2190" !default; $slick-next-character: "\2192" !default; 変更後 $slick-prev-character: image-url("left.png") !default; $slick-next-character: image-url("right.png") !default;矢印の表示と位置調整
位置の調整は以下の記事を参考にさせていただきました。
https://qiita.com/milneo/items/3560cb01cba92c2ccb6f
これで、矢印が表示されたと思います。slider.scssはslickに対してcssを記述しているファイルです。名前などは人それぞれ違うと思うので気をつけてください。slider.scss.slick-prev{ left: 50px; height: 80px; width: 80px; z-index: 10; } .slick-next{ right: 50px; height: 80px; width: 80px; z-index: 10; }最後に
なんとか、矢印の画像の変更はできました。
ただ、まだコードの意味や自分が行ったことの意味を理解していないので、もっと勉強しなけらばなと思いました。参考
- 投稿日:2019-12-21T19:02:27+09:00
【Rails】Migration
Migrationとは
Railsでのデータベースへの変更を加える際に使用する機能
下記の順で実行する
- DBスキーマを変更するコードを記述したRubyのファイル マイグレーションファイルを作成
- マイグレーションファイルを適用する
ひとつのマイグレーションがバーションとして扱われる
開発用, 本番用, テスト用と個別に管理されるマイグレーションの適用
開発環境以外は
RAIS_ENV
で指定# 開発環境 rails db:migrate # 本番環境 rails db:migrate RAILS_ENV=production # テスト環境 rails db:migrate RAILS_ENV=test # 指定バージョンまでマイグレーションを適用 rails db:migrate VERSION=20191221~マイグレーションの取り消し
# 1つ前のマイグレーションを取り消す rails db:rollback # 指定したステップ数だけ取り消す rails db:rollback STEP=3
- 投稿日:2019-12-21T17:01:58+09:00
herokuにruby on railsアプリをmysqlを使用してデプロイする。deploy
前提条件
nodeとyarnは必ず最新にしておいてください。
それは書きません。プロジェクトの作成
noracorn-railsというプロジェクトで作成します
ghq get https://github.com/noracorn/noracorn-rails.git rails new noracorn-rails cd noracorn-railsscaffoldで、適当にサイトを作成
rails generate scaffold person name:string age:integer rake db:migrateトップページをいったんscaffoldで作成したものにする
noracorn-rails/config/routes.rbRails.application.routes.draw do resources :people root 'people#index' end立ち上がることを確認しましょう
以下のコマンドを打ってから、http://localhost:3000/にアクセス
Personのscaffoldにアクセスできることを確認するbundle install rails serverherokuでアプリを作成する
heroku login heroku create noracornrailsherokuにmysqlを追加
(herokuにクレジットカードを登録してないと追加できません。)
heroku addons:add cleardb:ignite -a noracornrailsdatabase設定
noracorn-rails/database.ymlproduction: <<: *default url: <%= ENV['DATABASE_URL'] %> username: <%= ENV['DATABASE_USERNAME'] %> password: <%= ENV['DATABASE_PASSWORD'] %>以下のコマンドを打つと、データベース接続情報が表示されます。
heroku configこんな感じで表示されます
mysql://user_xxx:password_xxx@host_xxx/dename_xxx?reconnect=true表示された接続情報をherokuの環境変数に入れていく
heroku config:set DATABASE_URL="mysql2://user_xxx:password_xxx@host_xxx/dename_xxx?reconnect=true" heroku config:set DATABASE_USERNAME="user_xxx" heroku config:set DATABASE_PASSWORD="password_xxx"config.assets.initialize_on_precompile = falseを、application.rbに入れる
noracorn-rails/config/application.rbmodule NoracornRails class Application < Rails::Application config.load_defaults 6.0 config.assets.initialize_on_precompile = false end endproduction.rbのconfig.assets.compileをtrueにする
noracorn-rails/config/environments/production.rbconfig.assets.compile = trueGem Fileを編集する。
ローカル環境とテストでは、sqlite3を使用してherokuではmysqlを使用するようにした。
上のほうで定義されているsqlite3は、コメントアウトしておいてください。#gem 'sqlite3', '~> 1.4' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'sqlite3', '~> 1.4' end group :development do # Access an interactive console on exception pages or by calling 'console' anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'sqlite3', '~> 1.4' gem 'spring-watcher-listen', '~> 2.0.0' end group :production do gem 'mysql2' endbundle installする
bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include" bundle installすべてコミットして、herokuにpush
git add . git commit git push origin master heroku git:remote --app noracornrails git push heroku masterherokuのmysqlをマイグレーション
heroku run rails db:migrateアプリが動いているか確認する
heroku open
- 投稿日:2019-12-21T16:48:13+09:00
【Rails】新規アプリケーションの作成準備
まえがき
備忘のためのメモでもあるので、少し簡単に記載させていただいております。少しずつ肉付けできればとは考えておりますが、わかりにくいところなどありましたら申し訳ございません。ご質問やご指摘などメッセージいただきましたら私の方でもお調べしますので、共に前進できればと考えております。何卒よろしくお願い申し上げます。
また、TECH::EXPERTにて学習させていただいているため内容は参照させていただいております。開発環境
MacOS:10.14.6
Ruby:2.5.1
Rails:5.2.4
MySQL:0.5.2index
1.ターミナルで新規アプリケーションのディレクトリを作成
2.gemのバージョン指定を追記/変更
3.データベース作成 + ブラウザで確認1.ターミナルで新規アプリケーションのディレクトリを作成
# 新規アプリケーションを作成したいディレクトリに移動 $ cd ~/ディレクトリ名 # 新規アプリをバージョンを5.2.3で、-dオプションでMySQLの使用を明示して作成 $ rails _5.2.4_ new アプリ名 -d mysql # アプリ名ディレクトリに移動 $ cd アプリ名 # 現在のディレクトリのパスを表示(確認までに) $ pwd※以下のエラーが出る場合
Installing mysql2 0.5.2 with native extensions Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /Users/user_name/Programs/web/foobar-repo/vendor/bundle/ruby/2.5.1/gems/mysql2-0.5.2/ext/mysql2 /Users/user_name/.rbenv/versions/2.5.1/bin/ruby -r (以下略)バージョンに関するエラー
ターミナルで以下のコマンドを実行$ gem install mysql2 -v '0.5.2' --source 'https://rubygems.org/' -- --with-cppflags=-I/usr/local/opt/openssl/include --with-ldflags=-L/usr/local/opt/openssl/lib $ cd ~/ディレクトリ名/アプリ名 $ bundle install2.gemのバージョン指定を追記/変更
テキストエディタでアプリ名のディレクトリを開き、Gemfileから必要に応じてgemのバージョンを変更します。
私の場合は「mysql2」と「sass-rails」のバージョンに変更が必要でしたので以下で変更しました。
また一番下に新たにgemを3つ追記しております。source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ~中略~ # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.2.4' # Use mysql as the database for Active Record gem 'mysql2', '0.5.2' # Use Puma as the app server gem 'puma', '~> 3.11' # Use SCSS for stylesheets gem 'sass-rails', '5.0.7' # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'mini_racer', platforms: :ruby ~中略~ gem 'pry-rails' gem 'compass-rails', '3.1.0' gem 'sprockets', '3.7.2'ターミナルで以下を実行し
Gemのバージョン指定を管理している「Gemfile.lock」というファイルを更新# Gemfileを元にgemをインストールし、Gemfile.lockを更新する $ bundle update3.データベース作成
ターミナルで以下を実行
# データベースの作成 $ rails db:create※ここまで終わったら以下のコマンドでサーバーを起動し
ブラウザ(http://localhost:3000)で確認# サーバーを起動 $ rails s
- 投稿日:2019-12-21T15:59:36+09:00
マイグレーションファイルの作成、変更、削除まで
今回は、物件のファイルを作ることを想定します。
流れ
マイグレファイル作成→カラムすべて間違い→もう一度入れ直したい
1.マイグレファイルを作成する
$ rails g migration CreateHomes2.作成したマイグレファイルをエディターで編集する
create_homes.rbclass CreateHomes < ActiveRecord::Migration[5.2] def change create_table :homes do |t| t.string :"物件名" t.string :"賃料" t.string :"住所" t.text :"備考" end end end3.マイグレーションをターミナル上で入力
$ rails db:migrate4.マイグレファイルを削除するため、削除用のファイルを作る
rails g migration RemoveColumnsFromeHomes5.作ったファイルを編集する
remove_columns_from_homes.rbclass RemoveColumnsFromHomes < ActiveRecord::Migration[5.2] def change remove_column :Homes, :"物件名", :string remove_column :Homes, :"賃料", :text remove_column :Homes, :"住所", :text remove_column :Homes, :"備考", :text end end6.マイグレーションをターミナル上で入力
$ rails db:migrate※こうすることで、再び作り直すことができます。
rollbackでも削除は、可能ですが複数開発のときに何を編集したのか分からなくなるのでやめましょう。7. カラムを追加するためのマイグレファイル作成
$ rails g migration AddColumnsToHomes8.マイグレファイルを編集
add_columns_to_homes.rbclass AddColumnsToHomes < ActiveRecord::Migration[5.2] def change add_column :homes, :property, :string add_column :homes, :rent, :text add_column :homes, :address, :text add_column :homes, :age, :text add_column :homes, :remarks, :text end end何かを分からないことがありましたら、コメントを頂ければ1日以内に返信するように致します。
- 投稿日:2019-12-21T15:51:40+09:00
rails server が失敗する
初めての記事で、超低レベルな内容になりますがよろしくお願いします。
rails new 任意の名前
を実行した後に
rails server
を実行すると思うんですが、ここで
cd 任意の名前
を実行しないとダメなんですね。
それはそう、って感じなんですけどね。しっかりと自分が作成したディレクトリに移動してからサーバーを立ち上げましょう。
- 投稿日:2019-12-21T15:35:01+09:00
Railsで中間テーブルダブルポリモーフィックやってみた。
Ruby on Rails Advent Calendar 2019の18日目が未投稿だったので代わりにでも。
はじめに
Railsを用いたサービス開発中に、中間テーブルとポリモーフィック関連を組み合わせる機会があり、ググってもあまり情報がないのでここに書く。
前提
- とあるプラットフォームが複数のサブスクリプションサービスを持っている(サービスA, サービスB, etc.)
- ユーザーは一つのアカウントで複数のサービスを契約できる。また同一サービスに対して複数契約もできる。
- それぞれのサービスに対して、
申し込み情報
と契約情報
を別テーブルで保持する。これらはユーザー
テーブルと関連づけられる。- ビジネスフロー例
- サービスAへの申し込み発生 → 申し込みレコードを発行
- 申し込みの妥当性確認などビジネスサイドの手続き。
- 2の処理完了 → 申し込み情報レコードを元に契約情報レコードを発行
- 各申し込み/契約に対して、
支払い情報
と請求先情報
が別テーブルで関連づいている。
- これらの情報はサービスをまたいで共有することができる。例えば、とあるユーザーがサービスAへの申し込みで登録した支払い/請求先情報を、サービスBへの申し込みにも利用することができる(→中間テーブルを採用)。
ER図を眺めてみる
サービスAのことだけ考えた場合、ER図は下記のようになる。
(各テーブルのフィールド、また本題と関係ないリレーションは省略)サービスA向けの申し込み情報テーブルを
ServiceAOrder
, 契約情報をServiceAContract
として、中間テーブルを介してそれぞれが支払い情報Payment
、請求先情報BillRecipient
を持つ。この時点で中間テーブルが4つ作られているが、サービスが増えるごとに4つずつ新しく中間テーブルを増やすのは非常にだるい、、
ここで気がつく。
中間テーブルにポリモーフィック関連って使えるのかな?
もしかして両サイドポリモーフィックもいける、、?もしかして中間テーブルダブルポリモーフィックできちゃう、、?
実装
というわけでやってみた。ソースコードはこちら
検証環境はRuby 2.6.3, Rails 6.0.2
方針としては
Subscription
モデルを中間テーブルとして、holder
とtarget
という2つのポリモーフィックなbelongs_toを作る。やろうとすれば割り当てるモデルに制限はないが、意味合い的に次のような割り当てをする。
- holder: SeviceAOrder, ServiceAContract, 他のサービスを追加していく
- target: Payment, BillRecipient
またシンプルに中間テーブルを利用する場合だと次のような指定をすれば良いが、ポリモーフィック関連を利用する場合はhas_manyにオプションで
source
,source_type
をつけてテーブルを明示的に指定する必要がある(Railsガイドのこのあたり)。has_many :subscriptions has_many :payments, through: :subscriptionsモデルのリレーション一覧↓
# app/models/subscription.rb class Subscription < ApplicationRecord belongs_to :holder, polymorphic: true belongs_to :target, polymorphic: true end # app/models/service_a_order.rb class ServeceAOrder < ApplicationRecord has_many :subscriptions, as: :holder has_many :payments, through: :subscriptions, source: :target, source_type: 'Payment' has_many :bill_recipients, through: :subscriptions, source: :target, source_type: 'BillRecipient' end # app/models/service_a_contract.rb class ServeceAContract < ApplicationRecord has_many :subscriptions, as: :holder has_many :payments, through: :subscriptions, source: :target, source_type: 'Payment' has_many :bill_recipients, through: :subscriptions, source: :target, source_type: 'BillRecipient' end # app/models/bill_recipient.rb class BillRecipient < ApplicationRecord has_many :subscriptions, as: :target has_many :service_a_orders, through: :subscriptions, source: :holder, source_type: 'ServiceAOrder' has_many :service_a_contracts, through: :payment_bill_recipient_holders, source: :holder, source_type: 'ServiceAContract' end # app/models/payment.rb class Payment < ApplicationRecord has_many :subscriptions, as: :target has_many :service_a_orders, through: :subscriptions, source: :holder, source_type: 'ServiceAOrder' has_many :service_a_contracts, through: :subscriptions, source: :holder, source_type: 'ServiceAContract' end簡単なテスト↓
# spec/models/service_a_order_spec.rb require 'rails_helper' RSpec.describe ServiceAOrder, type: :model do describe '中間テーブル機能チェック' do it 'service_a_orderレコードに対して、ポリモーフィックなpaymentとbill_paymentレコードがきちんと紐づく' do user = User.new(name: 'Dan', email: 'test@example.com') user.save! service_a_order = ServiceAOrder.new(plan_type: 1, user: user) service_a_order.save! payment = Payment.new(payment_type: 1) service_a_order.subscriptions.create(target: payment) # service_a_order.payments << payment # こっちの書き方でもOK bill_recipient = BillRecipient.new(address: 'Chiyoda') service_a_order.subscriptions.create(target: bill_recipient) # service_a_order.bill_recipients << bill_recipient # こっちの書き方でもOK expect(service_a_order.payments.count).to eq 1 expect(service_a_order.payments.first).to eq(payment) expect(service_a_order.bill_recipients.count).to eq 1 expect(service_a_order.bill_recipients.first).to eq(bill_recipient) end end endちなみにソースコードの方では
ServiceBOrder
とServiceBContract
を追加しているが、いけてそう。参考
Railsのポリモーフィック関連とはなんなのか
Combining has_many :through with polymorphic associations in ActiveRecordまとめ
そのうち地雷を踏みそうだけど後悔はしていない。
- 投稿日:2019-12-21T14:24:24+09:00
番外編 1. Rubyチュートリアル
Ruby in Twenty Minutes
https://www.ruby-lang.org/en/documentation/quickstart/
irbを使ってみよう
rails consoleを使ってみよう
- 投稿日:2019-12-21T14:16:14+09:00
Railsをherokuでデプロイする方法
herokuでのデプロイは、AWSに比べてめちゃめちゃ簡単だったので、まとめました!
(githubへのpush、会員登録、クレジットカード登録など完了後)
herokuにログインする
デプロイしたいアプリに移動したら
$ heroku login何かキーを押してくださいと言われるので、適当にエンターキーを押す。
↓
herokuのページに推移する。
↓
loginを押してターミナルに戻る
↓
ログイン完了作ったアプリをherokuとリンクさせる
デプロイしたいアプリに移動したら
$ heroku create アプリ名アプリ名がURLに入るのでしっかり考えましょう
すでにそのアプリ名がherokuで使われている場合はできませんデータベースを作成する
※データベースが必要な場合のみ
ターミナル $ heroku addons:create cleardb:igniteこれでデータベース作成は完了しました。
mysql2の環境変数を指定
初期設定だとmysql2の設定ができていないのでそこを設定していきます。
現在のmysqlの設定を確認します。$ heroku config以下のような長い文字列が出てくるので、それに応じて環境変数を入力していきます。
CLEARDB_DATABASE_URL: mysql://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=trueheroku configで表示された文字列をもとに、以下のように入力していきます。
$ heroku config:add DB_USERNAME='<ユーザー名>' $ heroku config:add DB_PASSWORD='<パスワード>' $ heroku config:add DB_HOSTNAME='<ホスト名>' $ heroku config:add DB_NAME='<データベース名>' $ heroku config:add DB_PORT='3306' $ heroku config:add DATABASE_URL='mysql2://<ユーザー名>:<パスワード>@<ホスト名>/<データベース名>?reconnect=true'エラー対策の微調整
config/environments/production.rb#初期はfalseなので変更 config.assets.compile = true #config.assets.js_compressor = :uglifierを変更 config.assets.js_compressor = Uglifier.new(harmony: true)デプロイ
$ git push heroku masterデータベースのmigrate
$ heroku rake db:migrateアプリの立ち上げ
$ heroku openこれでブラウザに、作ったアプリが表示されます!
補足
万が一、エラーが出てしまった場合は
$ heroku logs -tで確認できるので、修正し、ローカルからgithubへのプッシュ。
そして再度$ git push heroku masterをすれば大丈夫です。
- 投稿日:2019-12-21T13:26:16+09:00
Railsでerbをhamlに変換する方法
- 投稿日:2019-12-21T13:11:55+09:00
Railsでアプリを作る簡単な流れ
一からアプリを立ち上げるとなると、意外と、何からしていいか分からない人もいると思うので、まとめました。
(アプリのダウンロードなど、環境構築などは完了していること)
アプリを作成する
保存したい場所に移動して
私はデータベース名は、mysqlでやってます。
指定しなければ、SQLiteというものが入ります。ターミナル $ rails new アプリ名 -d mysql(データベース名)gemのインストール
ターミナル $ bundle installコントローラーを作成する
投稿サイトを作る場合のコントローラーを作成します。
※コントローラー名は複数形にしましょうターミナル $ rails g controller posts(コントローラー名)posts.controller.rbclass PostsController < ApplicationController def index(アクション名) #空でいいので作成する end endデータベースを作成する
データベースが必要であれば作成します。
通常であれば2つのファイルが生成されます。ターミナル $ rails db:createモデルを作成する
データベースが必要な場合はモデルを作成します。
※モデル名は単数形にしましょうターミナル $ rails g model post(モデル名)モデルを作成すると、マイグレーションファイルも同時生成されます。
必要なカラムがあれば追加します。20190000_xx_xx.rbclass CreatePosts < ActiveRecord::Migration[5.2] def change create_table :posts do |t| #t.(型名) :(カラム名), (オプション) t.text :content, null: false t.timestamps end end endカラムの追加が完了したら
ターミナル $ rails db:migrateこれでデータベースの準備は完了です。
トップページのルーティングを作成する
routes.rb#root to: "コントロ-ラー名#アクション名" root to: "posts#index"トップページのviewを作成する
app/views/posts(コントローラー名)の中に index(アクション名).html.erbを作成index.html.erbHELLO WORLDrailsを起動する
ターミナル $ rails slocalhost:3000で起動します
- 投稿日:2019-12-21T12:27:47+09:00
【Railsチュートリアル】 NoMethodError in StaticPages#homeが出た時の対処法
エラー発生
Railsチュートリアル第5章の5.1.1ナビゲーションをやってRailsサーバーを再起動すると下記のようなエラーが発生。
NoMethodError in StaticPages#home
undefined method full_title原因
ググってみると下記のサイトを発見。
「Rails Tutorialでrails sエラーで困っています・・・」
https://teratail.com/questions/12510その回答として
「full_title を app/helper/下のファイルで定義すれば erb ファイル中で参照できると思います。」試しにapp/helpers/application_helper.rbを見ると中身が空だった。
対処法
Railsチュートリアル第4章「リスト4.2: full_titleヘルパーを定義する」の中身を書いたらエラーが解決し、無事表示された。このエラーが表示されたら、app/helpers/下を見てみよう。
- 投稿日:2019-12-21T12:12:03+09:00
railsでapplication.scssと同じディレクトリのscssファイルが読み込まれないときの対処法
背景と対象
usersコントローラを作成したときに生成された、app/assets/users.scssに記述したscssが反映されない。つまりはアセットパイプラインの仕組みが適用されていない状況になってしまっている状況。全部app/assets/application.scssに書けばcssの適用は出来ますがめっちゃ見ずらいのでやめた方がいいです。このような状況でつまっている方の役に立てればと思い書きました。ちなみにアセットパイプラインについては以下のページがおすすめです!
https://diveintocode.jp/blogs/Technology/AssetPipeline解決方法
とっても簡単です!
app/assets/application.scssのコメントアウトの最下部に*= require_selfとrequire_tree を以下のように追加してください。それぞれのコードの意味はコード内に書いてあります。ちなみにこれらの順番はどっちでもよく、require_selfを先に書けばapplication.scssが先に読み込まれます。後に書けばapplication.scss以外のscssファイルが先に読み込まれます。
app/assets/application.scss/* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's * vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * *= require_self まずはこのファイルを読み込むという記述 追加! *= require_tree app/assets以下のcssファイルを読み込んでいる 追加! */ }これでアセットパイプラインの仕組みを利用して分かりやすく、すっきりしたコードが書けます!
- 投稿日:2019-12-21T11:51:45+09:00
【Rails+PostgreSQL+Heroku】環境構築まとめ
やりたいこと
rails new で作ったアプリをheorkuでデプロイしたい。
herokuではsqliteではなくpostgresqlを使わないとダメなので、初めからその設定をしておく。
psql 12.1
Rails 5.0.7.2railsの設定
rails new e-stat-rails --database=postgresql
rails db:create
rails db:migrate
rails server
localhost:3000で起動できているか確認。エラー対処
【再起動して解決】connections on Unix domain socket “/tmp/.s.PGSQL.5432”?への対処
【rails】Specified 'postgresql' for database adapter, but the gem is not loaded と怒られた件
herokuへ
Herokuへデプロイした時に「The page you were looking for doesn't exist. 」エラーが出る
こうならないようにcontrollerとroutesを設定してrootでhelloworldと表示するようにする。application_controller.rbclass ApplicationController < ActionController::Base protect_from_forgery with: :exception def hello render html:"hello, world!" end endroutes.rbRails.application.routes.draw do root 'application#hello' end
git add .
git commit -m "hogehoge"
git push origin master
heroku create
git push heroku
open heroku
できた!!
- 投稿日:2019-12-21T11:06:58+09:00
ずら〜っと、Railsでデータベースを確認する方法一覧
データベースクライアントの起動
$ rails dbconsoleこうなる
sqlite>テーブル一覧の見方
sqlite> .tables指定したテーブルのカラムの確認方法(スキーマの確認)
.schema テーブル名
- 投稿日:2019-12-21T09:17:54+09:00
WindowsにRails環境を導入してみる
WindowsにRailsを導入しようとしたらめちゃくちゃ手こずったので、記録しておこうと思って書きました
初めに
ここからRubyをダウンロードする、Devkitがついてるやつがいいらしい
インストールが完了したらコマンドプロンプトを開いてgem install rails
を実行
問題なくインストールできたようなので次のステップへ
rails new hoge
を実行するとガーっとファイルが作られていって安心していたら変なのが出るCould not find gem 'sqlite3 (~> 1.4) x64-mingw32' in any of the gem sources listed in your Gemfile. Run `bundle install` to install missing gems.意訳:ふえぇ、SQLite3 v1.4が見つからないよぉ
Railsを始めてsqlite3まわりのエラーで躓いている人たちへを見るとSQLite3でエラーが頻発して阿鼻叫喚としてるとか書いてある、怖いGemfileを編集する
# Use sqlite3 as the database for Active Record gem 'sqlite3', '~> 1.4'2行目のSQLite3のバージョンを下げてみる
# Use sqlite3 as the database for Active Record gem 'sqlite3', '~> 1.3.6'ディレクトリ移動して
bundle install
hoge>bundle install Bundle complete! 14 Gemfile dependencies, 70 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed.勝ったなガハハ、サーバ立ててlocalhost:3000にアクセスしてやろう。
hoge>rails server C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/activesupport-6.0.2.1/lib/active_support/dependencies.rb:325:in `require': cannot load such file -- sqlite3/sqlite3_native (LoadError)勝ってなかった。
SQLite3くんが悪さをしているように見えるので消してやりましょうhoge>gem uninstall sqlite3 Successfully uninstalled sqlite3-1.3.13-x64-mingw32
gem install sqlite3 --platform ruby
でSQLite3を再インストールhoge>gem install sqlite3 --platform ruby Temporarily enhancing PATH for MSYS/MINGW... Installing required msys2 packages: mingw-w64-x86_64-sqlite3 Building native extensions. This could take a while... Successfully installed sqlite3-1.4.2 Parsing documentation for sqlite3-1.4.2 Installing ri documentation for sqlite3-1.4.2 Done installing documentation for sqlite3 after 1 seconds 1 gem installed通った。
なおサーバは立たない、なんでや。Railsのバージョンを下げる
rails 環境構築~ヘルスケアwebサービスを自分で作る医者の日記~と【Windows】RubyとRuby on Raisの環境構築でSQLite3まわりで苦労したのコメント欄にRailsのバージョンを下げたらいけたと書いてあったので早速
gem i -v 5.2.3 rails
を実行
終わったぽいのでrails new hoge
でプロジェクトを作るとすんなり通った。
これはいけたのでは?
恐る恐るrails server
実行対戦ありがとうございました。
原因
詳しいことは不明ですが、Rails6.0.2.1とSQLite3 v1.4の相性がよくなかったのかなと思います
最終的な環境
Ruby 2.6.5p114
Gem 3.0.3
Rails 5.2.3
SQLite3 1.4.2最後に
Qiitaで記事を書くのは初めてなので、変なところがありましたらご指摘いただけると幸いです。
- 投稿日:2019-12-21T04:28:52+09:00
【gemなし】Railsでラベル機能を作る
速攻でラベルのモッグを作りたい時のためにメモ
rails new
$ rails _5.2.3_ new sample-relation -d postgresql --skip-bundl && cd sample-relation && bundle install --path vendor/bundle && rails db:createscaffoldで無駄なファイルが生成されないよう設定
/config/application.rbmodule SampleRelation class Application < Rails::Application # ここから下を追加 config.generators do |g| g.javascripts false g.helper false g.test_framework false end end endpostテーブル(投稿機能機能)をscaffoldで生成
$ rails g scaffold post title:string details:stringlabelテーブル(ラベル機能)をscaffoldで生成
$ rails g scaffold label title:stringpost_labelテーブル(postとlabelの中間)をmodelを生成
$ rails g model post_label post:references label:referencesアソシエーション
投稿
post.rbclass Post < ApplicationRecord has_many :post_labels, dependent: :destroy, foreign_key: 'post_id' has_many :labels, through: :post_labels, source: :label end中間
post_label.rbclass PostLabel < ApplicationRecord belongs_to :post, optional: true belongs_to :label, optional: true endラベル
label.rbclass Label < ApplicationRecord has_many :post_labels, dependent: :destroy, foreign_key: 'label_id' has_many :posts, through: :post_labels, source: :post endコントローラー
posts_controller.rbprivate def post_params params.require(:post).permit(:title, :details, label_ids: [] ) endビュー
新規投稿画面
new.html.erb<%= form_with(model: post, local: true) do |form| %> <% if post.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2> <ul> <% post.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.post :title %> <%= form.text_field :title %> </div> <div class="field"> <%= form.post :details %> <%= form.text_field :details %> </div> <div class="field"> <% Label.all.each do |label| %> <% if action_name == 'new' || action_name == 'create' %> <%= form.check_box :label_ids, { multiple: true, checked: label[:checked], disabled: label[:disabled], include_hidden: false}, label[:id], "" %> <label><%= label.title %></label> <% elsif action_name == 'edit' || action_name == 'update' %> <%= form.check_box :label_ids, { multiple: true, checked: @task.label_ids.include?(label.id), disabled: label[:disabled], include_hidden: false}, label[:id], "" %> <label><%= label.title %></label> <% end %> <% end %> </div> <div class="actions"> <%= form.submit %> </div> <% end %>投稿一覧
index.html.erb<p id="notice"><%= notice %></p> <h1>Posts</h1> <table> <thead> <tr> <th>Title</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @posts.each do |post| %> <tr> <% post.post_labels.each do |post_label| %> <%= post_label.label.title %><br> <% end %> <td><%= post.title %></td> <td><%= link_to 'Show', post %></td> <td><%= link_to 'Edit', edit_post_path(post) %></td> <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New post', new_post_path %>めんどくさがりな方のためにラベルのシードデータの設定
seeds.rb20.times do |i| Label.create!(title: "sample#{i + 1}") endmigrate(テーブルをDBに反映)してseedデータを作ってrails s(サーバー起動)
$ rails db:migrate && rails db:seed && rails s以上です!
- 投稿日:2019-12-21T01:19:40+09:00
Rails6 マイグレーションファイルの記載ミスでマイグレートしてしまったらrollbackを使おう
目的
- マイグレーションファイルの記載を間違え、マイグレートしてしまった時の対処法をまとめる
筆者がやらかしたこと
- マイグレーションファイルの記載をミスる。
- その状態でマイグレートしてしまう。
- データベースを確認したところ期待した方になっていない。
- 現在のマイグレーションファイルを削除する。
- 再度、マイグレーションファイルを作成し正式な記載にをした。
- マイグレートを実行した。
- データベースが期待したものになっていた。
間違えてマイグレートをしてしまった時はrollebaskをしよう
マイグレート後にDBに異変を感じたらすぐに下記のコマンドを実行してマイグレート前の状態に戻す。
$ rails db:rolleback
そのあとでマイグレーションファイルの記載を確認、修正を行い再度、マイグレートを行う。