20210801のRailsに関する記事は15件です。

pumaのログをターミナルに出力する

解決策 以下を追記 config/environments/development.rb config.logger = Logger.new(STDOUT)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails+Vue.js]〜分前を実装してみた

はじめに Q&Aサイトを作成している中で、質問の投稿時刻をTwitterのような〜分前にしたいと考えました。 しかし、Railsから渡される値をそのまま使うと、 のようになってしまいます。 そこで今回は、Moment.jsを用いて相対時刻の表示をしたいと思います。 バージョン等 Rails 6.1.3 Vue.js 2.6.11 Moment.js 2.29.1 手順 まずは、moment.jsをインストールします npm install moment --save 次に〜分前表示をしたいコンポーネント内に以下の記述をします。 <script> import moment from "moment"; export default { filters: { moment: function(date) {                 moment.locale("ja"); return moment(date).fromNow(); }, }, </script> コードの解説をすると、 moment.locale("ja");で日本語表示にしています。 returnでmoment(date)の後に、希望のフォーマットになるようにメソッドを記述します。 ここに関しては、 https://blog.capilano-fw.com/?p=1033 が参考になりました。 あとは、Vueのフィルターを使用して、 {{ question.created_at | moment }} とすると、 〜分前のフォーマットで表示することができました! まとめ Railsから渡された値を、フロント側で処理をすることができました。 また、最近ではDay.jsがMoment.jsよりも処理が早いとも聞いたのでこれから導入する方は調べてみるのもいいかもしれません。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

binding.pryを使えるようになりたい!

はじめに 本記事は、「binding.pry」を今後活用できるようにするため、 現時点で学習したことをアウトプットします。 インストール pry-railsというGemをインストールする必要があります。 Gemfileに以下のコードを記述します。 gem 'pry-rails' その後、ターミナルにてbundle installします。 「binding.pry」に限らず、Gemをインストールする際には、bundle installします。 エラーが発生した場合、原因がどのコードにあるのかを「binding.pry」を使って確認することができます。 コードで「binding.pry」という文字列をコード内に記述すると、 そこで、処理が止まります。 その後からの処理の結果を手動で確認することができます。 例文 class OrdersController < ApplicationController def index @order = Order.new end def create @order = Order.new(order_params) binding.pry if @order.valid? @order.save return redirect_to root_path else render 'index' end end private def order_params params.require(:order).permit(:price) end end 今回は、Ordersコントローラーのcreateアクションにエラーはないのかを確認するために、 9行目で、「binding.pry」を発動しています。 ここで「rails s」サーバーを起動させ、 指定した行為を実行すると、 ターミナル上で、 [1] pry(#<OrdersController>)> と表示されます。 その後からの処置がどうなるのかを試したい時に、 その後の処理を記述することで、結果を確認することができます。 10行目で、 if @order.valid? という記載があるので、 [1] pry(#<OrdersController>)> @order.valid? と記述します。 すると、 [1] pry(#<OrdersController>)> @order.valid? => false コード全体を記述していないため、わかりづらいですが、 結果は、「エラー」となりました。 *「valid?」は、エラーがある時は「false」、ない時は「true」となります。 コントローラーのcreateアクションでミスが発生しているということですね。 終わり 学習段階で、ここまでの理解です。 正直申し上げると、理解が浅く、使いこなせるレベルまで到達していないことが、 今回投稿してみてわかりました。 明日、メンターへさらに理解をするために、 質問し、理解を深めます。 さらに深く説明できるようになれば、また投稿したいと思います。 それでは、引き続きがんばりましょう!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MVCについて(仕事で実際に触れてみて)思ったこと

イントロダクション 4月より転職してエンジニアとして働いています。 業務ではRails、フロントはVue.jsを使用した開発に携わらせてもらっています。 タイトルの通り、MVCモデルについて実務を通して思ったことを書いていくのですが、せっかくなので、自分の知識の復習も兼ねてMVCモデルとはというところから話してみたいと思います。 MVCとは ググればめちゃくちゃ記事出てくるのと、本筋ではないのでさっくりと書かせていただきます。 M(モデル)・・・データを加工する場所 C(コントローラー)・・・データをモデルやビューに受け渡す場所 V(ビュー)・・・見た目を整える場所 それぞれ上記のように役割を明確にすることで、開発をしやすく、かつ保守なども行いやすいというメリットがあります。 実際、僕のような業務に入り始めて間もないものでも、このMVCモデルのおかげで開発に携われるようになっています。 レストランで例えると キッチン・・・モデル。データ(食材)を美味しい料理に加工する ウェイター・・・コントローラー。加工された料理をお客様のもとに運んだり、お客様から受け取った注文をキッチンに伝えたりする。 ビュー・・・料理そのもの。見た目整えればお客様の食欲そそる(UI向上)。 自分なりにMVCモデルについてなにかわかりやすい例えないかなと考えた結果、レストランめっちゃわかりやすいやん! って思ったけど、調べてみたら結構これも記事にされていた(本当に自分で考えましたよ!)。 MVCのメリットって? さっきも書きましたけど、M・V・Cそれぞれで明確に役割を持っているので、開発しやすい。 また、モデルだけ改善させたいのよね〜とかいうときに改善させやすい。 実務で扱っていてエラーが起きたとしても、どこでエラー起きているのか判断しやすいというのもメリットかと感じています。 MVCのデメリットって? 現状、Railsしか経験していないため、もしかしたらRailsに限ってしまうかも知れませんが、 モデルで行うべき処理をコントローラーで行えてしまうというのが今の所僕が感じる最大のデメリットかなと感じています。 本来、データの加工などはモデルで行うべきとされていますが、Railsのその自由度のおかげでコントローラーで書いても正常に動いてしまいます。 その瞬間はそれで良いのかも知れませんが、コントローラーをファットにしてしまうと、その後機能を追加しようとしたときにボディブローのように効い来ている場面を見かけます。 そして、いざどうしようもなくなったときにコントローラーをリファクタリングすることになり、結局モデルにビジネスロジックを移行するという作業が増えてしまう(もしくは複雑になりすぎて手が出せないということになりかねない)。 まとめ 一言でまとめると「取り返しがつかないことになるかも知れないので、コードを書くときはMVCの役割に沿った場所で書くべき」なのだと実務を通して感じております。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] VSCodeを入れたらやること

はじめに ほとんどの方が開発するために用いるエディタとしてVSCodeを使っていることでしょう。 Railsで開発していく上で私が初めてVSCodeを導入したときに、最低限入れておくべきと思った、拡張機能や、設定を忘れないうちに記事に残しておきたいと思います。 もしおすすめ拡張機能があれば教えていただけると幸いです。 よろしくお願いします。  ##VSCodeの日本語化 我々が親しんでいる日本語で表示させたい人はまずはこれをするべきですね。 英語の方が使いやすいって人や、ストイックな人はする必要はないです。 拡張機能の検索に「Japanese Language Pack for Visual Studio Code」と打ち込むと出てきます。 検索予測で出てくるので全部打ち込む必要はありません。 インストールした後、再起動しないと反映されなかったりするので気を付けましょう。 HTML/CSS自動補完機能 続いてHTMLとCSSの自動補完をしてくれる拡張機能を入れます。 拡張機能の検索フォームで「HTML Snippets」で検索してインストールします。 Rubyの構文チェック Rubyの構文チェックをしてくれます。Rubyを使って開発をするのであれば必須でしょう。 拡張機能の検索フォームで「Ruby」と検索すると出てきます。 全角スペースのチェック機能 全角スペースにより、動作しない場合、それを見つけるのは苦労します。 全角スペースになっているところを検出してくれる拡張機能です。 拡張機能の検索フォームで、「zenkaku」と入力すれば出てきます。 zenkakuを利用するにはまだ設定が必要です。 インストールが完了した後「command + shift + p」の三つのキーを同時に入力し、コマンドパレットという設定ファイルの検索画面を開きます。 そこに「> Enable zenkaku」と入力して選択します。 「command + Q」の二つのキーを同時に入力してVSCodeを終了させます。 続いて常にzenkakuをONにしておくための設定もしておきます。 finderでホームディレクトリを開く command + shift + .で隠しディレクトリを表示する  > .vscode > extensions > mosapride.zenkaku-0.0.3 > と移動する extension.jsを2本指タップしてメニューを表示する 「このアプリケーションを開く」から「テキストエディット」を選択する 5行目の「var enabled = false;」を「var enabled = true;」に変更してcommand + Sで保存する これで完了です。 コードのスペルチェック コードのスペル間違いを指摘してくれる拡張機能を追加します。 拡張機能の検索フォームで「Code Spell Checker」と入力してインストールします。 オートセーブ設定 最後に拡張機能ではなくVSCode自体の設定をいじります。 「command + , 」で設定画面を開けます。 一番上のAuto Saveというところのプルダウンから「onFocusChange」を選択します。 最後に あくまでこれは私が最初に行った設定です。他にも便利機能や必須の拡張機能や設定があれば教えて欲しいです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ウィザード形式でデータを保存できない‥

こんにちは オリアプ作成中に思うような実装にならなかったので メモの代わりに記事にしました。 実装したい機能 ユーザー新規登録を行う際に、 admin_usersテーブルと詳細なプロフィールの 投稿を行うadmin_profilesテーブルを生成しました。 admin_usersテーブル t.string :store_name, null: false t.string :email, null: false, default: '', unique: true t.string :encrypted_password, null: false, default: '' admin_profilesテーブル t.string :postal_code, null: false t.integer :prefecture_id, null: false t.string :municipality, null: false t.string :address, null: false t.string :building_name t.string :phone_number, null: false t.text :profile, null: false t.references :admin_user, null: false AdminUserモデル PASSWORD_REGGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i.freeze validates_format_of :password, with: PASSWORD_REGGEX validates :store_name, presence: true has_many :events has_one :admin_profile AdminProfileモデル belongs_to :admin_user, optional: true has_one_attached :admin_image extend ActiveHash::Associations::ActiveRecordExtensions belongs_to :prefecture with_options presence: true do validates :postal_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/ } validates :prefecture_id, numericality: { other_than: 1, message: "can't be blank" } validates :municipality validates :address validates :phone_number, format: { with: /\A\d{10,11}\z/ } validates :profile validates :admin_image end AdminProfileモデルで has_one_attached :admin_imageと 記述しているのは、ActiveStrageを用いてプロフィール画像を 保存したいからです。 admin_userとadmin_profileは1対1の関係で admin_user has many admin_profile admin_profile belongs_to admin_user このadmin_usersテーブルとadmin_profilesテーブルを使用して ユーザー登録機能をウィザード形式で実装することを試みました。 エラー表示は起こらないのにデータが保存されない‥ admin_users/registrations_controller def new @admin_user = AdminUser.new end def create @admin_user = AdminUser.new(sign_up_params) render :new and return unless @admin_user.valid? session['devise.regist_data'] = { admin_user: @admin_user.attributes } session['devise.regist_data'][:admin_user]['password'] = params[:admin_user][:password] @admin_profile = @admin_user.build_admin_profile render :new_admin_profile end def create_admin_profile @admin_user = AdminUser.new(session['devise.regist_data']['admin_user']) @admin_profile = AdminProfile.new(admin_profile_params) render :new_admin_profile and return unless @admin_profile.valid? @admin_user.build_admin_profile(@admin_profile) @admin_user.save session['devise.regist_data']['admin_user'].clear sign_in(:admin_user, @admin_user) end private def admin_profile_params params.require(:admin_profile).permit(:admin_image, :postal_code, :prefecture_id, :municipality, :address, :building_name, :phone_number, :profile) end まじで辛かったです。 2週間ほど悩み倒しました。 エラーにはならないしbinding.pryしてみても paramsにデータは入ってたので データを保存する段階で何か不備が起きていたのだろうとは思ってましたが、 それがなかなか見つからず‥。 ActiveStroageが邪魔してる 詳細な原因は不明ですが、どうやらActiveStrageがデータの保存の 邪魔をしてたみたいです。 ActiveStrageのファイルが保存されるタイミングって、saveトランザクションが コミットされた後だそうです。 コミットされた後に保存しようとするから外部キーのadmin_userを nilの状態で登録しようとしてしまい、ActiveStrageの保存と admin_user_idの外部キーのvalidationの関係で 保存されなかった説が濃厚です。 なので、 admin_users/registrations_controllerの @admin_user.build_admin_profile(@admin_profile) @admin_user.save これを @admin_user.save @admin_profile.admin_user_id = @admin_user.id @admin_profile.save に変更してやったら無事全て保存することができました!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新規登録画面実装② devise 新規登録の項目追加 別モデルから取得

