- 投稿日:2020-07-12T23:42:52+09:00
【Rails】rails g migrationコマンドのオプションで注意したいこと
- 投稿日:2020-07-12T23:39:02+09:00
ActiveAdminのactionsボタンのitemについて
はじめに
ActiveAdminは管理画面のCRUDを簡単に実装できるGemです。
ActiveAdminは便利なのですが、細かいところをイジろうとした際にどのように実装すれば良いのか詰まることが頻繁にあります。
今回は、条件によって表示するactionsを分けたいと思いこちらの記事を参考にさせていただいて実装をしました。
実装の中で以下のitemという記述が何をしているのかよくわからなかったため調べました。app/admin/users.rbactions defaults: false do |user| item I18n.t('active_admin.view'), admin_user_path(user), class: 'view_link member_link' item I18n.t('active_admin.edit'), edit_admin_user_path(user), class: 'edit_link member_link' item I18n.t('active_admin.delete'), admin_user_path(user), class: 'delete_link member_link', method: :delete, data: { confirm: I18n.t('active_admin.delete_confirmation') } unless user.admin? end何をしているのか?
itemを消してみるとSyntaxErrorになります。
app/admin/users.rbactions defaults: false do |user| I18n.t('active_admin.view'), admin_user_path(user), class: 'view_link member_link' item I18n.t('active_admin.edit'), edit_admin_user_path(user), class: 'edit_link member_link' item I18n.t('active_admin.delete'), admin_user_path(user), class: 'delete_link member_link', method: :delete, data: { confirm: I18n.t('active_admin.delete_confirmation') } unless user.admin? enditemが必要なのはわかりましたが、itemの中身はどのようになっているのかpryで見てみます。
app/admin/users.rbactions defaults: false do |user| binding.pry item I18n.t('active_admin.view'), admin_user_path(user), class: 'view_link member_link' item I18n.t('active_admin.edit'), edit_admin_user_path(user), class: 'edit_link member_link' item I18n.t('active_admin.delete'), admin_user_path(user), class: 'delete_link member_link', method: :delete if user.id == 1 endなるほどitemはaタグを生成してくれていることがわかりました。
itemを使ってみる
itemには引数を渡すことができます。
app/admin/users.rbactions defaults: false do |user| item('hoge') endhogeという名前で
/admin/users
へのリンクが生成されました。
また、itemに第2引数を渡すこともできます。app/admin/users.rbactions defaults: false do |user| item('hoge', '/admin/hoge') endこちらは
hoge
という名前で/admin/hoge
へのリンクを生成します。
最後に
actionsをカスタマイズする際にitemに引数を渡すと、様々なリンクを生成できることがわかりました。
actionsについて書かれているソースコードの箇所はこちらになりますので、気になられた方は参照ください。参考
- 投稿日:2020-07-12T23:31:07+09:00
TECH CAMP学習 個人アプリ④git ignore
5Kって何だ!?
個人アプリを作成中に、Git Hubにプルリクエストをしてない事をユーザー管理作成中の時に気づいてしまいました。
かなりデータが溜まっていって、ワークスペースになんか『5K』と表示されてしまい全てをプルリクエストできません、と注意で書かれてありました。Git Hubデスクトップにもchangesが500と表示されてしまい500!!??となりました。5Kの意味はこれの事なのかな??
そしてやはり遅かったのか、どうすればプルリクエストできるのか、ファイルのどれかを消さないといけないのかと思い何となく一部のファイルを消去。
ただそれだけでは全くうまくいかず、少なくならず、ひたすらにググってググって、やっと見つけたのがgit ignore!!!
VS code 内で.git ignoreファイルを作り、以下のコードを入れました。
これで一気にchangesが91まで縮小され、プルリクエストができるようになりました。
- 投稿日:2020-07-12T23:19:26+09:00
Ruby on Rails チュートリアル(第4版) 第8章
8.1.1 演習
1.GET login_pathとPOST login_pathとの違いを説明できますか? 少し考えてみましょう。
GETはlogin_pathの内容を取得、POSTはlogin_pathに送信する。
違うのは分かる、でもうまく説明出来ない感じ。
GETとPOSTの違いについて参考にさせていただきました。2.ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。現在、いくつのSessionsリソースがあるでしょうか? ヒント: パイプやgrepの使い方が分からない場合は Learn Enough Command Line to Be Dangerousの Section on Grep (英語) を参考にしてみてください。
$ rails routes | grep sessions login GET /login(.:format) sessions#new POST /login(.:format) sessions#create logout DELETE /logout(.:format) sessions#destroy8.1.2 演習
1.リスト 8.4で定義したフォームで送信すると、Sessionsコントローラのcreateアクションに到達します。Railsはこれをどうやって実現しているでしょうか? 考えてみてください。ヒント:表 8.1とリスト 8.5の1行目に注目してください。
action="/login" method="post"
POST /login
はcreateアクションだから。8.1.3 演習
1.Railsコンソールを使って、表 8.2のそれぞれの式が合っているか確かめてみましょう. まずはuser = nilの場合を、次にuser = User.firstとした場合を確かめてみてください。ヒント: 必ず論理値オブジェクトとなるように、4.2.3で紹介した!!のテクニックを使ってみましょう。例: !!(user && user.authenticate('foobar'))
>> user = nil => nil >> !!(user && user.authenticate('foobar')) => false >> user = User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2020-07-10 15:10:18", updated_at: "2020-07-10 15:10:18", password_digest: "$2a$10$VICUYjma4CkWdl2WFBg.FenXS3mnUPnWYT8YmGUOYS2..."> >> !!(user && user.authenticate('foobar')) => true >> !!(user && user.authenticate('password')) => false8.1.4 演習
1.8.1.4の処理の流れが正しく動いているかどうか、ブラウザで確認してみてください。特に、flashがうまく機能しているかどうか、フラッシュメッセージの表示後に違うページに移動することを忘れないでください。
省略8.2.1 演習
1.有効なユーザーで実際にログインし、ブラウザからcookiesの情報を調べてみてください。このとき、sessionの値はどうなっているでしょうか? ヒント: ブラウザでcookiesを調べる方法が分からない? 今こそググってみるときです! (コラム 1.1)
省略2.先ほどの演習課題と同様に、Expiresの値について調べてみてください。
省略8.2.2 演習
1.Railsコンソールを使って、User.find_by(id: ...)で対応するユーザーが検索に引っかからなかったとき、nilを返すことを確認してみましょう。
>> user=User.find_by(id:3) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]] => nil2.先ほどと同様に、今度は:user_idキーを持つsessionハッシュを作成してみましょう。リスト 8.17に記したステップに従って、||=演算子がうまく動くことも確認してみましょう。
>> session = {} => {} >> session[:user_id] = nil => nil >> @current_user ||= User.find_by(id: session[:user_id]) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT ? [["LIMIT", 1]] => nil >> session[:user_id]= User.first.id User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => 1 >> @current_user ||= User.find_by(id: session[:user_id]) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2020-07-10 15:10:18", updated_at: "2020-07-10 15:10:18", password_digest: "$2a$10$VICUYjma4CkWdl2WFBg.FenXS3mnUPnWYT8YmGUOYS2..."> >> @current_user ||= User.find_by(id: session[:user_id]) => #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2020-07-10 15:10:18", updated_at: "2020-07-10 15:10:18", password_digest: "$2a$10$VICUYjma4CkWdl2WFBg.FenXS3mnUPnWYT8YmGUOYS2..."> >>8.2.3 演習
1.ブラウザのcookieインスペクタ機能を使って (8.2.1.1)、セッション用のcookieを削除してみてください。ヘッダー部分にあるリンクは非ログイン状態のものになっているでしょうか? 確認してみましょう。
省略2.もう一度ログインしてみて、ヘッダーのレイアウトが変わったことを確認してみましょう。その後、ブラウザを再起動させ、再び非ログイン状態に戻ったことも確認してみてください。注意: もしブラウザの [閉じたときの状態に戻す] 機能をオンにしていると、セッション情報も復元される可能性があります。もしその機能をオンにしている場合、忘れずにオフにしておきましょう (コラム 1.1)。
省略8.2.4 演習
1.試しにSessionヘルパーのlogged_in?メソッドから!を削除してみて、リスト 8.23が redになることを確認してみましょう。
省略2.先ほど削除した部分 (!) を元に戻して、テストが greenに戻ることを確認してみましょう。
省略8.2.5 演習
1.リスト 8.25のlog_inの行をコメントアウトすると、テストスイートは red になるでしょうか? それとも green になるでしょうか? 確認してみましょう。
REDになる。2.現在使っているテキストエディタの機能を使って、リスト 8.25をまとめてコメントアウトできないか調べてみましょう。また、コメントアウトの前後でテストスイートを実行し、コメントアウトすると red に、コメントアウトを元に戻すと green になることを確認してみましょう。ヒント: コメントアウト後にファイルを保存することを忘れないようにしましょう。また、テキストエディタのコメントアウト機能については Test Editor Tutorial の Commenting Out (英語) などを参照してみてください。
Ctrl + /
8.3 演習
1.ブラウザから [Log out] リンクをクリックし、どんな変化が起こるか確認してみましょう。また、リスト 8.31で定義した3つのステップを実行してみて、うまく動いているかどうか確認してみましょう。
省略
2.cookiesの内容を調べてみて、ログアウト後にはsessionが正常に削除されていることを確認してみましょう。
省略メモ
rails routes
コマンドで現状のルーティングを確認することが出来る。flash.now
のメッセージはその後リクエストが発生したときに消滅する。@foo = @foo || "bar"
は@foo ||= "bar"
と等価である。
- 投稿日:2020-07-12T22:37:42+09:00
【ターミナル】ターミナル強制終了後、rails sしたらA server is already runningとなった時の対処法【Rails】
「controll+z」でサーバーを切ったら、rails sが効かなくなった。どうしよう・・という問題。
【バージョン】
Rails 5.2.4.3
Ruby 2.5.1
macOS Catalina 10.15.4
【経緯】
ローカルで作業中、rails sで立ち上げたlocalhost:3000を「controllキー + c」でサーバを切り、再度「rails s」で起動させようとしたらうんともすんともいわず・・・ほかの切り方がないか調べたところ「controllキー + z」で強制終了できることが判明。
しかし、「controllキー + z」で強制終了後、
再度、rails sで立ち上げたところ、localhost:3000が立ち上がらず、下記のエラーが出た。ターミナルA server is already running. Check /Users/名前/XXX/XXXXXX/tmp/pids/server.pid.「サーバーはすでに起動しています」と言われた。
【解決方法】
なので、
ターミナル% lsof -i:3000でどんなプロセスが動いているのかを確認してみる。
lsofコマンド
…「LiSt Open Files」(開いているファイル群を列挙する)という言葉に由来するようです。その名の通り、「プロセスが開いているファイル」を表示するコマンドらしいです。
ターミナルCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME ruby 6792 satokokinoshita 11u IPv4 0x95b341c28591923f 0t0 TCP localhost:hbci (LISTEN) ruby 6792 satokokinoshita 22u IPv6 0x95b341c27813ce6f 0t0 TCP localhost:hbci (LISTEN)ここで、COMMANDがrubyとなっているPIDの番号 (ここだと6792、下の画面だと3405) を、○に入れる。
ターミナル% kill -9 〇〇〇〇
これで、rails sで再度起動できるようになりました。※ちなみにkillコマンドについてはkill -9(強制終了)以外は試しておりません。
localhost:3000のサーバーを切った時に消えるはずのプロセスが、強制終了したことで一部残ってしまっていたのだと思います。
「PID(プロセスアイディー)」は、プロセスを識別するための一意の数字になりますが、
PIDを指定してkillコマンドで切ることで、サーバーを切った状態に戻ったということになったのだと思います。【参考にさせていただいたサイト】
このポートで実行中のプロセスはどれ? lsofコマンドの使い方
プロセスを止める最終手段killコマンドの種類・シグナルの使い方
【当該エラーに直面した時の感想的な】
Railsの画面に表示されるエラーは慣れたけど、ターミナルのエラーってあまりないので変な汗がでました?
ターミナルコマンドはどんどん慣れていきたいです。
- 投稿日:2020-07-12T21:36:16+09:00
ブランチに最新のマスターの情報を取り込む方法
初投稿!
非常に感動した内容だった為、備忘録!
ブランチを切って作業をしていると、マージするまでの間にmasterに追加された更新で表示が変わってしまったり、コンフリクトするようになってしまいますよね。
それを防止するためには定期的にブランチにマスターの内容を反映させる必要があります。
その方法をメモ。
- 反映したいブランチに切り替える
作業してるディレクトリ% git checkout ブランチ名2. マスターの内容をブランチに反映させる
作業してるディレクトリ% git merge master以上
参考にさせていただいたサイトhttps://hacknote.jp/archives/11191/
- 投稿日:2020-07-12T19:40:44+09:00
ActionTextのデータ構成はどうなってる?
個人的に
ActionText
を導入する機会があったのでメモ。
blogサービスのようなものを開発する際に、Article
モデルにどのようにActionText
を導入すればいいのか悩んだので、誰かの役に立てればと思います。ActionTextとは
rails6から使えるようになった機能の1つ。
Railsにリッチテキストコンテンツと編集機能を導入できる。今回やりたいこと
記事投稿サービスを作りたいと思います。
タイトル、説明文、本文の3つのデータをもつArticleモデルを作成し、本文の編集にActionTextを導入します。データ構成
ActionText
を導入するモデル作成
Article
モデルを生成します。
title
は記事のタイトル、description
は記事の説明文を表します。本文のデータを格納するカラムは作成しないことに注意してください。rails g model Article title:string description:text
ActionText
を導入する
ActionText
は以下のコマンドでインストールできます。rails action_text:installActionTextをインストールすると、2つのmigrationファイルが生成されます。
1つはActive Storage
に関わるファイルで、もう一つがActionText
のテーブルを作成するファイルです。
後者のテーブルがこの記事で説明したいデータ構成の鍵となります。リッチテキストコンテンツは独自のRichTextモデルに保存され、このモデルはアプリケーションの既存のあらゆるActive Recordモデルと関連付けられます。 あらゆる埋め込み画像(およびその他の添付ファイル)は自動的にActive Storageに保存され、includeされたRichTextモデルに関連付けられます。
https://railsguides.jp/action_text_overview.html#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB
class CreateActionTextTables < ActiveRecord::Migration[5.2] def change create_table :action_text_rich_texts do |t| t.string :name, null: false t.text :body, limit: 16777215 t.references :record, null: false, polymorphic: true, index: false t.datetime :created_at, null: false t.datetime :updated_at, null: false t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true end end end上記のデータを、
Article
モデルと紐づけることで、記事の内容をリッチテキストで編集することが可能になります。
データの紐付けは簡単で、以下のようにモデルに追加してください。article.rbclass Article < ApplicationRecord has_rich_text :content endどのようなデータ構造になっているのか
上記で説明した通り、
Article
テーブルでtitle
とdescription
を保持し、記事の内容(content
)は、ActionText::RichText
というテーブルに保持されています。以下のコンソールの結果を見るとイメージをしやすいと思います。# Articleモデルのデータを取得 irb(main):001:0> Article.all.first => #<Article id: 1, created_at: "2020-07-11 13:19:00", updated_at: "2020-07-11 13:19:00", title: "テスト", description: "テストです"> # Articleモデルに紐づいているActionText::RichTextのデータを取得 irb(main):002:0> Article.all.first.content => #<ActionText::RichText id: 1, name: "content", body: #<ActionText::Content "<div class=\"trix-conte...">, record_type: "Article", record_id: 1, created_at: "2020-07-11 13:19:00", updated_at: "2020-07-11 13:19:00"> # 記事の内容を取得するには? irb(main):003:0> Article.all.first.content.body => #<ActionText::Content "<div class=\"trix-conte...">
- 投稿日:2020-07-12T19:40:44+09:00
Action Textのデータ構成について
個人的に
ActionText
を導入する機会があったのでメモ。
blogサービスのようなものを開発する際に、Article
モデルにどのようにActionText
を導入すればいいのか悩んだので、誰かの役に立てればと思います。ActionTextとは
rails6から使えるようになった機能の1つ。
Railsにリッチテキストコンテンツと編集機能を導入できる。データ構成
ActionText
を導入するモデル作成
Article
モデルを生成します。
title
は記事のタイトル、description
は記事の説明文を表します。rails g model Article title:string description:text
ActionText
を導入する
ActionText
は以下のコマンドでインストールできます。rails action_text:installActionTextをインストールすると、2つのmigrationファイルが生成されます。1つは
Active Storage
に関わるファイルで、もう一つがActionText
のテーブルを作成するファイルです。後者のテーブルがこの記事ではターゲットとなります。ActionTextで編集された内容は、このテーブルに格納されるからです。class CreateActionTextTables < ActiveRecord::Migration[5.2] def change create_table :action_text_rich_texts do |t| t.string :name, null: false t.text :body, limit: 16777215 t.references :record, null: false, polymorphic: true, index: false t.datetime :created_at, null: false t.datetime :updated_at, null: false t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true end end end上記のデータを、
Article
モデルと紐づけることで、記事の内容をリッチテキストで編集することが可能になります。
データの紐付けは簡単で、以下のようにモデルに追加してください。article.rbclass Article < ApplicationRecord has_rich_text :content endどのようなデータ構造になっているのか
上記で説明した通り、
Article
テーブルでtitle
とdescription
を保持し、記事の内容(content
)は、ActionText::RichText
というテーブルに保持されています。以下のコンソールの結果を見るとイメージをしやすいと思います。# Articleモデルのデータを取得 irb(main):001:0> Article.all.first => #<Article id: 1, created_at: "2020-07-11 13:19:00", updated_at: "2020-07-11 13:19:00", title: "テスト", description: "テストです"> # Articleモデルに紐づいているActionText::RichTextのデータを取得 irb(main):002:0> Article.all.first.content => #<ActionText::RichText id: 1, name: "content", body: #<ActionText::Content "<div class=\"trix-conte...">, record_type: "Article", record_id: 1, created_at: "2020-07-11 13:19:00", updated_at: "2020-07-11 13:19:00"> # 記事の内容を取得するには? irb(main):003:0> Article.all.first.content.body => #<ActionText::Content "<div class=\"trix-conte...">結論
ActionTextは本当に簡単に導入できますが、データの仕組みが少し複雑なので注意してください。
また、私自身railsを勉強し始めて半年の未熟者ですので、間違いや不適切な表現があればご指摘ください。
- 投稿日:2020-07-12T19:05:07+09:00
Rails5でECサイトを作る⑧ ~Productモデル編、親子ともに条件つきで絞り込み表示~
はじめに
架空のベーカリーで買い物できるECサイトを作るシリーズ、Rails5でECサイトを作る⑦の続きです。
今回は商品の一覧、詳細を表示するProductモデルの実装です。商品の管理はadminサイト側で行うので、customerサイト側では画面を表示する処理のみになります。ただし、商品を束ねるGenreモデル、その下に属するProductモデルの両方に「販売中・停止」のステータスが存在します。商品ごとの販売中・停止を設定するほかに、ジャンルごとでも同様の設定を行えるということです。customerサイトで表示するのはGenre、Product両方で「有効」のものだけなので、その絞り込みが少々難しめです。
ソースコード
https://github.com/Sn16799/bakeryFUMIZUKI
Modelのアソシエーション
controller
app/controllers/products_controller.rbclass ProductsController < ApplicationController # サイドバー表示用 before_action :set_genres def show @product = Product.find(params[:id]) @cart = @product.cart_items.build end def index # ジャンルが有効 かつ 商品ステータスが有効 な商品を絞り込み @products = Product.includes(:genre).where(genres: {validity: true}).is_active.page(params[:page]).per(9) end private def set_genres @genre = Genre.is_valid end def product_params params.require(:product).permit(:name,:price,:image_id, :genre_id) end endindexにおいて、Genreモデル(親)のvalidityカラムと、Productモデル(子)のstatusカラムに条件を設定して絞り込みをかけています。これで、「ジャンルが有効」かつ「商品ステータスが有効」の商品群を取り出すことができました。また、ページャ(kaminari)を用意して、1ページにつき9個の商品が表示されるようにしています。
app/models/product.rbscope :is_active, -> { where(status: true) }app/models/genre.rbscope :is_valid, -> { where(validity: true) }controller内にあるis_activeとis_validは、いずれも商品、ジャンルの有効・無効を絞り込むスコープです。今回のアプリでは何回も行う処理ではないので別に必須ではないのですが、スコープを定義しておくことで後から修正しやすくなったり、コードソース上で何の処理をしているのか、視覚的に分かりやすくなったりします。
view
index画面
app/views/products/index.html.erb<div class="col-lg-10 space"> <div class="container"> <h2> <span style="display: inline-block;">全商品一覧</span> <span style="display: inline-block;">(<%= @products.count %>種)</span> </h2> </div> <div class="container"> <div class="row"> <% @products.each do |gp| %> <%= render 'products/box', product: gp %> <% end %> </div> </div> <%= paginate @products %> </div> <%= render 'genres/index', genres: @genres %>部分テンプレートは、'products/box'が商品1個ごとに写真・名前・値段などが載ったち小さなdivで、'genres/index'はジャンルごとに商品を見られるリンクを集めたサイドバーです。HTMLソースは前回の記事で公開しています。
show画面
app/views/products/show.html.erb<div class="col-lg-10 space"> <div class="container"> <div class="row"> <div class="col-lg-4 offset-lg-2"> <%= attachment_image_tag(@product, :image, :fill, 560, 420, fallback: "no_img.jpg") %> </div> <div class="col-lg-4"> <h3> <%= @product.name %> </h3> <h4>商品説明</h4> <%= @product.introduction %> <h4> <%= price_include_tax(@product.price) %> </h4> </div> </div> </div> <div class="container"> <div class="w-50 offset-lg-6"> <%= form_with(model: [@product, @cart], local: true, url: {controller: 'cart_items', action: 'create'}) do |f| %> <%= f.label :ご購入個数 %> <%= f.number_field :quantity, value: 1 ,min:1, max:99 %>個 <%= f.hidden_field :product_id, value: @product.id %> <%= f.submit "カートに入れる", class: "btn btn-danger" %> <% end %> </div> </div> </div> <%= render'genres/index', genres: @genres %>show画面では、商品の説明を見て、気に入ったものをカートに入れることができます。
空欄のフォームを表示するようにはなっていますが、CartItemControllerに何も書いていないため、現時点で「カートに入れる」ボタンを押すとエラーになります。ご注意を。
後記
商品がたくさん並んだ画面を作ったことで、見た目にはパン屋さんのサイトになりました。相変わらず機能面は皆無ですが。また、ページャや商品のボックスにCSSの加工を一切施しておらず、少し殺風景な感じは拭えません。装飾は最後にまとめて行う予定なので、まずは機能の完成を急ぎたいところ。
このECサイトの原型となっているのはスクールのチーム実装で作ったアプリなのですが、今見るとバリデーションなど意外と抜け落ちているところがあります。3人がかりで取り組んでも見逃す部分はあるのだなあと思いましたが、もしかしたら単にそこまで細かく要件定義された課題ではなかっただけかも知れません。
今回は2回目の開発なので、その辺りもこだわって実装していきたいと思います。次回へ続く!
参考
- 投稿日:2020-07-12T18:13:48+09:00
【Nuxt/Rails】formDataで画像をPOSTしてCarrierWaveで保存した
Nuxt.jsからformDataで画像をPOSTして、Railsで画像を保存する(CarrierWaveを使ってます)際に地味に詰まってしまったので備忘録を残します。
Rails
Google Cloud Storageに画像を保存していまして、設定諸々は以下の備忘録に書いてます。
https://qiita.com/arthur_foreign/items/43da529ab3beb760ba4b
※そのため、CarrierWaveの設定周りは省略しました。
また、実装としては記事のサムネイルを保存することとします。
model
article.rbclass Article < ApplicationRecord belongs_to :user mount_uploader :thumbnail, ImageUploader serialize :thumbnail endcontroller
articles_controller.rbclass ArticlesController < ApplicationController def create article_form = ArticleForm.new(article_form_params) if article_form.invalid? render_422(article_form) else @article = article_form.save! render json: @article, status: :ok, serializer: ArticleSerializer end end endserializer
article_serializer.rbclass ArticleSerializer < ActiveModel::Serializer attributes :thumbnail belongs_to :user, serializer: UserSerializer endform
article_form.rbclass ArticleForm include ActiveModel::Model include Virtus.model attr_reader :thumbnail, :user_id attribute :thumbnail, String attribute :user_id, User def save! Article.create!( thumbnail: thumbnail, user_id: user_id ) end endVue/Nuxt
画像を送信する時のformDataのみ書いてます。
<script> methods: { async handleSubmit() { const formData = new FormData() const blob = new Blob([this.image], { type: this.thumbnailType }) formData.append('article[thumbnail]', blob, this.thumbnailName) await this.postArticle(formData) }, }, </script>※画像の設定は別の備忘録に書こうと思います。
- 投稿日:2020-07-12T16:51:56+09:00
hamlでYouTube動画をDBから呼び出して埋め込み表示させてみた
自作アプリでYouTubeの動画を埋め込み表示させてみた時に見付けた方法
自作アプリの作成でお気に入りの動画を一旦DBに保存して、呼び出す際に埋め込み表示させたかったので、色々模索したやり方を紹介します。
一般的な埋め込みの方法
好きなYouTube動画の共有ってところを選ぶ
これをHTML(haml)に直接貼り付ければ完成
ただ、これでDBに投稿して、hamlファイルから呼び出そうとすると文字列で出てしまったので、それを解消する方法です。
実際に行ったやり方
%iframe#player{frameborder: "0", height:"390", src: (movie.url), type: "text/html", width: "640"} ※今回はMovieモデルと言うのを作って、カラム名をurlにしてます簡単に言うと、
・外枠の部分はhamlファイルにしておく(サイズ等はお好みで変えられるはずです)
・DBにはURL部分のみ保存→呼び出す記述にしてます
・タイトルや内容なども別のカラムで保存こうする事で、DBに投稿→呼び出しの際も埋め込み表示に出来ました。
実際の画像(まだ開発中ですが)
1つ注意ポイント
私が使ったURLですが、この青下線の部分です(ダブルクォーテーションは要らないです)
こっちの青下線のURLではダメでした。
おそらく埋め込み用のURLでは無いからだと思います。以上、同じ様な実装をされたい方の参考になれば幸いです
- 投稿日:2020-07-12T16:02:11+09:00
[Rails] enumを使って下書き機能を作った
はじめに
下書き機能を作ろうと思った時にあまり記事がなかったので記録として残しておこうと思いました。
開発環境
ubuntu(WSL) Ruby 2,5.1 Rails 6.0.2事前準備
以下の機能は作成済みとします。
- 投稿機能・詳細・削除・編集(Post)
- ユーザーの作成・詳細(User)
models/post.rbbelongs_to :usermodels/user.rbhas_many :microposts, dependent: :destroyPostテーブルにカラムを追加する
まずはPostモデルにstatusカラムを追加しboolean型にします。
booleanでなくintergerでも可能です。
以下のコマンドを入力します。bin/rails g migration AddStatusToPost status:booleanマイグレーションファイルを編集します。
migrationfile.rbdef change add_column :microposts, :status, :boolean, default: true, null: false end編集したらマイグレートします。
Postモデルにenumを追加する。
models/post.rbenum status: { draft: false, published: true }statusカラムのdraft(下書き)をfalseに指定し、statusカラムのpublished(公開)をtrueに指定します
ユーザーごとの情報を取得
@user
でuserのidを取得。users_controller.rb#下書き用 def confirm @user = User.find(params[:user_id]) @microposts = @user.microposts.draft.page(params[:page]) end #公開用 def show @user = User.find(params[:id]) @microposts = @user.microposts.published.page(params[:page]) endルーティングを追加
collection
をつけるとURLにidが付かなくなりますroutes.rbresources :users do get 'confirm' endViewの設定
関係あるところだけを抜粋しました。
view/users/show.html.slim//ユーザーの詳細画面 = link_to "投稿一覧", @user = link_to "お気に入り", user_likes_path(current_user) = link_to "下書き一覧", user_confirm_path(current_user) //自分の投稿を表示する - if @microposts.present? = render "microposts/list", microposts: @microposts - else h4 投稿はありません下書き一覧は自分の好みに合わせて書いてください。
view/users/confirm.html.slimh4 下書き一覧 table.table.table-hover thead.thead-default tr th = Micropost.human_attribute_name(:title) th = Micropost.human_attribute_name(:content) th = Micropost.human_attribute_name(:created_at) th tbody - @microposts.each do |micropost| tr td = link_to micropost.title, micropost td = link_to micropost.content, micropost td
icroposts/list
の中身は上記と同じです。終わりに
間違いがありましたら編集リクエスト、コメントをお願いします。
参考文献
- 投稿日:2020-07-12T15:56:35+09:00
gitでコミットを取り消したい(特定のコミット番号まで戻したい時)
こんな人におすすめ
『あああコミットしたけど元にもどしたいなー』『マージしたけどブランチ内で昔の履歴みたいなー』
なんて時、履歴を見て、ささっと取り消してしまいましょう。環境
ruby 2.5.1 Rails 5.0.7.2手順
1)自分がいるブランチのコミットログを調べる
git logこういうのが出てきます。
ユーザー名@ユーザー名noMacBook-Pro アプリケーション名 % git log commit 8af1dXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (HEAD -> 今いるブランチ名, origin/今いるブランチ名) Author: ユーザー名 <メールアドレス> Date: Sun Jul 12 15:28:51 2020 +0900 コミットした時のコメント commit 239b0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Author: ユーザー名 <メールアドレス> Date: Thu Jun 25 23:36:58 2020 +0900 コミットした時のコメント commit ed8ccXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX Author: ユーザー名 <メールアドレス> Date: Thu Jun 25 17:31:52 2020 +0900 コミットした時のコメント2)戻したい場所のハッシュ値を確認
commit ed8ccXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX3)リセットする
git reset --hard ed8ccXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX完了done!
- 投稿日:2020-07-12T14:05:57+09:00
Railsで表示時間を日本時間に設定する方法
やりたいこと
投稿時間を国際標準時間から日本時間の表示に変更したい
設定の方法
config/application.rb
内にconfig.time_zone = 'Tokyo'
の記述を追加application.rb# ↑これ以前のコードは割愛 module App class Application < Rails::Application config.time_zone = 'Tokyo' end end
- サーバーが立ち上がっている場合は一度シャットアウトして再度立ち上げ直す
※dockerを起動している場合は、下記でコンテナを立ち上げ直す(ターミナルで下記コマンドを実行)
docker-compose stop
docker-compose up -d
これで日本時間で表示されるが、フォーマットを別途変更する必要あり
strftimeメソッド
を使って、表示フォーマットを変えたい箇所にメソッドを当てるsample.html.erb# 下記はサンプル <td><%= @tweet.created_at.strftime('%Y年%m月%d日 %H時%M分') %></td>変換のメソッドを定義する方法
やること:Initializeにフォーマット変換を定義する
config/initializers配下
にtime_formats.rb
というファイルを作成するTime::DATE_FORMATS[:datetime_jp] = '%Y年%m月%d日 %H時%M分'
と記述するtime_formats.rbTime::DATE_FORMATS[:datetime_jp] = '%Y年%m月%d日 %H時%M分'※ [:datetime_jp] は任意の命名でOK
※ '%Y年%m月%d日 %H時%M分' には変換したいフォーマットを記述する
- 使いたい箇所(viewファイル内)で .to_s(:datetime_jp]) と記述して使う
sample.html.erb# 下記はサンプル <td><%= @tweet.created_at.to_s(:datetime_jp) %></td>
- 投稿日:2020-07-12T13:36:32+09:00
【Rails】プロフィールに自己紹介機能を実装するシンプルな方法
プロフィールに自己紹介機能を実装する
ポートフォリオ完成後、追加実装したので順序を備忘録として残します。
ユーザー名・email・パスワードなどの既存カラムに、introductionカラムを新たに追加します。
なるべくシンプルに記します!どうやって?
以下の順序です。
- git checkout -b introduction (ブランチ切る)
- usersテーブルにintroductionカラムを追加する
- データベースに反映させる
- usersコントローラーに必要コードの追記
- userモデルに必要コードの追記
- ユーザー詳細ページ(MYPAGE)に表示させる
- ユーザー編集ページ(EDIT)に表示させる
- 完成!
以下順番に記します!
1. git checkout -b introduction (ブランチ切る)
新たな機能を実装するため、ブランチを切リます。
2. usersテーブルにintroductionカラムを追加する
ターミナル$ rails generate migration AddIntroductionToUsers introduction:text invoke active_record create db/migrate/20200712005652_add_introduction_to_users.rb上記rails gコマンドでintroductionカラムを追加します。
3. データベースに反映させる
ターミナル$ docker-compose run web rails db:migrate == 2020~~~~ AddIntroductionToUsers: migrating =========================== -- add_column(:users, :introduction, :text) -> 0.0518s == 2020~~~~ AddIntroductionToUsers: migrated (0.0519s) ==================4. usersコントローラーに必要コードの追記
private methodに追記
introduction属性を付与するusers_controller.rbdef user_params_update params.require(:user).permit(:name, :email, :image, :introduction) # introdution追加 endこれでintroductionをupdate可能になります
5. userモデルに必要コードの追記
バリデーションを追加します。自己紹介は50文字以内で入力させます。
文字数は自由に設定してください。
※presenseですが、falseにしないと新規登録時に作用してintroductionがnilとなって新規登録できなくなりますので注意してください。新規登録時に自己紹介も入力必要な場合とするならtrueでOKです。user.rbvalidates :introduction, presence: false, length: { maximum: 50 } # 自己紹介の最高文字数は50文字6. ユーザー詳細ページ(MYPAGE)に表示させる
show.html.slim= @user.introductionSCSSなどで適宜修正してください
7. ユーザー編集ページ(EDIT)に表示させる
ユーザー編集はユーザー名・emailのみでしたがそこにintroductionを追記します。
edit.html.slim.form-group = f.label :introduction = f.text_area :introduction, class: 'form-control', id: 'user_introduction'完成
以上で自己紹介をusersテーブルに追加し、introduction属性を追加完了しました。
途中でintroductionをintroduceと書いていたりしたので、皆様も注意してください!
- 投稿日:2020-07-12T13:08:42+09:00
undefined method `user_signed_in?'と出たときの対処法
日々学んだことやつまずいたことについてまとめていきます。
記載に誤りがありましたら、ご指摘していただけると助かります!
いつも他のかたの記事に助けられているので、少しでもお役に立てればと思います。どういうエラーなのか
deviseで使えるようになる、 user_signed_in ヘルパーメソッドが定義されていないというエラー。
どんなときに起こるのか
1.deviseがインストールされていないとき。
2.routes.rbにdevise_for :users などの記述がないとき。対処法
1.
Gemfileに以下を記述。gem 'devise'ターミナルで以下を実行。
gemをインストール
bundle install設定ファイルを作成
rails g devise:installログイン機能に対応したモデルを作成
rails g devise userログイン機能に関連するテーブルを作成
bundle exec rake db:migrate2.
routes.rbに以下を記述devise_for :users
- 投稿日:2020-07-12T12:12:17+09:00
【1対多】の関連付け
個人的備忘録
ターミナルでモデルの関連付けをするときにいつも忘れるのでメモ。
Attendanceモデルをuserモデルに紐付けたいときに使う。
重要なのは最後の user:references 。$ rails g model Attendance worked_on:date started_at:datetime finished_at:datetime note:string user:references以下のt.references :user, foreign_key: true が表示されていればおk
class CreateAttendances < ActiveRecord::Migration[5.1] def change create_table :attendances do |t| t.date :worked_on t.datetime :started_at t.datetime :finished_at t.string :note t.references :user, foreign_key: true t.timestamps end end end$ rails db:migrate結果。
# This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # # Note that this schema.rb definition is the authoritative source for your # database schema. If you need to create the application database on another # system, you should be using db:schema:load, not running all the migrations # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema.define(version: 20190523135500) do create_table "attendances", force: :cascade do |t| t.date "worked_on" t.datetime "started_at" t.datetime "finished_at" t.string "note" t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["user_id"], name: "index_attendances_on_user_id" end create_table "users", force: :cascade do |t| t.string "name" t.string "email" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "password_digest" t.string "remember_digest" t.boolean "admin", default: false t.string "department" t.datetime "basic_time", default: "2019-05-22 23:00:00" t.datetime "work_time", default: "2019-05-22 22:30:00" t.index ["email"], name: "index_users_on_email", unique: true end end最後に格モデルに対してコードを記述するのを忘れずに。
class User < ApplicationRecord has_many :attendances, dependent: :destroyclass Attendance < ApplicationRecord belongs_to :userこれで関連付けができました。
- 投稿日:2020-07-12T11:09:04+09:00
【Rails】RspecでCapybaraを使用した際に「undefined method `visit'」というエラーが出た場合の解決方法
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・rspec-rails: 4.0.1
・Capybara: 3.32.2
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina前提
下記実装済み。
・Slim導入
・Bootstrap3導入
・Font Awesome導入
・ログイン機能実装
・投稿機能実装原因
Capybaraが読み込めていない。
解決方法
1.
require
で読み込むspec_helper.rbrequire 'capybara/rspec' # 追記 RSpec.configure do |config| end2. 解決方法1で解決しない場合は
DSL
で強制的に読み込むspec_helper.rbrequire 'capybara/rspec' RSpec.configure do |config| config.include Capybara::DSL # 追記 end
- 投稿日:2020-07-12T10:56:25+09:00
booleanのvalidateについて
booleanのカラムについて、バリデーションをかけたがvalid?がtrueにならず、期待していた実行とは違うものになってしまった!
そこで、booleanのカラムについて調べたことを備忘録としてまとめておく!
ダメなパターン:Notnull制約でfalseが入っているので、presence: trueをすれば良いと思い下記のようにした!
validates :check, presence: trueしかし、これだとcheck=falseの時にエラーが出てしまう!
調べてみると、下記のようにする必要があることがわかった!
validates :check, inclusion: {in: [true, false]}
- 投稿日:2020-07-12T09:54:28+09:00
[Rails]No route matches [GET] "/users/sign_out”の対処法
はじめに
ログアウトを実行するとルーティングエラーが発生したのでアウトプット
環境
Rails 5.0.7.2
ruby 2.5.1
devise問題点
deviseのアカウント編集機能を実装し、ログアウトをリクエストすると、
No route matches [GET] "/users/sign_out”とエラー発生原因
sign_out時のメソッドがDELETEからGETに変更されているので(いつなったのかは把握できていない)、変更すれば解決しそう。
対処方法
config/initializers/devise.rbを編集▼
devise.rb#省略 config.sign_out_via = :delete #省略上記の記述をgetに変更▼
devise.rb#省略 config.sign_out_via = :get #省略サーバーを再起動して、rake routesをターミナルにて実行すると▼
destroy_user_session GET /users/sign_out(.:format) devise/sessions#destroygetメソッドに変化しているので再度ログアウトを実行すると想定通りの動作をするはず!
参考にしてください!
- 投稿日:2020-07-12T02:58:36+09:00
all_month が気になって ActiveSupport DateAndTime::Calculations を読んでみた
これ何
先輩にレビュー中に、 all_month 使った方がいいんじゃない?と言われたので、気になって調べてみた。
ActiveSupport の DateAndTime::Calculations に定義されていたので、周りのmethodも読んでみる範囲指定のmethod
all_monthの内部実装を眺めてみた。rails/railsの内部実装だが、読めるコードでわかる。
def all_month beginning_of_month..end_of_month endref: activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
同じファイルの中を見てみるとall_month 以外にも all_xxx methodが存在した。対象範囲が変わるだけで、使えそうなmethodが多い。
- all_day
- all_month
- all_quarter:3ヶ月ごとの日時情報が取れる
- all_week:週の開始日を決めることができる
- all_year
気づき 1. future?, past?
未来・過去かを判定するmethodが存在する!再定義しなくても、rails/railsであるものを使える!!気づき。
Date.yesterday.past? => true Date.yesterday.future? => false Date.tomorrow.future? => true Date.tomorrow.past? => false気づき 2. all_xxxと同様にnext_xxx, prev_xxxも存在する
next_xxx, prev_xxx が定義されている。 prev_xxx は last_xxx にaliasされている。
Date.current => Sun, 11 Jul 2020 Date.current.next_week => Mon, 13 Jul 2020 Date.current.prev_week => Mon, 29 Jun 2020 Date.current.last_week => Mon, 29 Jun 2020参考文献