- 投稿日:2020-07-10T22:30:57+09:00
Rails ✕ PostgreSQLで既定のIDをUUIDに設定する方法
動作環境
- Ruby 2.7.0
- Rails 6.0.3.2
- PostgreSQL 12.3
準備
1. PostgreSQLデータベースを使用してRailsアプリケーションを作成します。
$ rails new blog -d=postgresql2.
config/database.yml
でデータベース名を変更できます。default: &default adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> development: <<: *default database: blog_development test: <<: *default database: blog_test3. 下記のrailsコマンドで
config/database.yml
の内容でデータベースを作成してくれます。$ rails db:create Created database 'blog_development' Created database 'blog_test'PostgreSQLでUUIDを有効にする
通常、以下の手順で、プライマリキーとしてUUIDを使うことが出来ます。
1. マイグレーションファイル作成コマンドを実行します。
$ rails g migration enable_uuid2. マイグレーションファイルの編集
# db/migrate/xxx_enable_uuid.rb class EnableUuid < ActiveRecord::Migration[6.0] def change enable_extension 'pgcrypto' end end既定のIDをUUIDに設定する
config/initializers/generators.rb
ファイルを作成して、中身を下記のようにします。# config/initializers/generators.rb Rails.application.config.generators do |g| g.orm :active_record, primary_key_type: :uuid endこの設定でmodel作成時にidがuuidであるというオプションがmigrationファイルに自動で付与されるようになります。
確認
1. Postモデルを作成します。
$ rails g model Post title:string2. マイグレーションファイルを確認します。
# db/migrate/xxx_create_posts.rb class CreatePosts < ActiveRecord::Migration[6.0] def change create_table :posts, id: :uuid do |t| t.string :title t.timestamps end end end3. マイグレーション
$ rails db:migrate4. レコードの作成
$ rails console > Post.create(title: 'new post') (0.2ms) BEGIN Post Create (25.3ms) INSERT INTO "posts" ("title", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["title", "new post"], ["created_at", "2020-07-10 13:05:38.915722"], ["updated_at", "2020-07-10 13:05:38.915722"]] (7.0ms) COMMIT => #<Post id: "464b7fa5-aaae-4970-a56f-b5c0cf6c1b83", title: "new post", created_at: "2020-07-10 13:05:38", updated_at: "2020-07-10 13:05:38">プライマリキーがUUIDタイプになりました!
- 投稿日:2020-07-10T20:58:55+09:00
商品情報編集機能を実装したい~part2~
前提
- ruby on rails 6.0.0 を使用。
- ユーザー機能はdeviseにより導入されているものとする。
- viewファイルは全てhaml形式とする。
- ちなみに使っているのはMacBook Air(Retina, 13-inch, 2020)です。
はじめに
前置きや手順などは part1 に記述してあるので早速実装の続きをしていこうと思います。気になったら是非読んでネ。
part2 でやることとしては手順の2番目にあたる「imageテーブルを関連づけて画像の投稿を実装」というところです。ではさっそく、
本日もはりきってやっていきましょう。
$ rails g model image
$ rails db:migrateまずはimageモデルを作ってマイグレートするところから。
前回と同じくマイグレーションファイルの記述等は省略しています。次にモデル構造の説明をしていきます。
app/models/product.rbclass Product < ApplicationRecord belongs_to :user has_many :images endapp/models/image.rbclass Image < ApplicationRecord belongs_to :product end上記を見ていただく通り、1つのproductモデルに対して、複数のimageモデルを持つことができる、1対多の関係になっています。(わかりやすいようバリデーションは省略しております)
imageテーブルでは1枚の画像に1つのレコードが対応していて、それぞれにproduct_idを紐づけているといった形です。ざっと構造が把握できたところでローカル環境で画像をアップロードする準備を行っていきます。
Gemfile~省略~ gem 'carrierwave' gem 'mini_magick'まずはgemの導入からです。画像をアップロードするために、今回は carrierwave の uploader を使っていきたいと思います。
$ bundle install
$ rails g uploader image忘れずに bandle install を行ってから、uploaderファイルを生成します。これらをしっかり使うために、生成したuploaderファイルと先ほどのモデルに記述を追加していきましょう。
app/models/image.rbclass Image < ApplicationRecord belongs_to :product mount_uploader :src, ImageUploader endこのように記述することで、imageモデルのsrcカラムにおいてImageUploaderを使用することが可能になります。
app/uploaders/image_uploader.rbinclude CarrierWave::MiniMagick process resize_to_fit: [50, 50]こちらはMiniMagickの設定です。アップロードした画像のサイズを調整できる便利なgemですね。
上記の2行は新しく追加するというより、コメントアウトの中からこの記述を見つけてコメントアウトを外していただく形になります。(resizeの中身は自由に調節していただいて構いません)ここまででアップロード自体はできるようになったので、実際に画像を投稿するフォームを作っていきます。
app/models/product.rbclass Product < ApplicationRecord belongs_to :user has_many :images, dependent: :destroy accepts_nested_attributes_for :images, allow_destroy: true endapp/views/products/_form.html.haml= form_with model: @product, local: true do |f| = f.text_field :name, placeholder: 'name' = f.fields_for :images do |i| = i.file_field :src = f.submit 'SEND'fields_forとやらが出てきました。こちらは1つのテーブルに対して、それに紐づいた複数のテーブルに同時にデータを保存することができるフォームヘルパーです。
使い方としては、まず親となるモデルに、accepts_nested_attributes_for という記述を追加します。因数にはそれに紐づく子モデルをもってきましょう。後ろに続く allow_destroy の部分は、trueにすると親レコードが削除された場合に、関連する子レコードも同時に削除してくれるといった便利な機能です。app/controllers/products_controller.rb#~省略~ def new @product = Product.new @product.images.new end #~省略~ def product_params params.require(:product).permit(:name, images_attributes: [:src]).merge(user_id: current_user.id) end扱うデータに伴って、コントローラーにも少し修正を加えます。
まずnewアクションの部分では、productに関連する新しいimageインスタンスを生成する記述を追加しています。これがないとimageに正しく画像が保存されないので注意です。
そしてストロングパラメータですね。こちらは少し特殊な記述をしています。attributes: [: ] というのは関連づくモデルのカラムを指定するというものです。
フォームヘルパーのfieldsforを使用した際にセットで使用するものと考えていただければ大丈夫だと思います。これで画像の投稿機能は実装できたことになります。
ただこのままだと画像が1枚しか選ぶことができないので次回そこをアップグレードしていきたいと思います。最後に
今回はimageモデルを作成して実際にフォームで画像を送り、データベースに保存するところまで実装しました。
文字だけではわかりにくいと思ったので参考画像やgifなんかも付け足したいなと思いました。今は少し忙しいので余裕ができたらやろうと思います。(多分)
次のpartではとうとうjQueryを導入していきます。表示をあれこれいじって画像を複数投稿できるフォームを作ろう!といった感じですね。頑張ります。
それではまた次のpartで。ありがとうございました。
- 投稿日:2020-07-10T20:58:55+09:00
画像の登録?もちろんできません(できる)~part2~
前提
- ruby on rails 6.0.0 を使用。
- ユーザー機能はdeviseにより導入されているものとする。
- viewファイルは全てhaml形式とする。
- ちなみに使っているのはMacBook Air(Retina, 13-inch, 2020)です。
はじめに
前置きや手順などは part1 に記述してあるので早速実装の続きをしていこうと思います。気になったら是非読んでネ。
part2 でやることとしては手順の2番目にあたる「imageテーブルを関連づけて画像の投稿を実装」というところです。
別テーブルに画像を登録するだけなのに実装するのに3万年くらいかかったので正しい手順を後世に残したいと思います。
ではさっそく、
本日もはりきってやっていきましょう。
$ rails g model image
$ rails db:migrateまずはimageモデルを作ってマイグレートするところから。
前回と同じくマイグレーションファイルの記述等は省略しています。次にモデル構造の説明をしていきます。
app/models/product.rbclass Product < ApplicationRecord belongs_to :user has_many :images endapp/models/image.rbclass Image < ApplicationRecord belongs_to :product end上記を見ていただく通り、1つのproductモデルに対して、複数のimageモデルを持つことができる、1対多の関係になっています。(わかりやすいようバリデーションは省略しております)
imageテーブルでは1枚の画像に1つのレコードが対応していて、それぞれにproduct_idを紐づけているといった形です。ざっと構造が把握できたところでローカル環境で画像をアップロードする準備を行っていきます。
Gemfile~省略~ gem 'carrierwave' gem 'mini_magick'まずはgemの導入からです。画像をアップロードするために、今回は carrierwave の uploader を使っていきたいと思います。
$ bundle install
$ rails g uploader image忘れずに bandle install を行ってから、uploaderファイルを生成します。これらをしっかり使うために、生成したuploaderファイルと先ほどのモデルに記述を追加していきましょう。
app/models/image.rbclass Image < ApplicationRecord belongs_to :product mount_uploader :src, ImageUploader endこのように記述することで、imageモデルのsrcカラムにおいてImageUploaderを使用することが可能になります。
app/uploaders/image_uploader.rbinclude CarrierWave::MiniMagick process resize_to_fit: [50, 50]こちらはMiniMagickの設定です。アップロードした画像のサイズを調整できる便利なgemですね。
上記の2行は新しく追加するというより、コメントアウトの中からこの記述を見つけてコメントアウトを外していただく形になります。(resizeの中身は自由に調節していただいて構いません)ここまででアップロード自体はできるようになったので、実際に画像を投稿するフォームを作っていきます。
app/models/product.rbclass Product < ApplicationRecord belongs_to :user has_many :images, dependent: :destroy accepts_nested_attributes_for :images, allow_destroy: true endapp/views/products/_form.html.haml= form_with model: @product, local: true do |f| = f.text_field :name, placeholder: 'name' = f.fields_for :images do |i| = i.file_field :src = f.submit 'SEND'fields_forとやらが出てきました。こちらは1つのテーブルに対して、それに紐づいた複数のテーブルに同時にデータを保存することができるフォームヘルパーです。
使い方としては、まず親となるモデルに、accepts_nested_attributes_for という記述を追加します。因数にはそれに紐づく子モデルをもってきましょう。後ろに続く allow_destroy の部分は、trueにすると親レコードが削除された場合に、関連する子レコードも同時に削除してくれるといった便利な機能です。app/controllers/products_controller.rb#~省略~ def new @product = Product.new @product.images.new end #~省略~ def product_params params.require(:product).permit(:name, images_attributes: [:src]).merge(user_id: current_user.id) end扱うデータに伴って、コントローラーにも少し修正を加えます。
まずnewアクションの部分では、productに関連する新しいimageインスタンスを生成する記述を追加しています。これがないとimageに正しく画像が保存されないので注意です。
そしてストロングパラメータですね。こちらは少し特殊な記述をしています。attributes: [: ] というのは関連づくモデルのカラムを指定するというものです。
フォームヘルパーのfieldsforを使用した際にセットで使用するものと考えていただければ大丈夫だと思います。これで画像の投稿機能は実装できたことになります。
ただこのままだと画像が1枚しか選ぶことができないので次回そこをアップグレードしていきたいと思います。最後に
今回はimageモデルを作成して実際にフォームで画像を送り、データベースに保存するところまで実装しました。
文字だけではわかりにくいと思ったので参考画像やgifなんかも付け足したいなと思いました。今は少し忙しいので余裕ができたらやろうと思います。(多分)
次のpartではとうとうjQueryを導入していきます。表示をあれこれいじって画像を複数投稿できるフォームを作ろう!といった感じですね。頑張ります。
それではまた次のpartで。ありがとうございました。
- 投稿日:2020-07-10T20:41:59+09:00
【Rails】多対多のアソシエーションを用いてコミュニティ加入の申請/承認機能の実装を行う
実施したいこと
申請・承認の仕組みを実装する
具体的には?
「ユーザ(小西)が、とあるコミュニティに加入したいと思いますが、
加入にはコミュニティの管理者(大西)の承認が必要になる」といったケースでの実装例です。ざっくりイメージ
処理フロー概要
- 該当コミュニティ画面にて、ユーザ(小西)が「申請」ボタンを押す。
- 該当コミュニティの申請待ちリストにユーザ(小西)が追加される。管理者が、該当コミュニティの申請待ち一覧画面を見て、申請者を承認するかどうか判断。
- 申請を承認する場合は、承認ボタンを押す。申請ユーザがコミュニティに加入し、申請待ちリストからは消去される。
- 申請を却下する場合は、否認ボタンを押す。申請待ちリストから消去される。
環境
Ruby 2.6.5
Rails 5.2.4.2
mysql 5.7現在のアプリケーション機能の構成
ユーザが色々なコミュニティに所属できるアプリケーションを作成しています。
- userモデル:アプリの利用ユーザ情報を保持
- communityモデル:コミュニティ情報を保持
- belongingモデル:ユーザが所属するコミュニティ情報を保持。ユーザは複数のコミュニティに所属できます。
※userとcommunityはbelongingモデルを介して多対多の関係となっています。以下ソースは関連部分のみ抜粋
user.rbclass User < ApplicationRecord has_many :belongings, dependent: :destroy has_many :applies, dependent: :destroy has_many :communities, through: :belongings # ユーザが所属しているコミュニティ endcommunity.rbclass Community < ApplicationRecord has_many :belongings, dependent: :destroy has_many :applies, dependent: :destroy has_many :users, through: :belongings # コミュニティに所属しているユーザ # ユーザがコミュニティに所属していればtrueを返す def user_belonging?(user) users.include?(user) end endbelonging.rbclass Belonging < ApplicationRecord belongs_to :user belongs_to :community validates :user_id, presence: true validates :community_id, presence: true validates :user_id, uniqueness: { scope: :community_id } validates :community_id, uniqueness: { scope: :user_id } endApplyモデルを追加し、申請状況を保持させる。
Applyモデルのルーティングやコントローラ、ビューファイルを追加します。
ルーティング(抜粋)
routes.rbRails.application.routes.draw do root 'home#index' resources :communities do resources :applies, only: %i[index create destroy] resources :belongings, only: %i[index create destroy] end resources :users, only: [:index, :show] end1.該当コミュニティ画面にて、ユーザ(小西)が「申請」ボタンを押す。
- 申請ボタン(コミュニティ詳細画面に配置) (views/communities/show.html.erb)
show.html.erb<!-- ログインユーザが当該コミュニティに所属している場合 --> <% if @community.user_belonging?(current_user) %> <%= link_to '退会する', community_belonging_path(@community, @belonging), method: :delete, data:{ confirm: "コミュニティ「#{@community.name}」を退会します。よろしいですか?" } ,class:"mini-red-link-btn font-bold text-line-none" %> <!-- 当該コミュニティには所属していないが、ログインはしている場合 --> <% elsif current_user %> <% if @apply %> <%= link_to '申請取消', community_apply_path(@community, @apply), method: :delete, class: "mini-red-link-btn font-bold text-line-none" %> <% else %> <%= link_to '加入申請', community_applies_path(@community), method: :post, class: "mini-green-link-btn font-bold text-line-none" %> <% end %>申請ボタンは、以下の条件で表示させます。
1. コミュニティにすでに加入している場合:退会するボタンが表示
2. コミュニティにまだ加入していない場合:申請ボタンが表示
3. すでに加入申請済の場合:申請取消ボタンを表示
- 申請ボタン押下後(createアクションが発生)
applies_controller.rbclass AppliesController < ApplicationController def create current_user.applies.create(community_id: apply_params[:community_id]) redirect_to community_url(apply_params[:community_id]), notice: "加入申請しました" end private def apply_params params.permit(:community_id) end endAjaxは使わず、同画面へのリダイレクトが発生するようにします。
(Ajaxを使ってもよさそう)これで、applyモデルに申請情報が追加されました。
2.該当コミュニティの申請待ちリストにユーザ(小西)が追加される。管理者が、該当コミュニティの申請待ち一覧画面を見て、申請者を承認するかどうか判断。
次に、申請待ちリストの確認です。
管理者(大西)が該当コミュニティ画面から「申請待ち一覧画面」を開きます。
- 申請待ち画面へのリンク(コミュニティ詳細画面) (views/communities/show.html.erb)
show.html.erb<% if user_admin_flg(current_user,@community) == 1 %> <%= link_to "承認待ち一覧", community_applies_path(@community), class:"btn btn-primary" %> <% end %>リンクをクリックすると、申請待ち一覧画面が開きます。
- 申請待ち一覧画面 (views/applies/index.html.erb)
index.html.erb<div class="container applicant-wrapper"> <h3>承認待ちユーザ一覧</h3> <div class="row"> <% @applies.each do |app| %> <div class="col-6"> <% if app.user.image.attached? %> <%= link_to app.user.image, user_path(app.user), class:"user-icon" %> <% else %> <%= link_to user_path(app.user) do %> <%= image_tag ("no_image.png"), class:"user-icon" %> <% end %> <% end %>  <%= app.user.username %><br> <%= link_to "承認", community_belongings_path(app.community, user_id: app.user.id, apply_id: app.id), method: :post, class:"mini-green-link-btn font-bold text-line-none" %> <%= link_to "却下", community_apply_path(app.community, app), method: :delete, class:"mini-red-link-btn font-bold text-line-none" %> <br> </div> <% end %> </div> </div>applyモデルから、該当コミュニティへの申請情報を一覧表示させています。
同画面において、承認ボタン、却下ボタンも配置しています。3.申請を承認する場合は、承認ボタンを押す。申請ユーザがコミュニティに加入し、申請待ちリストからは消去される。
承認ボタンを押すと、以下の処理が実行されます。
1. belongingsコントローラのcreateアクションが実行される。
2. 申請待ち一覧から削除するため、Applyモデルの該当の申請情報が削除される。
3. 申請待ち一覧画面へリダイレクト
- belongingsコントローラ
belongings_controller.rbclass BelongingsController < ApplicationController def create @belonging = Belonging.create(community_id: belonging_params[:community_id], user_id: belonging_params[:user_id]) Apply.find(belonging_params[:apply_id]).destroy! redirect_to community_applies_url(@belonging.community), notice:"「#{@belonging.user.username}」が、コミュニティ:#{@belonging.community.name}へ加入しました。" end private def belonging_params params.permit(:community_id, :user_id, :apply_id) end end4.申請を却下する場合は、否認ボタンを押す。申請待ちリストから消去される。
却下ボタンを押すと、以下の処理が実行されます。
1. 申請待ち一覧から削除するため、appliesコントローラのdestroyアクションが実行され、Applyモデルの該当の申請情報が削除される。
2. 申請待ち一覧画面へリダイレクト
- appliesコントローラ
applies_controller.rbclass AppliesController < ApplicationController def destroy @apply = Apply.find(params[:id]) @apply.destroy! @comminity = Community.find(params[:community_id]) redirect_to community_url(@comminity), notice: "加入申請を取り消しました" end end以上になります。
文中でappliesコントローラとbelongingsコントローラはアクション毎に分けて紹介していますが、最後に全部まとめて載せておきます。
applies_controller.rbclass AppliesController < ApplicationController def create current_user.applies.create(community_id: apply_params[:community_id]) redirect_to community_url(apply_params[:community_id]), notice: "加入申請しました" end def destroy @apply = Apply.find(params[:id]) @apply.destroy! @comminity = Community.find(params[:community_id]) redirect_to community_url(@comminity), notice: "加入申請を取り消しました" end def index @applies = Apply.where(community_id: params[:community_id]) end private def apply_params params.permit(:community_id) end endbelongings_controller.rbclass BelongingsController < ApplicationController def create @belonging = Belonging.create(community_id: belonging_params[:community_id], user_id: belonging_params[:user_id]) Apply.find(belonging_params[:apply_id]).destroy! redirect_to community_applies_url(@belonging.community), notice:"「#{@belonging.user.username}」が、コミュニティ:#{@belonging.community.name}へ加入しました。" end def destroy @belonging = Belonging.find(params[:id]) @belonging.destroy! @comminity = Community.find(params[:community_id]) redirect_to community_url(@comminity), notice: "コミュニティ「#{@comminity.name}」を退会しました。" end private def belonging_params params.permit(:community_id, :user_id, :apply_id) end end初心者が自分の頭でロジック・コードを考えて実装したので、
間違いや、もっと適した実装方法があるかもしれません。
ぜひご指摘いただけますと幸いです。この実装で、多対多の関係のことがより理解できたなと思います。
- 投稿日:2020-07-10T19:13:55+09:00
[Rails]パラメータに配列として情報を保存したい時
パラメーターに情報が入らない
controller.rb#省略 def new @goal = Goal.new end def create Goal.create(goal_params) redirect_to root_path end private def goal_params params.require(:goal).permit(:name, :time, :days) end endこの状態でcreateアクションを実行すると値が入らないので
binding.pryで確認。ターミナル内でgoal_paramsを実行▼
[2] pry(#<GoalsController>)> goal_params Unpermitted parameter: days => <ActionController::Parameters {"name"=>"ラジオ体操", "time"=>"19:51"} permitted: true>パラメータにdaysカラムの値が入っていない...
どうやら配列で情報を保存しいたい場合は、:daysではなく、days: []でなければならないということ。コードを編集
controller.rb#省略 def new @goal = Goal.new end def create Goal.create(goal_params) redirect_to root_path end private def goal_params params.require(:goal).permit(:name, :time, days: []) #ここを編集 end endbinding.pryでパラメータ内を確認▼
[2] pry(#<GoalsController>)> goal_params => <ActionController::Parameters {"name"=>"筋トレ", "time"=>"20:01", "days"=>["", "水曜日", "木曜日", "金曜日", "土曜日"]} permitted: true>これでパラメータに情報は入りました。
参考にしてください!
- 投稿日:2020-07-10T18:35:54+09:00
[CentOS][Gem]Error: Your version of SQLite (3.7.17) is too old. Active Record supports SQLite >= 3.8. 解決法
起こったこと
Rails 6 project で
gem 'sqlite3'
を使用してbundle install
すると
SQLite が古い とエラー'./rails-proj/'$ bundle install ... Your version of SQLite (3.7.17) is too old. Active Record supports SQLite >= 3.8. ... FailedOSの sqlite3 が古いのかと思い、
こちらを参考に 自分で最新sqlite3 (3.8.11) をインストール し
https://qiita.com/8zca/items/175efb0612070530d186option 指定で
gem install
も
エラーは変わらない。# 自分でインストール $ /opt/sqlite/sqlite3/bin/sqlite3 --version 3.32.3 $ bundle config build.sqlite3 --with-sqlite3-include=/opt/sqlite/sqlite3/include \ --with-sqlite3-lib=/opt/sqlite/sqlite3/lib $ bundle exec gem install sqlite3 ... Failed原因
どうやら sqlite3 をコンパイルする際にOSの
sqlite.x86_64
nativeライブラリが必要のようで
そのversion が古いよう$ yum list | grep sqlite ... sqlite.x86_64 3.7.17-1.fc21 @/sqlite-3.7.17-1.fc21.x86_64 ...Yum の標準repo で登録されてるsqlite version は古いので
yum install sqlite-*
で入らない。$ yum --showduplicates list sqlite .. Available Packages sqlite.i686 3.7.17-8.el7_7.1 base sqlite.x86_64 3.7.17-8.el7_7.1 base解決策
自分でrpmからインストールする
(最新version は glibc が必要で CentOS7は未対応そうなので
とりあえず sqlite v3.8.11)$ wget https://kojipkgs.fedoraproject.org//packages/sqlite/3.8.11/1.fc21/x86_64/sqlite-devel-3.8.11-1.fc21.x86_64.rpm $ wget https://kojipkgs.fedoraproject.org//packages/sqlite/3.8.11/1.fc21/x86_64/sqlite-3.8.11-1.fc21.x86_64.rpm $ sudo yum install sqlite-3.8.11-1.fc21.x86_64.rpm sqlite-devel-3.8.11-1.fc21.x86_64.rpm $ yum list | grep sqlite Installed Packages sqlite.x86_64 3.8.11-1.fc21 @/sqlite-3.8.11-1.fc21.x86_64そして
bundle install
も通った'./rails-proj/'$ bundle install ... Installed!参考
https://qiita.com/8zca/items/175efb0612070530d186
https://www.reddit.com/r/linuxadmin/comments/c9hy5w/trying_to_upgrade_sqlite_3717_to_version_38_on/
- 投稿日:2020-07-10T18:16:58+09:00
商品情報編集機能を実装したい~part1~
前提
- ruby on rails 6.0.0 を使用。
- ユーザー機能はdeviseにより導入されているものとする。
- viewファイルは全てhaml形式とする。
- ちなみに使っているのはMacBook Air(Retina, 13-inch, 2020)です。
はじめに
プログラミング学習のため、某フリマサイトのコピーサイトを作っています。
商品情報編集機能を実装したが、画像の複数投稿になかなか苦戦したので参考になればと思い書くことにしました。
大した量じゃないのにpart分けしているのはあとで見たときに達成感を得るためです。許してください。(いっぱい書いたぞ!ってなりたい)
part1で特に詰まる部分はないと思いますが、part2以降の土台になってくるのでウォーミングアップ程度に書いていきます。仕様書
- 商品に登録された情報をひとつひとつ変更できる。
- 商品情報を編集できるのは商品を登録したユーザーのみ。
- 画像の差し替えは一枚ごとにできる。
- 商品名や画像など、すでに登録されている情報は編集画面にあらかじめ表示される。
- エラーハンドリングを行う。
(マークアップまで完成したら参考画像を載せようと思ってます)
手順
1, 土台となるコントローラやモデルの作成。
2, imageテーブルを関連づけて画像の投稿を実装。
3, jQueryを導入して複数画像の投稿を実装。
4, メインとなる編集機能を実装。
5, 画像のプレビューをする。これら5つの手順をそれぞれpart分けして実装していくことにする。
それでは、
いざ実装へ
まずは基礎的な部分を固めていく。
最初にターミナルから。$ rails g contoroller products
$ rails g model product
$ rails db:migrateいつもの流れですね。データベースの作成やマイグレーションファイルの記述など細かい点は省略します。
それでは早速ルートファイルから記述していきましょう。
app/config/routes.rbRails.application.routes.draw do root "products#index" resources :products devise_for :users, controllers: { registrations: 'users/registrations' } enddeviseの部分はあらかじめ実装してあるユーザー機能に関する部分なので気にしなくて大丈夫です。
ここも細かい説明は不要ですね。resourcesで基本のアクションを作り、ルートパスにindexアクションを指定しています。(今回、destroyとshowは使わないのでexceptして頂いても大丈夫です)次にcontrollerの記述です。
app/controllers/products_controller.rbclass ProductsController < ApplicationController before_action :ensure_current_user, only[:edit, :update] before_action :set_product, only[:new, :create, :edit, :update] def index @products = Product.all end def new @prodcut = Product.new end def create @product = Product.new(product_params) if @product.save redirect_to products_path else render :new end end def edit end def update if @product.update(product_params) redirect_to products_path else render :edit end end private def product_params params.require(:product).permit(:name).merge(user_id: current_user.id) end def ensure_current_user product = Product.find(params[:id]) if product.user_id != current_user.id redirect_to action: :index end end def set_product @product = Product.find(params[:id]) end endひとまずはこんなところでしょうか。
順を追って解説していきます。まずは基本のアクションについて。
@products = Product.all
indexは問題ないですね、productテーブルに登録された全てのレコードを取り出しています。
@prodcut = Product.new
new,createでは商品の登録を行っています。モデル.newで新しいオブジェクトを生成し、そこにフォームの値を代入します。
def product_params
params.require(:product).permit(:name).merge(user_id: current_user.id)
endそうして送信されたデータをproduct_paramsメソッドで受け取っています。みんな大好きストロングパラメータですね。
最低限の機能を実装するだけなのでカラムはnameだけにしています。if @product.save
redirect_to products_path
else
render :new
end続くif文ですが、これがエラーハンドリングというやつです。
処理が成功した場合はindexへ、逆に失敗した場合はnewを再表示させています。
概念としては複雑な部分もありますが、機能としてはもうお馴染みといっていいと思います。@product = Product.find(params[:id])
次にedit,updateアクションとなりますが、やっていることは先ほどと同じです。createと違うところと言えば、すでにデータが存在するので新しくオブジェクトを作る必要がなく、findメソッドで選択したproductをもってきていることです。
def ensure_current_user
product = Product.find(params[:id])
if product.user_id != current_user.id
redirect_to action: :index
end
end最後にensure_current_userメソッドです。
一見難しそうに見えますが処理はすごく簡単。要は選択したproductのユーザー情報とログインしているユーザー情報が違う場合は編集できませんよーってことです。さて、コントローラーの記述が終わったのでそろそろviewファイルを記述します。
app/view/products/index.html.haml- if user_signed_in? - @products.each do |product| - if product.user_id == current_user.id = link_to edit_product_path(product.id) do #{product.name} = link_to("出品", new_product_path) %h2 ログインしています = link_to 'ログアウト', destroy_user_session_path, method: :delete - else %h2 ログインしていません = link_to '新規登録', new_user_registration_path = link_to 'ログイン', new_user_session_pathまずはindexからですが、着目すべきは最初の6行だけです。
ユーザーがログインしているか。
その商品はそのユーザーが登録したものか。
といった二つの条件のもと、editとnewのパスを表示させています。app/views/products/_form.html.haml= form_with model: @product, local: true do |f| = f.text_field :name, placeholder: 'name' = f.submit 'SEND'こちらも特別に説明すべきことはないと思います。
form_withメソッドを使ってproductモデルにデータを送るというものですね。あとはこいつを部分テンプレートとしてnew.html.hamlとedit.html.hamlにrender表示させるだけです。最後に
ここまでで、商品のデータを作成し、それを編集する機能を実装することができました。(カラムは名前だけですが、、、)
仕様書でいうところの、
- 商品に登録された情報をひとつひとつ変更できる。
- 商品情報を編集できるのは商品を登録したユーザーのみ。
- エラーハンドリングを行う。
これら3つをクリアすることができたことになります。
次のpartでは画像(imageテーブル)を追加できるようにしていくのでよければお付き合いください。
- 投稿日:2020-07-10T16:07:44+09:00
BonsaiのReindexで "this cluster currently has [3000]/[3000] maximum shards open" とエラーがでる
Heroku、Rails、Elasticsearch、Bonsai、Searchkickという環境で
$ bundle exec rake searchkick:reindex CLASS=Use # もしくは $ bundle exec rake searchkick:reindex:allとしてReindexをしようとすると以下のようなエラーがでる。
this action would add [2] total shards, but this cluster currently has [3000]/[3000] maximum shards openShard(シャード:直訳で破片)というのはインデックスを分割したものらしく、通常はなにかのバックアップとして、メインで使うプライマリーシャードに対してレプリカシャードを作ったりするらしい。
しかしShardは3000どころか2しか使ってないとbonsaiに表示されてるんだが‥。
おそらくの原因
おそらくは bonsai が提供する Elasticsearch のバージョンが 7.2.0 で、searchkickの最新版が依存するGem
elasticsearch
のバージョンが 7.8.0 になっていたためだったと思われる。Gemfile.lockの中を elasticsearch で検索してバージョンが 7.8.0 になってたら、これを疑った方がいい。The latest version works with Elasticsearch 6 and 7
https://github.com/ankane/searchkick#getting-startedSearchkick - bonsai
https://docs.bonsai.io/article/99-searchkickSearchkickのRead.meにも、bonsaiのドキュメントにもこのことは触れられていないので気づきにくい。
解決策(たまたまかも)
elasticsearch のバージョンを 7.2.0 と明示的に指定して
# Gemfile gem 'elasticsearch', '7.2.0' # ←追加 gem 'searchkick'The bundle currently has elasticsearch locked at 7.8.0
と怒られたので
bundle update
した。$ bundle update Fetching elasticsearch-api 7.2.0 (was 7.8.0) Installing elasticsearch-api 7.2.0 (was 7.8.0) Fetching elasticsearch-transport 7.2.0 (was 7.8.0) Installing elasticsearch-transport 7.2.0 (was 7.8.0) Fetching elasticsearch 7.2.0 (was 7.8.0) Installing elasticsearch 7.2.0 (was 7.8.0)しかし他のGemのバージョンも上げてしまったので、特定のGemだけをアップデートさせる
bundle update elasticsearch
とした方が良かったかもしれない。あとはHerokuにプッシュしてReindexしたら上手くった。
$ git push heroku master $ heroku run bundle exec rake searchkick:reindex:all参考
shardの状態の確認コマンドはこちらが参考になった?
https://swfz.hatenablog.com/entry/2015/07/22/040354その他
bonsaiのConsoleでインデックスを削除してReindexしたら上手くこともあった。
GET /_cat/indices # もしくは GET /_aliased/ # でインデックス名を確認し DELETE /posts_production_xxxxxxxx # で一度インデックスを削除してからReindexし直すと直る。けどpuroductionで同様にしたらダメでしばらく検索機能が使えない状態に‥。bonsaiを削除して入れ直してもダメ、
heroku restart
してもダメで、原因を特定せずに本番環境でやってしまう危険さを身にしみたので皆さんも注意してほしい。レプリカシャード
bonsaiをHerokuの管理画面から入れただけなので、今回レプリカシャードの指定をしていない。シャードが最大上限3000に達したというのはご判定だろうが、bonsaiのドキュメントにあるように
number_of_replicas
をModelで設定した方がいいのかもしれない。User.rbclass User < ApplicationRecord searchkick settings: { number_of_replicas: 0 } endもしかするとProcfile経由でリリース時にReindexを自動実行しようとしたせいでこうなったのかもしれない。force push とかもしちゃっていたので‥。
- 投稿日:2020-07-10T16:07:44+09:00
[未解決] BonsaiのReindexで "this cluster currently has [3000]/[3000] maximum shards open" とエラーがでる
解決したと思ったら再発するの繰り返しです。Qiitaには非公開に戻す機能が内容で、備忘録も兼ねて未解決のまま公開しておきます。詳しい人いたらコメントで教えてくれると嬉しいです。
Heroku、Rails、Elasticsearch、Bonsai、Searchkickという環境で
$ bundle exec rake searchkick:reindex CLASS=Use # もしくは $ bundle exec rake searchkick:reindex:allとしてReindexをしようとすると以下のようなエラーがでる。
this action would add [2] total shards, but this cluster currently has [3000]/[3000] maximum shards openShard(シャード:直訳で破片)というのはインデックスを分割したものらしく、通常はなにかのバックアップとして、メインで使うプライマリーシャードに対してレプリカシャードを作ったりするらしい。
しかしShardは3000どころか2しか使ってないとbonsaiに表示されてるんだが‥。
解決策①(別アプリで再発)
stagingとしている方で、bonsaiのConsoleでインデックスを削除してReindexしたら上手いった。
GET /_cat/indices # もしくは GET /_aliased/ # でインデックス名を確認し DELETE /posts_production_xxxxxxxx # で一度インデックスを削除してからReindexし直すけどpuroductionで同様にしたらダメ‥。bonsaiを削除して入れ直してもダメ、
heroku restart
してもダメだった‥。解決策②(ただし別アプリで再発)
Bonsai が提供する Elasticsearch のバージョンが 7.2.0 で、Searchkickの最新版が依存するGem
elasticsearch
のバージョンが 7.8.0 になっているからではと考えた(Gemfile.lockの中を elasticsearch で検索してバージョンが 7.8.0 になってたので気づいた)。The latest version works with Elasticsearch 6 and 7
https://github.com/ankane/searchkick#getting-startedSearchkick - bonsai
https://docs.bonsai.io/article/99-searchkickSearchkickのRead.meにも、bonsaiのドキュメントにもこのことは触れられていないが関係があるのでは?
elasticsearch のバージョンを 7.2.0 と明示的に指定して
# Gemfile gem 'elasticsearch', '7.2.0' # ←追加 gem 'searchkick'The bundle currently has elasticsearch locked at 7.8.0
と怒られたので
bundle update
した。$ bundle update Fetching elasticsearch-api 7.2.0 (was 7.8.0) Installing elasticsearch-api 7.2.0 (was 7.8.0) Fetching elasticsearch-transport 7.2.0 (was 7.8.0) Installing elasticsearch-transport 7.2.0 (was 7.8.0) Fetching elasticsearch 7.2.0 (was 7.8.0) Installing elasticsearch 7.2.0 (was 7.8.0)他のGemのバージョンも上げてしまったので、特定のGemだけをアップデートさせる
bundle update elasticsearch
とした方が良かったかもしれない。これをHerokuにプッシュしてReindexしたら上手くった。
$ git push heroku master $ heroku run bundle exec rake searchkick:reindex:allシャード数について
bonsaiをHerokuの管理画面から入れただけなので、今回レプリカシャードの指定をしていない。シャードが最大上限3000に達したというのは誤判定だろうが、bonsaiのドキュメントにあるように
number_of_replicas
をModelで設定した方がいいのかもしれない。User.rbclass User < ApplicationRecord searchkick settings: { number_of_replicas: 0 } endその他
もしかするとProcfile経由でリリース時にReindexを自動実行しようとしたせいでこうなったのかもしれない。force push とかもしちゃっていたので‥。またstagingとproductionで解決した方法が違ったので、この2つのアプリに何か違いがあるのかも‥。
参考
shardの状態の確認コマンドはこちらが参考になった?
https://swfz.hatenablog.com/entry/2015/07/22/040354
- 投稿日:2020-07-10T16:07:44+09:00
ElasticsearchのReindexで "this cluster currently has [3000]/[3000] maximum shards open" とエラーがでるとき
heroku、Rails、Elasticsearch、bonsaiという環境で
$ bundle exec rake searchkick:reindex CLASS=Use # もしくは $ bundle exec rake searchkick:reindex:allとしてReindexをしようとすると以下のようなエラーがでる。
this action would add [2] total shards, but this cluster currently has [3000]/[3000] maximum shards openShard(シャード:直訳で破片)というのはインデックスを分割したものらしく、通常はなにかのバックアップとして、メインで使うプライマリーシャードに対してレプリカシャードを作ったりするらしい。
しかしShardは3000どころか2しか使ってないとbonsaiに表示されてるんだが‥。
結論(編集中)
bonsaiのConsoleでインデックスを削除してReindexしたら上手くこともあったけど、本番環境でもダメ、bonsaiを削除して入れ直してもダメ、
heroku restart
してもダメ。Qiitaに非公開に戻す機能がないので以下をやると危険です。取り急ぎ。GET /_cat/indices # もしくは GET /_aliased/ # でインデックス名を確認し DELETE /posts_production_xxxxxxxx # で一度インデックスを削除してからReindexし直すと直る。Procfile経由でリリース時にReindexを自動実行しようとしたせいでこうなったのかもしれない。
- 投稿日:2020-07-10T15:51:25+09:00
ポートフォリオ
ポートフォリオ1
こちらのポートフォリオは環境構築だけで開発は行っていません。
(aws,nginx,ruby,docker,mysql)を使って環境構築を行いました。https://github.com/tmk616window/docker-ruby2
ポートフォリオ2
ポートフォリオ投稿サイトを作りました。
URLはこちらになります
https://github.com/tmk616window/review00
https://review0.herokuapp.com/経緯
まずなぜこれを作ろうと思ったのか説明させていただきます。
自分がインターンの採用のためにポートフォリオを作ろうと思ったときに「何を作ればいいかわからない。どこまで作りこめばいいかわからない。」という悩みがありました。
ツイッターやyoutubeのコメント欄でもこういった悩みを持った方々をよく見かけました。
それだったら何を作ればいいのかまたどれくらい作りこめばいいのかの指標になるようなものをポートフォリオに落とし込んでみようと思いました。コンプト
エンジニア採用が決まった方が記事を投稿し、それを未経験の方が参考にしてポートフォリオを作る指標を定めることを目標にしています。
機能
では実際に機能の説明をさせていただきます。
トップページ
こちらがトップページになります。
採用された方が自分のポートフォリオを6項目で評価し、数値化してわかりやすくしています。詳細ページ
興味がある投稿をクリックすると詳細ページに移動します。
詳細ページにはポートフォリオの情報がより詳しく記載されています。
いいねボタンはajaxで実装しました。
いいね数の数字もリアルタイムで変わるように実装しました。相談
詳細ページの「相談する」のボタンを押すと詳細ページに移動します
相談ページではslack形式でリアルタイムに相談できるようなものを作りました。
こちらでは詳細ページで気になったことなどを質問できるようにするために作りました。
入力したメッセージは相手のマイページに通知が行くようになっています
actioncableを使いました。マイページ
上のチャットメッセージのところに先ほど他のユーザーが相談ページで送ったメッセージの通知が来るようになっています。
マイページの画像はawsのs3に接続していましたが料金がかかりすぎていたので接続を切りました。
コード自体は残っているのでそちらを参照お願いします。
ほかのユーザーのマイページに入ると画像の下にフォローボタンが出てきてフォローすることができます。イベント一覧
こちらは時間があったのでサブで機能追加したものです。
画像はawsのs3に接続していましたが料金がかかりすぎていたので接続を切りました。
コード自体は残っているのでそちらを参照お願いします。
気になるイベントをクリックすると詳細ページに飛びます。イベント詳細ページ
詳細ページに飛びます。
下のイベント申し込みボタンをクリックすると申し込みページに飛んで申し込むことができます。
申し込みが完了すると相手のマイページのイベントメッセージのところに通知が行くようになっています。以上でポートフォリオの説明を終わります。
- 投稿日:2020-07-10T12:22:36+09:00
rails db:migrate で BusyException: database is locked
以下のようなエラーがでたが、原因はデータベースのGUI閲覧ツール(DB Browser for SQLiteなど)で変更を保存前の操作が残っていたから。
$ rails db:migrate rails aborted! StandardError: An error has occurred, this and all later migrations canceled: SQLite3::BusyException: database is locked以下によると、SQLiteは同時に1つのプロセスからしかアクセスできないらしく、DB Browser がアクセスしてたからロックされてたということだそうだ。
https://stackoverflow.com/questions/5452662/rake-dbmigrate-is-throwing-busyexception-database-is-locked-exception
- 投稿日:2020-07-10T09:57:17+09:00
Searchkickでのデバッグ術
Railsコンソールで
dubug: true
属性?を付与して検索を実行してやると、そのときに使われた Search Option, Setting, Mapping, Results(検索スコアとか)を見れていい。> Post.search "日本の絶景", fields: [:name, :description, :category_name], operator: "or", debug: trueModel Searchkick Options {:language=>"japanese", :_type=> #<Proc:0x00007f96bd9f4858 /Users/takuya/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/searchkick-4.4.1/lib/searchkick/model.rb:17 (lambda)>, :class_name=>"Post"} Search Options {:fields=>[:name, :description, :category_name], :operator=>"or", :debug=>true} Elasticsearch Query curl http://localhost:9200/posts_development/_search?pretty -H 'Content-Type: application/json' -d '{"query":{"bool":{"should":[{"dis_max":{"queries":[{"match":{"name.analyzed":{"query":"日本の絶景","boost":10,"operator":"or","analyzer":"searchkick_search"}}},{"match":{"name.analyzed":{"query":"日本の絶景","boost":1,"operator":"or","analyzer":"searchkick_search","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true}}}]}},{"dis_max":{"queries":[{"match":{"description.analyzed":{"query":"日本の絶景","boost":10,"operator":"or","analyzer":"searchkick_search"}}},{"match":{"description.analyzed":{"query":"日本の絶景","boost":1,"operator":"or","analyzer":"searchkick_search","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true}}}]}},{"dis_max":{"queries":[{"match":{"category_name.analyzed":{"query":"日本の絶景","boost":10,"operator":"or","analyzer":"searchkick_search"}}},{"match":{"category_name.analyzed":{"query":"日本の絶景","boost":1,"operator":"or","analyzer":"searchkick_search","fuzziness":1,"prefix_length":0,"max_expansions":3,"fuzzy_transpositions":true}}}]}}]}},"timeout":"11s","_source":false,"size":10000}' Elasticsearch Results { "took": 10, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": { "value": 21, "relation": "eq" }, "max_score": 57.485226, "hits": [ { "_index": "posts_development_20200709213129463", "_type": "_doc", "_id": "28", "_score": 57.485226 }, { "_index": "posts_development_20200709213129463", "_type": "_doc", "_id": "20", "_score": 46.743748 } ] } }
- 投稿日:2020-07-10T08:52:43+09:00
[Rails]初学者によるRubocopの導入
はじめに
Rubocopとは、Rubyの静的コード解析ツール。
ruby-style-guide
に従って、ソースコードの修正・改善点を指摘してくれます。また、インデントのずれや、不必要なスペース・改行などは特定のコマンドを打つことで自動で修正してくれるので、自分にとってはもちろん、他の人が見ても読みやすいコードに整形することが出来ます。
※あくまで初学者の観点で設定等を決めています。導入
gemfilegem 'rubocop', require: falseターミナルbundle install使ってみる
ターミナルbundle exec rubocopこれらがRubocopが検知した修正点になります。
しかし、デフォルトのルール全てに従っていると、コードを書く際に気を配る点があまりにも増えてしまうので、自分やチーム内で許容するルールを設定することが出来ます。設定をカスタマイズする
アプリケーションのディレクトリに
.rubocop.yml というファイルを作成し、その中に設定を記述します。rubocop.ymlAllCops: # 除外するディレクトリを設定。例えばschemaやmigrationファイルなどは書き直すことが少ないため、検知対象外に Exclude: - bin/* - db/schema.rb - node_modules/**/* - db/migrate/* - vendor/**/* # Rails向けのチェックを行う Rails: enabled: true # "Missing top-level class documentation comment."を無効 Style/Documentation: Enabled: false # "Prefer single-quoted strings when you don't need string interpolation or special symbols."を無効 Style/StringLiterals: Enabled: false # "Line is too long"を無効 Metrics/LineLength: Enabled: false #'frozen_string_literal: true'を無効 Style/FrozenStringLiteralComment: Enabled: falseなど様々な設定が可能です。
デフォルトの設定を参考にいろいろいじってみようと思います。設定後、もう一度
ターミナルbundle exec rubocop
すると、72filesが56filesと、先ほどよりも修正点が減っていることがわかります。修正する
ターミナルbundle exec rubocop --auto-gen-config.rubocop.todo.yml というファイルが自動生成されます。
これにより、一時的に修正点を全て無効とみなされます。
ここでrubocopを実行すると、修正点がない状態になります。.rubocop.todo.yml# Offense count: 1 # Cop supports --auto-correct. # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include. # Include: **/*.gemfile, **/Gemfile, **/gems.rb Bundler/OrderedGems: Exclude: - 'Gemfile'一例として、上記のような記述があります。
この記述を削除すると、該当部分の無効化していた修正点が復活します。
早速修正して行きますが、
Cop supports --auto-correct.
という記述がある場合、Rubocopが以下のコマンドで自動で修正してくれます。ターミナルbundle exec rubocop -a今回修正したのは、Gemfileのgemの記述がアルファベット順になっていないのを正しい順番に並べ替えました。
まとめ
1.gemを導入し、
.rubocop.yml
に設定をカスタマイズする
2.bundle exec rubocop --auto-gen-config
を実行し、
.rubocop.todo.yml
を生成する。
3..rubocop.todo.yml
に書かれている記述を1つ消し、修正する
4.3.を繰り返す。実際の現場では、自動化されていてあまり自分で修正することはなさそうですが、
まだまだ初学者ですので、一つ一つ改善していって規約を確認し、
初めから読みやすいコードを書けるエンジニアになれるよう心がけます。
- 投稿日:2020-07-10T04:07:15+09:00
Railsでcredentials.yml.encをAtomエディタで編集したかった色々(Windows)
初めてQiita書きます書き方全然わかりません許してください。
タイトルの通り、Rails5.2以降で追加されたらしいcredentials.ymlを
Windows環境でAtomエディタにて編集したかった時の色々です。(筆者はRails6ですが)
自分にいい感じの日本語記事が見つからなかったので、もういっそ自分で忘備録作ってしまおうと。
あと同じ目的だったり、ハマった人のためになればいいなと。
大先輩達による記事を読んでからのお話
以下2記事、リンクになっています。
Rails5.2から追加された credentials.yml.enc のキホンたった30分でわかるcredentials.yml.enc[rails5.2] - 環境変数を定義する使い方 -
さっそくエラーにぶち当たるお話
rails credentials:editしてのエラーメッセージ。上記の記事に書いてある通りのエラーメッセージなので理解はできたのですが、なにせAtomエディタで編集したいのと、Windows環境なので色々自分とは環境が違ってくるなと。
コレ
$ rails credentials:edit No $EDITOR to open file in. Assign one like this: EDITOR="mate --wait" bin/rails credentials:edit For editors that fork and exit immediately, it's important to pass a wait flag, otherwise the credentials will be saved immediately with no chance to edit.EDITORが指定されてないよ、何使ったらいいのわかんないよ。って言われるやつですね。
上の方にある記事ではvi、vimとかの指定でしたね。今だけはとりあえずAtom使わせてください。初心者なんです......。
Atomエディタを指定してあげる の前に
Windows環境でシステム環境変数を指定するのですが。一体どうやって環境変数:EDITORを登録するんだ?
Windowsでシステム環境変数いじるなんて余裕ですバッチこいな人は飛ばしてください。
Windowsでシステム環境変数の設定の仕方
Windowsのシステム環境変数の設定画面への行きつき方は
過去の自分へはこちらが分かりやすかったです。
(Qiita外の記事です)
Windows 10でPath環境変数を設定/編集する:Tech TIPS - @IT
が、めんどくさい私はWindows検索窓にて検索しちゃいます。
開いたらこんな画面。そして環境変数(N)...
と意味深な所をクリック
こんな画面が開いたら「新規」の部分どちらかをクリック
(モザイク広くてごめんなさい)
私は上のユーザー環境変数で「新規」しています。
ではWindowsでシステム環境変数の設定の仕方余裕ですバッチこいっと
すっ飛ばした勢と合流します。
Atomエディタを指定してあげる
変数EDITORにAtomエディタを割り当てます。
その時の変数名と変数値がこちら。
変数名を 「EDITOR」
変数値を 「"atom" --wait」
としてOKです。
(--wait を入れとかないと、コマンドプロンプトからrails credentials:editして
Atomエディタ起動する前に処理が進んじゃってエディタ開かせてくれません)一応PC再起動して環境変数を反映させます。
あなたのプロジェクトファイルにてrails credentials:editしてみてください。そこそこ時間経ってから
Atomエディタが元気よく立ち上がりましたか?14816.credentials.yml# aws: # access_key_id: 123 # secret_access_key: 345 # Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies. secret_key_base: ai3id93jaso......と表示され、開いているファイル名が14816.credentials.ymlとか13613.credentials.ymlとか
最初に数列が追加された名前で開きましたか?
成功です。
余談
あとは好きなように編集して保存してエディタを閉じるだけ。
閉じたらFile encrypted and saved.なんてコンソールに続きが出てたら大成功です。
反映されているかの確認のため、rails credentials:show してみてください。
以上です。以上なんですけど。
時々、Function provided here: Object.<anonymous> (C:\Users\ユーザー名\AppData\Local\atom\app-1.48.0\resources\app.asar\node_modules\github\lib\worker.js:79:22 Remote event names: destroyed, crashed File encrypted and saved.とかとかなんか、destroyed???? crashed???やばくない??
となりますが。厳密には違うかもしれませんけど、それはエディタ自体を終了する前にタブを閉じていたりするとなります。一応Remote event names: destroyed, crashed出ていてもきちんと暗号化されていますし、
rails credentials:showもRails.application.credentials.~~~~
でも呼び出せるので大丈夫だとは思いますが。
怖いので。
rails credentials:edit でAtomエディタを開く(開かせる)
開いたエディタで編集する
保存する
右上の✕ボタンで "Atomエディタ自体" を終了する。
コンソールに戻ってくると「File encrypted and saved.」だけが出てる。
rails credentials:showで反映されているか確認してみる。
なのが安心できますね。エラーメッセージが出たときにgithubの何かしらが出ていたので、
git(commit複数行メッセージ)とかでもAtomエディタ使っている人はこうなるのかもしれません。読みづらい文章でごめんなさい。Qiitaどころかこんな長文ほぼ初めて書きました。
読んでいただいた方ありがとうございました。
- 投稿日:2020-07-10T02:21:17+09:00
【Rails6】CarrierWaveとfog-googleでGoogle Cloud Storage(GCS)に画像をアップロードした
Rails6で開発していますが、画像のアップロード機能どうしようかな〜と思って、active storageを最初に利用していましたが、RailsをAPIにしてNuxt.jsに返却するのが地味に面倒とか、気をつけないとN+1問題をめっちゃ発生させたりしそうで嫌だったので、CarrierWaveを利用することにしました。(別に頑張っても良かったんですが、その辺を考えるのが面倒だったので、もう少し実装が軽くなる方法を選びました。)
また、改めてCarrierWaveを利用しようと思ったきっかけも以下でした。
https://tech.dely.jp/entry/2019/12/22/145733
しかし、CarrierWaveに移行したのはいいんですが、S3の利用率が高いのかは分かりませんが、GCSの情報があまりなかったんですよね…。
ただ、画像をRails6(consoleですが)で、GCSに画像をアップロードすることが出来たため、備忘録を残したいと思います。
Gemfile
gem "carrierwave" gem "fog-google" gem "google-api-client" gem "mime-types"Uploader
アップローダー名はImageとでもしておきましょう。
$ rails g uploader Image
image_uploader.rbclass ImageUploader < CarrierWave::Uploader::Base # テスト以外の環境はGCSにアップロードされるよう設定 if Rails.env.test? storage :file else storage :fog end def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end endCarrierWave
あらかじめ、Google Cloud Storageのサービスアカウントを作って、認証情報となるJsonを取得しておきましょう。
※ちなみに閲覧については
allUsers
が可能です。以下が参考になるかもしれません。
https://cloud.google.com/iam/docs/creating-managing-service-account-keys?hl=ja
config/initializers配下に、
carrierwave.rb
のファイルを作りましょう。
dotenvとcredentialsがごっちゃになってますが気にしないでください…carrierwave.rbCarrierWave.configure do |config| config.fog_provider = "fog/google" config.fog_credentials = { provider: "Google", google_project: ENV["GOOGLE_CLOUD_PLATFORM_PROJECT_NAME"], # ここでサービスアカウントのJsonを呼び出すようにしてあげる google_json_key_string: Rails.application.credentials.gcs[:google_cloud_storage_credential_content] } config.fog_directory = ENV["GOOGLE_STORAGE_BUCKET_NAME"] end CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
credentials.yml.enc
の書き方とかは、以下の記事が参考になりました。https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39
この書き方地味に公式に載ってなくて、Issue起票して解決されていた方がいました。
そのドキュメントも共有しておきます。
https://github.com/fog/fog-google/issues/385
Model
Aritlce(記事)にthumbnail(サムネイル)を設定する想定で話を進めます。
サムネイルのカラムとアップローダークラスを紐付けましょう。
article.rbclass Article < ApplicationRecord mount_uploader :thumbnail, ImageUploader endRails Console
既にDBにデータがある前提のコマンドです。
また、画像は適当なディレクトリに入れています。
[1] pry(main)> article = Article.last [2] pry(main)> thumbnail = Rails.root.join("app/assets/images/test.png").open [3] pry(main)> article.update(thumbnail: thumbnail)これで完了です。
- 投稿日:2020-07-10T02:16:02+09:00
(1分で決める)empty?とblank?とpresent?の使い分けについて
(備忘録)説明最小限にしてすぐ使用できるようにまとめた。(結論)blank?かprresent?をどっちか覚えとけば何とかなる。
empty?を使う時は
下記の条件を満たしたうえで中身が空であるか知りたいときに使用。
①必ず入れ物が存在していること
②中身が数字やtrue,falseでないことif box.empty?①②を満たさない場合は NoMethodErrorが生じる。
blank?を使うときは
中身が空orそもそも存在しているかを知りたいときに使用
irb(main):001:0> box = nil => nil irb(main):002:0> box.blank? => truepresent?を使用するときは
存在していてかつ中身が空ではないことを知りたいときに使用(!blank?と同義)
irb(main):006:0> box = nil => nil irb(main):007:0> box.present? => falseもう少し詳しく知りたい、この場合はどうすればいいの?ってときは
https://qiita.com/go_d_eye_0505/items/541110cb9821734b0623
表形式でパターンを網羅しているのでわかりやすかったです。
- 投稿日:2020-07-10T01:58:49+09:00
Rails6 + Bootstrap4.5でドロップダウンが機能しない
以下解決プロセス
application.html.erbの
タグ内に
以下を挿入<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>/app/assets/javascript/application.jsがないよと言われるようになるので
/app/assets/javascript/application.js
を作成し以下を記述
(Rails 6ではデフォルトでこの場所にapplication.jsがない)//= require jquery3 //= require popper //= require bootstrapこれだけだとapplication.jsがassets pipelineに含まれてないとエラーがでるので
/app/assets/config/manifest.js
//= link_tree ../images //= link_directory ../stylesheets .css //= link application.js # ココを追記これでドロップダウンメニューが機能するようになりました
Bootstrapではないですがこちらを参考にしました
Rails6でSemanticUIのJavaScriptを読み込む方法(ドロップダウン・アコーディオン等を使いたい!) - Qiita
- 投稿日:2020-07-10T01:02:16+09:00
TECH CAMP学習 個人アプリ作成②
deviseを使用して、ユーザーモデルを作成
個人アプリ作成でdeviseのインストールを行いました。
まずはGemfileに下記を入力します。
ちなみにdeviseは日本語で「工夫する、考案する、案出する、発明する」という意味だそうです。
次にターミナルにて
『bundle install』
『rails g devise:install』
『rails g devise user』を順番に実行します。
そしてマイグレーションファイルを以下2点のように編集します。
※注意 #は省いていただいて結構です。
① null:falseは空の状態での保存を防ぐ為に使用します。
②unique:trueはテーブル内で名前の重複を禁止させる為に使用します。
次にapp/models/user.rbを下記のように編集します。
validatesは日本語で検証する、presenceは存在、uniquenessは唯一性という意味だそうです。英語で書かれてあるコードを普通に日本語に訳すことで、意味もよく捉えられるように感じました。
あとmigrationは移動、移行という意味のようです。つまりマイグレーションファイルはデータベースのテーブルへの移動するための設計図のようなイメージでよいのではないでしょうか。