やりたいこと devise導入済みです。 ①の記事では、userモデルのカラムを deviseの新規登録画面に表示、登録できるようにしましたが、 今回は別モデルであるDepartment(部署)を登録したいです! 3時間程戦いました・・・。 departmentとuserの関係は、1:Nにしてます。 (userは1つの部署に所属。部署は複数のuserを持つ) modelファイルにアソシエーション ここら辺はなんてこと無く出来ました。 models/user.rb belongs_to:department models/department.rb has_many:users, dependent: :destroy マイグレーションファイル class CreateDepartments < ActiveRecord::Migration[5.2] def change create_table :departments do |t| t.string :name,null: false   #表示名 t.string :correct_name #正式名称 t.timestamps end end end 部署名は、会社によっては長くなりがちで、、あまり長いと厄介なので、 表示名と正式名称でカラムを分けました。 class DeviseCreateUsers < ActiveRecord::Migration[5.2] 省略 t.integer :department_id,null:false 省略 department_idは外部キーです。 部署idを登録させる  Applicationコントローラー class ApplicationController < ActionController::Base # ユーザー認証などが行われる前に、configure~が実行される before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters # デフォルトにないname/join_year/部署を追加しているので、それらを許可するよう記載している devise_parameter_sanitizer.permit(:sign_up, keys: [:name,:join_year,:department_id]) end end ちゃんとdepartment_idを受け取って保存するように指示します。 新規登録画面に入力フォームを追加 <div class="form-group"> <%= f.label:"所属先" %><br /> <%= f.collection_select(:department_id, @departments, :id, :name, class: "form-control") %> </div> これで、完成!!!!だと思ってました...。 しかしこれだと@departmentsを渡せてないので、 undefined methodmap' for nil:NilClassというエラーが出てきます。 どこに@departmentsの値を定義すれば・・・・? @departmentsの値を定義する controllers/users/registrations_controller.rbに書きます! あることに気づかず、rails g devise:controllers usersをやってしまいました。 (無ければ、rails g devise:controllers usersで、コントローラー作れます) class Users::RegistrationsController < Devise::RegistrationsController # before_action :configure_sign_up_params, only: [:create] # before_action :configure_account_update_params, only: [:update] def new @user = User.new @departments = Department.all end 省略 ルーティングを直す 上記のコントローラーを通過してビューを表示してほしいので、ルーティングを直します。 routes.rb Rails.application.routes.draw do devise_for :users, controllers: { registrations: 'users/registrations' } # devise_for :users  ←元々はコレだった マイページでの部署の表示 users/show/html.erb 省略 <div style="text-align:center;"><%=link_to departments_path do %><%= user.department.name %><% end %></div> <div style="text-align:center;"><%= user.name %></div> 省略 完成! 無事に部署の登録、マイページでの表示に成功しました!! 参考にさせていただいた記事 ありがとうございます!この記事のおかげでなんとか実装できました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails + Vue.jsで都道府県に応じた市区町村を表示するセレクトボックスを作成する

はじめに 表題のようなセレクトボックスを作成する機会があったため備忘録として記事を残しておきます。 完成品 本記事ではrails newから始め、以下のようなセレクトボックスを作成するところまで手順を書いていきます。 環境 Ruby 2.7.3 Rails 6.0.4 Vue 2.6.14 1. 都道府県, 市区町村モデル作成 以下のER図のような都道府県(Prefecture), 市区町村(City)モデルを作成していきます。 まずはrails newでRailsアプリケーションを新規作成します。 $ rails _6.0.4_ new example_app $ cd example_app $ rails db:create 都道府県(Prefecture)モデルを作成していきます。 $ rails g model Prefecture name:string Running via Spring preloader in process 71121 invoke active_record create db/migrate/20210731145941_create_prefectures.rb create app/models/prefecture.rb マイグレーションファイルを以下のように編集しましょう。 都道府県名は一意なのでunique制約を付けておきます。 db/migrate/20210731145941_create_prefectures.rb class CreatePrefectures < ActiveRecord::Migration[6.0] def change create_table :prefectures do |t| t.string :name, null: false t.timestamps end add_index :prefectures, :name, unique: true end end マイグレーションをDBに適応させます。 $ rails db:migrate == 20210731145941 CreatePrefectures: migrating ================================ -- create_table(:prefectures) -> 0.0010s -- add_index(:prefectures, :name, {:unique=>true}) -> 0.0004s == 20210731145941 CreatePrefectures: migrated (0.0016s) ======================= モデルファイルにnameカラムのバリデーションを追記します。 app/models/prefecture.rb class Prefecture < ApplicationRecord validates :name, presence: true, uniqueness: { case_sensitive: false } end 次に市区町村(City)モデルを作成します。 $ rails g model City name:string prefecture:references Running via Spring preloader in process 71410 invoke active_record create db/migrate/20210731150527_create_cities.rb create app/models/city.rb マイグレーションファイルを以下のように編集しましょう。 市区町村は名称の重複があるためユニーク制約は付けないようにします。 db/migrate/20210731150527_create_cities.rb class CreateCities < ActiveRecord::Migration[6.0] def change create_table :cities do |t| t.string :name, null: false t.references :prefecture, null: false, foreign_key: true t.timestamps end end end マイグレーションをDBに適応させます。 $ rails db:migrate == 20210731150527 CreateCities: migrating ===================================== -- create_table(:cities) -> 0.0017s == 20210731150527 CreateCities: migrated (0.0018s) ============================ モデルファイルにnameカラムのバリデーションを追記します。 app/models/city.rb class City < ApplicationRecord belongs_to :prefecture validates :name, presence: true end また都道府県(Prefecture)モデルに市区町村(City)とのアソシエーションを追記します。 app/models/prefecture.rb class Prefecture < ApplicationRecord has_many :cities validates :name, presence: true, uniqueness: { case_sensitive: false } end 2. 都道府県, 市区町村オブジェクトを作成する 総務省のサイトから都道府県, 市区町村のリストデータ(Excelファイル)をダウンロードしましょう。 ダウンロードしたらExcelやNumbersで開きCSVファイルとして書き出しを行います。 書き出したCSVファイルをRailsアプリケーションのlib/フォルダに入れましょう。 このCSVファイルをRubyで読み込み、都道府県のデータと市区町村のデータをうまく配列に変換していきます。 CSVファイルを開いてみると以下のようになっていると思います。 1列目に自治体コード, 2列目に都道府県名, 3列目に市区町村名...といったようになっています。 lib/自治体一覧表.csv 010006,北海道,,ホッカイドウ,,, 011002,北海道,札幌市,ホッカイドウ,サッポロシ,, 012025,北海道,函館市,ホッカイドウ,ハコダテシ,, 012033,北海道,小樽市,ホッカイドウ,オタルシ,, 012041,北海道,旭川市,ホッカイドウ,アサヒカワシ,, ... このデータを使い都道府県の配列を作っていきます。 require 'csv' # CSV読み込み file_path = 'lib/自治体一覧表.csv' # CSVを1行毎の配列へ変換 csv_data = CSV.read(file_path) # => [["010006", "北海道", nil, "ホッカイドウ", nil, nil, nil], ["011002", "北海道", "札幌市", ... csv_dataを以下のように処理すると2列目の都道府県名のみの配列になります。 # 2列目のみの配列へ変換 csv_data.map { |row| row[1] } # => ["北海道", "北海道", "北海道", "北海道", ... "沖縄県", "沖縄県", "沖縄県"] # uniqメソッドを使用することで重複を削除できます prefectures_list = csv_data.map { |row| row[1] }.uniq # => ["北海道", "青森県", "岩手県", ... "宮崎県", "鹿児島県", "沖縄県"] 次に市区町村の配列を作っていきます。 市区町村オブジェクトを作成する際、都道府県名も必要となってくるため以下のような配列を作ることを目標としていきます。 [["北海道", "札幌市"], ["北海道", "函館市"], ... ["沖縄県", "竹富町"], ["沖縄県", "与那国町"]] 都道府県の配列を作ったコードに習うと以下のようなコードになると思いますが元データの都合上nilの入ったデータが出来てしまいます。 # 2, 3列目のみの配列へ変換 csv_data.map { |row| row[1, 2] } # => [["北海道", nil], ["北海道", "札幌市"], ... ["沖縄県", "竹富町"], ["沖縄県", "与那国町"]] # 3列目がnilだった場合処理を飛ばす csv_data.map do |row| next if row[2] == nil row[1, 2] end # => [nil, ["北海道", "札幌市"], ... ["沖縄県", "竹富町"], ["沖縄県", "与那国町"]] # compactメソッドで配列内のnilを削除 cities_list = csv_data.map do |row| next if row[2] == nil row[1, 2] end.compact # => [["北海道", "札幌市"], ["北海道", "函館市"], ... ["沖縄県", "竹富町"], ["沖縄県", "与那国町"]] 長くなりましたが以上でCSVデータから都道府県, 市区町村の配列が作成出来ました。上記のコードを用いてPrefectureオブジェクト, Cityオブジェクトを作成するseeds.rbを書いていきましょう。以下のようになります。 db/seeds.rb require 'csv' # CSV読み込み file_path = 'lib/自治体一覧表.csv' csv_data = CSV.read(file_path) # 都道府県データ抽出 prefectures_list = csv_data.map { |row| row[1] }.uniq # 市区町村データ抽出 cities_list = csv_data.map do |row| next if row[2] == nil row[1, 2] end.compact # 都道府県データ作成 prefectures_list.each do |prefecture| Prefecture.create!(name: prefecture) end # 市区町村データ作成 cities_list.each do |prefecture, city| prefecture = Prefecture.find_by(name: prefecture) prefecture.cities.create(name: city) end さて、初期データを作成してみましょう! $ rails db:seed Railsコンソールでデータが作成出来ているか確認してみます。 $ rails c > Prefecture.count => 47 > City.count => 1747 > Prefecture.all.each { |pref| puts pref.name } 北海道 青森県 岩手県 ... 宮崎県 鹿児島県 沖縄県 > Prefecture.find_by(name: '東京都').cities.each { |city| puts city.name } 千代田区 中央区 港区 ... 八丈町 青ヶ島村 小笠原村 都道府県, 市区町村の数を確認しましたが合っています。 ※ 市町村の数は総務省によると1,724あるそうです。これに東京都の特別区23を足すことで上記の1,747になります。 関連付けもしっかり出来ています。 20行程度のコードで都道府県, 市区町村のデータをまとめられるRuby素敵です。 以上で必要なオブジェクトは揃いました。これから表題の内容に入っていきます。 3. Vueの導入 RailsアプリケーションにVue.jsを導入していきましょう。 本章ではVueコンポーネントをerbから読み込んでHello Worldを表示していきたいと思います。 ルートページ用の適当なコントローラを作っておきます。 $ rails g controller home index ルーティングを設定しておきます。 config/routes.rb Rails.application.routes.draw do root 'home#index' end 以下のコマンドを叩いてRailsアプリケーションにVue.jsを導入します。 app/javascriptディレクトリ下にVueコンポーネントとVueコンポーネントを読み込むjsファイルが作成されました。 $ rails webpacker:install:vue ... create app/javascript/packs/hello_vue.js create app/javascript/app.vue ... Webpacker now supports Vue.js ? 以降はbin/webpackを実行してファイルの変更がある度に自動でコンパイルしておくようにします。 $ bin/webpack-dev-server Home#indexビューに作成されたVueコンポーネントを読み込むためのコードを追記します。 app/views/home/index.html.erb <%= javascript_pack_tag 'hello_vue' %> それではrails sコマンドを実行しルートパスにアクセスしてみましょう。以下のように"Hello Vue!"という文字が表示されていればVue.jsが動作しています。 4. セレクトボックスに都道府県を表示する ビューに以下を追記してフォームを表示します。 app/views/home/index.html.erb <%= form_with id: 'example_form' do |f| %> <%= f.select :prefecture, [] %> <%= f.select :city, [] %> <%= f.submit '検索' %> <% end %> <%= javascript_pack_tag 'hello_vue' %> 今回はVueコンポーネントを使用せずにerb上のタグにVueを適応させていこうと思います。app/javascript/app.vueは削除しapp/javascript/packs/hello_vue.jsを以下のように編集します。 app/javascript/packs/hello_vue.js import Vue from 'vue/dist/vue.esm'; new Vue({ el: '#example_form', data: { message: 'Hello Vue' } }); 上記ではdataにmessageという変数を宣言しています。erb内でこの変数が読み込めるかテストしてみましょう。 app/views/home/index.html.erb <%= form_with id: 'example_form' do |f| %> <%= f.select :prefecture, [] %> <%= f.select :city, [] %> <%= f.submit '検索' %> {{message}} <% end %> <%= javascript_pack_tag 'hello_vue' %> 読み込めていますね!確認が出来たらmessage変数は削除しておいてください。 それではセレクトボックスに都道府県を表示していきましょう。 都道府県のデータはデータベース上に登録されているためRails上で読み込みVue側に渡す必要があります。 RailsからVueにデータを渡す方法はいくつかありますが今回はgonというgemを使用します。 Gemfileに以下を追記しbundle installして下さい。 gonについては以下の記事が参考になります。 gonを使ったRailsとJavascriptの連携について Gemfile gem 'gon' gonを使用するためにapplication.html.erbに以下を追記します。 app/views/layouts/application.html.erb ... <%= include_gon %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> ... Prefectureモデルの中でセレクトボックスで使用する情報はidとnameになります。(idは都道府県名を表示するだけなら必須ではありませんがセレクトボックスの使用用途を考えると後々必要になると思います) というわけでindexアクション内でidとnameの情報をJSONデータに変換しVue側に渡します。 app/controllers/home_controller.rb class HomeController < ApplicationController def index gon.prefectures = Prefecture.all.to_json only: %i[id name] end end Rails側でJSONに変換して格納した変数をJavaScript側でJSON.parseメソッドを用いてJSONからオブジェクトへ変換します。 app/javascript/packs/hello_vue.js import Vue from 'vue/dist/vue.esm'; new Vue({ el: '#example_form', data: { prefectures: JSON.parse(gon.prefectures) } }); 上記のイメージがわかない場合はブラウザの開発者ツールのコンソールでコードを打ってみるといいかもです。 以上でVue側に都道府県のデータを渡せました。 あとはerb側でVueのコードを記述するだけです。v-forを使用し配列prefecturesの繰り返し処理を行います。 app/views/home/index.html.erb <%= form_with id: 'example_form' do |f| %> <%= f.select :prefecture do %> <option v-for="prefecture in prefectures" :key="prefecture.name" :value="prefecture.id"> {{prefecture.name}} </option> <% end %> <%= f.select :city, [] %> <%= f.submit '検索' %> <% end %> <%= javascript_pack_tag 'hello_vue' %> 以上でセレクトボックスに都道府県を表示することが出来ました。 ↑ 省略してますが沖縄県までちゃんと表示されています! ちなみに5章の実装を行わないのであればこんな面倒なことをしなくても以下のコードで同様の実装が出来ます。 <%= f.select :pref, options_for_select(Prefecture.all.map{ |pref| [pref.name, pref.id] }) %> 5. セレクトボックスに都道府県に応じた市区町村を表示する さて、いよいよ本題の実装に入ります。 セレクトボックスで都道府県が選択されたらVueがAjax通信を行いRails側から市区町村データを受け取る機能を実装していきます。 まずRails側で市区町村データを返す機能を実装します。 $ rails g controller cities app/controllers/cities_controller.rb class CitiesController < ApplicationController def set_cities cities = Prefecture.find(params[:id]).cities render json: cities.all.to_json(only: %i[id name]) end end config/routes.rb Rails.application.routes.draw do root 'home#index' post 'set_cities', to: 'cities#set_cities' end これで/set_citiesに都道府県のidを渡せば対応した市区町村のJSONデータが帰ってくるようになりました。 Vue側の実装をしていきます。 まずセレクトボックスで選択された都道府県のidを取得していきたいと思います。 Vueに選択された都道府県のidを格納する変数selectedPrefを定義します。また、都道府県が選択された際実行するメソッドgetCities()も定義します。 app/javascript/packs/hello_vue.js import Vue from 'vue/dist/vue.esm'; new Vue({ el: '#example_form', data: { selectedPref: '', prefectures: JSON.parse(gon.prefectures) }, methods: { getCities: function(prefecture) { console.log(prefecture); // とりあえず取得したデータをコンソール上で表示 } } }); erbを編集しselectタグにv-modelと@changeを定義します。 セレクトボックスで選択された内容がv-modelに指定された変数に格納されるようになります。 また、セレクトボックスで選択された内容が変更された場合@changeで指定されたメソッドが実行されるようになります。 app/views/home/index.html.erb <%= form_with id: 'example_form' do |f| %> <%= f.select :prefecture, nil, {}, {'v-model': 'selectedPref', '@change': 'getCities(selectedPref)'} do %> <option v-for="prefecture in prefectures" :key="prefecture.name" :value="prefecture.id">{{prefecture.name}}</option> <% end %> <%= f.select :city, [] %> <%= f.submit '検索' %> <% end %> <%= javascript_pack_tag 'hello_vue' %> それではブラウザ上で動作確認してみましょう。セレクトボックスで適当な都道府県を選択すると開発者ツールのコンソール上に対応するidが表示されると思います。 getCities()メソッドに都道府県のidが渡されることが確認出来ました。 次にAjax通信の実装をしていきます。 VueでAjax通信をするにはaxiosというライブラリを読み込む必要があります。 またAjax通信する際にCSRFトークンを作成しておかないと422エラーを吐かれます。 詳しくはこちらの記事を参考にしてみてください。 app/javascript/packs/hello_vue.js import Vue from 'vue/dist/vue.esm'; import axios from 'axios'; // CSRFトークン作成 axios.defaults.headers.common = { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content') }; new Vue({ el: '#example_form', data: { selectedPref: '', cities: [], // 取得した市区町村データを格納する変数 prefectures: JSON.parse(gon.prefectures) }, methods: { getCities: function(prefecture) { // Ajax通信 axios // /set_citiesへPOSTリクエストを送信 .post('/set_cities', { id: prefecture }) // Rails側から帰ってきたデータをcitiesへ格納 .then((response) => { this.cities = response.data }) } } }); erbを編集して市区町村名を表示するよう実装します。 app/views/home/index.html.erb <%= form_with id: 'example_form' do |f| %> <%= f.select :prefecture, nil, {}, {'v-model': 'selectedPref', '@change': 'getCities(selectedPref)'} do %> <option v-for="prefecture in prefectures" :key="prefecture.name" :value="prefecture.id">{{prefecture.name}}</option> <% end %> <%= f.select :city do %> <option v-for="city in cities" :key="city.name" :value="city.id">{{city.name}}</option> <% end %> <%= f.submit '検索' %> <% end %> <%= javascript_pack_tag 'hello_vue' %> ブラウザ上で確認してみましょう。 無事、セレクトボックスに都道府県に応じた市区町村を表示できました! ですが1つだけ問題が発生しています。 北海道を選択した際コンソールを見るとエラーが発生しています。 北海道には「泊村」が2つあるためダブってるよとエラーが出ているっぽいです。 このエラーの対応は人によって異なると思いますが手っ取り早くオブジェクトの名称を「泊村(国後郡)」のように変更しちゃえばいいのかなと思います。 参考 https://www.soumu.go.jp/denshijiti/code.html https://www.soumu.go.jp/kouiki/kouiki.html https://qiita.com/s_nakamura/items/5d153f7d9db1b1190296 https://qiita.com/ngron/items/2faae8068baa093d6aba
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

BEM記法とは?Bootstrapとの併用は難しい・・・[初心者]

初めに ポートフォリオ制作でBEM記法を取り入れていきたいと思いましたが... Bootstrapを導入しているため、出来そうにないということに気づきました。 (BEM記法に触れていないレベルで、Bootstrapとの併用は高度すぎるように感じました) 色々調べて自分なりに理解したことをまとめていきます。 BEM記法って何? CSSの命名規則。BEM記法にのっとり、記述すればココはあそこの記述ね!というのが自分以外の人が見ても、わかりやすい。 ただし、コードが長くなりがち。 B:Block (ブロック)でっかい括り E:Element(エレメント) でっかい括りの中の要素 M:Modifier(モディファイアー・修飾語という意味) 上記2つの変化球 とのこと。 この順番でクラス名を決めていくらしい。(block_element--modifireのように) 実際にどう記述するのか <button type="button" class="form__btn">送信</button> <button type="button" class="form__btn form__btn--disabled">送信</button> <nav class="nav"> <ul class="nav__list"> <li class="nav__item"><a href="">menu</a></li> </ul> </nav> ここで気付く... Bootstrapでは、"btn btn-primary"や、"nav navbar"とか書いて、ボタンやら、ナビゲーションバーを表示していました。もしここにBEM記法のクラス名を導入したら... かなり長くゴチャゴチャになってしまうのでは....????? BEM記法とBootstrapは併用できるのか? 相性が悪いというのはやはりあるらしい。 考えたこと Bootstrap使うところは、Bootstrapの命名規則に従って、Bootstap使わないところはBEM記法で書くのはどうだろうか?? 一つの Web システム内に2つの命名規則が混在してしまうことになる...ややこしい・・・ こうすれば綺麗に併用できるらしい 正直、今のレベルで...ポートフォリオ制作期限もある中で...自身のポートフォリオでBEM記法とBootstapをうまく併用するのは無理だと感じました。 BEM記法について 参考にした記事 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【個人開発】Railsエンジニアの技術選定

はじめに 普段はRubyをメインにサーバーサイド開発をしています。 この度、個人開発で上場企業を比較できるサイトを個人で開発しました。 開発したサイト: 上場企業ランキング 開発に関する技術選定は今後の開発効率を左右する重要課題であるものの、個人開発の場合はを1人で行うためかなり悩みました。 今後個人開発を始める方にとって少しでも参考になることがあれば良いなと思い、本記事では私が技術選定について考えたことや採用した後の感想を記します。 基本的なスタンス まず、今回の個人開発の目的ですが、サービスの成功を重視しています。そのため、新しい技術の習得はそれほど重要視はしておりません。 その上での基本的なスタンスです。 業務を通して使い慣れた技術を使う 新しい技術は開発効率に寄与する場合のみ採用する 管理コストの低いマネージドなサービスを利用する 以下、バックエンドとフロントエンドの両面から解説します。 バックエンド WEBフレームワーク: Rails(APIモード) 業務で1年以上利用しているため採用 ORM(Active Record)やテスティングライブラリ(RSpec)の使いやすさが素晴らしい Go言語とEcho(かGin)を採用し、OpenAPI定義を生かして、OpenAPI Generatorでサーバー用のコードを自動生成する方法も検討しましましたが、それでも使い慣れたRailsよりは開発効率が落ちてしまうことを懸念し不採用としました。 インフラ: Heroku 定額の利用料のため(現在は、月月$7のHobbyプランを利用中)、利用料金の見通しを立てやすい ymlでコード化し開発環境に利用しているDockerfileをでイメージをビルドできるので、構築コストが低い クラウドインフラ学習のためAWSやGCPも検討しましたが、利用料金過多になることを危惧し不採用となりました。 DB: PostgreSQL Heroku との相性が良い インフラにHerokuを利用することが決まっていたので、相性の良さからDBはPostgreSQL一択でした。 CI/CD: GitHub Actions GitHubの秘匿情報管理の手間がなく安心 使い慣れたCircle CIを利用する場合も検討しましたが、今回の開発ではメリットがなさそうだったので不採用となりました。 フロントエンド JSフレームワーク: Nuxt.js 業務でVue.jsを半年以上書いているため学習コストが低いため採用 ディレクトリ構成の規約や、ルーティングの自動生成によって開発効率がかなり高い 設定周りの記述をnuxt.config.jsだけで完結できて便利 Nuxt.jsほんと素晴らしいですね。今回の開発で初めて利用しましたが、すんなり導入できました。 CSSフレームワーク: Bootstrap モバイルフレンドリーかつフラットデザイン ほぼstyleタグを書かなくて済むため、JavaScript、Vue.jsのコーディングに集中できる ドキュメントやカスタマイズの情報が多い 色をデフォルトから変更するだけで、Bootstrapぽさを軽減できる Tree Shakingを使わないとバンドルサイズが肥大化しすぎるので注意 他にもVuetifyやMaterial、TailwindCSSも検討したものの、マテリアルデザインな点やモバイルに対応していない点、情報量の少なさから不採用としました。 ホスティング: Netlify GitHub と連携しデプロイを自動化できる ドキュメントやブログ等に情報が多い Netlifyにホスティングを終えた後に、Vercel が無料枠で利用できスループットがよいということを知ったので、Netlifyに課題感が出てきたらVercelへの移行を検討します。 参考 Zenn個人開発の限界に挑んだ話 - devsumi 2021 | YouTube 【個人開発】マンガを楽しむWebアプリを支える技術の共有:インフラアーキテクチャおよび技術選定 まとめ 今回の個人開発では、使い慣れた技術(Rails や Heroku)を使いつつも、初めての技術(Nuxt.js や GitHub Actions)を利用することで、開発効率と技術学習を良いバランスで実現できています。 引き続き、開発したサイトをグロースしていきたいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ストロングパラメーターってなに???

対象者 ストロングパラメーターに関して知りたい方 ストロングパラメーターの入力方法を知りたい方 目的 ストロングパラメーターのメソッド1つ1つの意味を考えながら使うこと 実際の手順と実例 1.ストロングパラメーターって?? 結論から言うと、ストロングパラメーターとは、データ送信時に不正なリクエストによって予期しない値に変更されてしまう脆弱性(マスアサインメント脆弱性)を防ぐ仕組みです。 私個人的に不正アクセスを防ぐ仕組みくらいに考えています。 2.書き方 1.基本構文 private def user_params params.require(:キー(モデル名)).permit(:カラム名1,:カラム名2,・・・).marge(カラム名: 入力データ) end 以下は例になります user_controller.rb def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) if @user.update(user_params) redirect_to user_path(@user), notice: "You have updated user successfully." else render "edit" end end private def user_params params.require(:user).permit(:name, :introduction, :profile_image) end 2.private privateは一種の境界線のようなもので、 「ここから下はControllerの中でしか呼び出せません」という意味を持ちます。 3.requireメソッド 引数にしたいキーを指定する場所 例では,(:user)に当たります。 キーの値に対するデータを抽出したい場合上記例のように書きます。 4.permitメソッド 許可された値のみを取得することができます。 permitに記載のないカラムは、保存や更新が実行されません。 5.ストロングパラメーターの呼び出し user_controller.rb def update @user = User.find(params[:id]) if @user.update(user_params) redirect_to user_path(@user), notice: "You have updated user successfully." else render "edit" end end 上記例のUpdateアクション抜粋です。 if文の(user_params)の部分でストロングパラメーターを呼び出しています。この他にもcreate,new等でこのように記述する場合が多いです。 参照 Rails4 | 新規・変更機能 | マスアサインメント機能と脆弱性とStrong Parameters 投稿者コメント 先日ストロングパラメーターに記載がないことが理由で作業が前に進まなかったので、このように記事にして改めて認識をまとめてみることにしました。 構文こぴぺして使っていただけると嬉しいです。 My Profile プログラミング学習歴3ヶ月目のアカウントです! プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。 また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。 もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails scaffoldコマンドで REST APIの作成

scaffoldとは scaffoldとは雛形を作成するコマンド。scaffoldは『はしご』という意味。 Railsではしごをかける(楽させる)つまり雛形を作成できる。 scaffolfコマンド $ rails g scaffold<model名> カラム名:型 指定したmodelと対応するためRESTfulなAPIを作成するためのコマンのド #REST APIの雛形を作成 *ここではarticle modelとする $ bundle exec rails g scaffold articles title:string body:text *REST APIの説明はこちら https://qiita.com/Hashimoto-Noriaki/items/d69c9dd0643f241776a9 generatoの設定 $ bundle exec rails d scaffold article title:string body:text で作成したファイルを削除。その後generatorの設定。 config/applixation.rb module HelloWorldRails class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 6.0 # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. config.generators do |g| g.javascripts false g.stylesheets false g.helper false g.test_framework false + g.template_engine false #追加 end + config.api_only = true end end *template_engineはgeneratorによってhtml.erbファイルを作るかどうかの設定。 WebAPIではJSONを返すのが目的なのでjson.jbuilderだけを作るようにする。 *api_onlyはtrueにすることによってAPI実装で必要な部分だけが作成されるようになるオプション。 scaffolfコマンドの実行とファイル確認 $ bundle exec rails g scaffold articles title:string body:text 作られたファイルは以下の通り 1 migrationファイル 2 model 3 routes.rbに対応するルーティングの追加 4controller 5view(先ほど行った設定によりjbuilderファイルのみ) controllerの確認 今回はarticle_controller.rb。scaffoldを作る理由はcontrollerの実装が綺麗で お手本になるから。 articles_controller.rb class ArticlesController < ApplicationController before_action :set_article, only: [:show, :update, :destroy] # GET /articles # GET /articles.json def index @articles = Article.all end # GET /articles/1 # GET /articles/1.json def show end # POST /articles # POST /articles.json def create @article = Article.new(article_params) if @article.save render :show, status: :created, location: @article else render json: @article.errors, status: :unprocessable_entity end end # PATCH/PUT /articles/1 # PATCH/PUT /articles/1.json def update if @article.update(article_params) render :show, status: :ok, location: @article else render json: @article.errors, status: :unprocessable_entity end end # DELETE /articles/1 # DELETE /articles/1.json def destroy @article.destroy end private # Use callbacks to share common setup or constraints between actions. def set_article @article = Article.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def article_params params.require(:article).permit(:title, :body) end end *具体的にはメソッドの数が変わってます。 JSONを返すようなWebAPIでは new editメソッドは使わない。 現状はREST APIに必要な最低限の実装になっている。 追加されたメソッド の確認 1 index 2 show 3 create 4 update 5 destroy *Readはindex(一覧表示)とshow(詳細ページ)に分かれる。 scaffoldコマンド一発でCRUD処理に対応することがわかる。 modelとmigrationファイル ・model/article.rb ・db/migration/****_create_articles.rb articleモデルが追加されたのとarticlesテーブルを作る新しいmigrationファイルが作成されている。 ⚫︎routes.rb 自動的に必要なルーティングが追加 routes.rb Rails.application.routes.draw do + resources :articles get "users/index" get "homes/index" end 追加されたのは1行だが routes.rb に resources の記述が追加されると CRUD 処理で必要なルーティングが追加される。 articleを絞り込みにした上でルーティングを確認 resources の記述一つだけで、6 つのルーティングが追加 view view には3つのファイルが作成される。 ① index.json.jbuilder ② show.json.jbuilder ③ _article.json.jbuilder *_article.json.jbuilderとは部分テンプレート(partical)と呼ばれるもので、コードを共通化させるもの。 index.json.jbuilder json.array! @articles, partial: 'articles/article', as: :article show.json.jbuilder json.partial! "articles/article", article: @article それぞれpartial (部分テンプレート)を呼び出している。 index.json.jbuilder は、複数の article が渡ってくるので、そのひとつひとつを article として部分テンプレートに渡している。 show.json.jbuilder は、ひとつの article が渡ってくるので、 それを部分テンプレートに渡している。 _article.json.jbuilder json.extract! article, :id, :title, :body, :created_at, :updated_at json.url article_url(article, format: :json) 変数 article に渡されたものを、部分テンプレート通りに json 出力します。こうすることで、同じ処理を何度も書かずに済み、修正するときも1箇所修正するとどちらも修正される。 対応関係を図にするとこんな感じ 処理を共通化する というのは、プログラミングをするうえでよくやることで、大事な作業です。 処理が共通化されずに、同じ内容のコードが複数箇所に散らばってしまうと、修正するときに複数箇所を修正する必要がある。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails ユーザー編集ページと更新

ユーザー編集ページ users/edit.html.erb <%@users.errors.full_messages.each do |messages|%>・・・1 <%=message%>・・・1 <%end%> <%=form_tag("/users/#{@user.id}/update",{multipart:true}do%>・・・2 <input name="name" value="<%=@user.name%>"> <input name="image" type="file">・・3 <input name="email" value="<%=@user.email%>">・・4 <input type="submit" value="保存">・・2 <%end%> ・・1配列@user_errors.full_messagesから要素を一つずつ取り出して、messageに代入。それを<%=message%>で表示 ・・2保存ボタンをクリックするとフォームで入力した内容がURL"/users{@user.id}/update" に送信される。また、画像を送信したいときには multipart:trueを記述する。 ・・3画像ファイルを選択するボタンを表示することができる ・・4初期値 users_controller.rb def edit @user=User.find_by(id: params[:id]) end userコントローラーのeditアクションでは、idがURLで入力した値の投稿者データを@userに代入した ユーザー更新 users_controller.rb def update @user=User.find_by(id: params[:id])/1 @user.name=params[:name] /2 @user.email=params[:email]/3 if params[:image]/4 @user.image_name="#{@user.id}.jpg"/5 image=params[:image]/6 File.binwrite("public/user_images/#{@user.image_name}",image.read)/7 end ・・1idがURLで入力した値である投稿者データを@userに代入 ・・2名前がフォームで入力した値である物を変数@user.nameに代入 ・・3メールアドレスがフォームで入力されたものを変数@user.emailに代入 ・・4画像が送信されているかを判定 ・・5usersテーブルの画像のファイル名をimage_nameカラムに(保存)上書き ・・6送信される画像ファイルを受け取る。 ・・7画像を「public/user_images」内に保存。変数imageに対し、readメソッドを用いることでその画像データ(今回はimage)を取得
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

変形させずに画像の表示サイズを揃える方法

解決したい問題 Railsでレシピを投稿できるアプリケーションを作成中、360×260の大きさでレシピ画像を表示したかったのですが、イメージタグにサイズ指定をしただけだと、縦長の画像をアップロードした際、画像が変形してしまいました。 xxxx.erb <%= attachment_image_tag recipe, :recipe_image, size: '360x260', format:'jpeg' %> ※画像アップロードにはrefileを使用しています この画像をアップロードすると↓           変形してしまう↓         この問題を解決してくれる便利なCSSプロパティがあったのでご紹介します! 解決方法 object-fitプロパティを使う! xxxx.erb <div class="img-container"> <%= attachment_image_tag recipe, :recipe_image, format:'jpeg' %> </div> application.css .img-container { width: 360px; height: 260px; } .img-container img { width: 100%; height: 100%; object-fit: cover; } 画像の幅と高さを指定して、object-fit: cover;を追加するだけで中央でトリミングされました! object-fitプロパティではcover以外に、縦横比を保持してボックスに収まるようにリサイズしてくれるcontainや、リサイズせずにそのまま画像を表示するnoneなどの値も使えます。 希望の表示形式に合わせて使い分けしてみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

画像の表示サイズを変形させずに揃える方法

解決したい問題 Railsでレシピを投稿できるアプリケーションを作成中、360×260の大きさでレシピ画像を表示したかったのですが、イメージタグにサイズ指定をしただけだと、縦長の画像をアップロードした際、画像が変形してしまいました。 xxxx.erb <%= attachment_image_tag @recipe, :recipe_image, size: '360x260', format:'jpeg' %> ※画像アップロードにはrefileを使用しています この画像をアップロードすると↓           変形してしまう↓         この問題を解決してくれる便利なCSSプロパティがあったのでご紹介します! 解決方法 object-fitプロパティを使う! xxxx.erb <div class="img-container"> <%= attachment_image_tag @recipe, :recipe_image, format:'jpeg' %> </div> application.css .img-container { width: 360px; height: 260px; } .img-container img { width: 100%; height: 100%; object-fit: cover; } 画像の幅と高さを指定して、object-fit: cover;を追加するだけで中央でトリミングされました! object-fitプロパティではcover以外に、縦横比を保持してボックスに収まるようにリサイズしてくれるcontainや、リサイズせずにそのまま画像を表示するnoneなどの値も使えます。 希望の表示形式に合わせて使い分けしてみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む