- 投稿日:2020-06-27T21:26:15+09:00
ゲストログイン機能について
ポートフォリオの作成にあたり、ゲストログイン機能は必須です。
忙しい担当者の方が、わざわざ会員登録をするよりも
ささっと多くの機能を見る場合が多いためです。ゲスト登録機能は、下記の記事の方法で搭載できました。
こちらの「その2: ゲストログイン機能の実装方法」で実装しました。
その際、下記の2点は少しつまづいたので
記載指定おきます。[1]routes.rbの設定
config/routes.rbdevise_scope :user do post 'users/guest_sign_in', to: 'users/sessions#new_guest' endこちらは、最初勝手に「devise_for :users」を修正するのかと思いましたが
追記する形で大丈夫でした。デバイスを利用している方ですと
config/routes.rbdevise_for :users devise_scope :user do post 'users/guest_sign_in', to: 'users/sessions#new_guest' endこんな感じですね。
[2]modelの設定
あとは記事の通りにやればうまく行くのですが、
自分は1つだけエラーになりました。上記の設定ですと、ゲストユーザーのアカウントは
メールアドレスとパスワードの作成だけされています。そのため、アカウントの作成に「nickname」などが
必須項目であった場合、エラーが起こります。その際は、モデルでその情報を追記してあげましょう。
models/user.rbdef self.guest find_or_create_by!(nickname: 'ゲスト', email: 'guest@example.com') do |user| user.password = SecureRandom.urlsafe_base64 end endこれで問題なく作成できました!
- 投稿日:2020-06-27T18:44:05+09:00
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
たまに以下エラーが起きることがあります。
# RAILS_ENV=production bundle exec rake db:migrate rake aborted! Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)結論から言うと、DBの接続情報が誤っているためにこのエラーが起きます。
やることは
config/database.yml
に関して以下のことになります
- 次の値に対して
config/database.yml
自体に設定している値config/database.yml
から指定している環境変数- 次の事態が起きていないかどうか確認する
- 値が間違っている
- DB設定の値が更新されていて、更新漏れが起きている
私は
config/database.yml
では環境変数を指定することが多く、
いつの間にかに更新されていた環境変数を更新漏れしていたり、
dockerの他のコンテナで指定していたDB名と環境変数で指定していたDB名が間違っていたり
と度々このエラーに遭います。他のエラーのときにもこのエラー起きるかもしれませんが、私の場合100%接続情報エラーなので、このエラーが紛らわしくて仕方ないです。
接続設定間違ってるよと言ってくれれば律儀に/var/run/mysqld/mysqld.sock
がどういうものを調べに行ったり、ググらなくて済むので他の場合は以下のQiitaの場合かもしれません
https://qiita.com/fujitora/items/d341c52706d1954cae28
- 投稿日:2020-06-27T18:19:17+09:00
初投稿。グループ機能作成中に起きた事
Routing Error
グループ機能作成中に起きたRouting Errorについて、
この画像では、controllerがgroupsになっている。
下の画像では、groupsとなっているが、ここでgroupにした事でRouting Errorが起きてしまった。
マイグレーションについて
例えばこの様マイグレーションファイルにdb:migrateで間違った記述をしてしまった時
db:rollbackで戻して訂正する事ができる。
また、db:migrateで訂正完了です。db:rollback
db:rollbackでは一つ前しか戻せない。
db:rollback STEP=数字
db:rollback STEP=数字を使う事で任意に所まで戻す事ができる。
- 投稿日:2020-06-27T17:33:35+09:00
Rails CRUD機能実装①(今回は、新規追加、削除)
この記事の目的
railsを用いた、CRUD機能をもったwebアプリケーションの作成手順です。鳥の写真と名前を投稿できるサイト(birdtweet)です。
railsアプリケーションの作成
railsのバージョン6.0.0を指定。-dの後ろに使用するDB(今回はmysql)を指定。
rails _6.0.0_ new birdtweet -d mysql設定変更。
config/database.yml... # encoding: utf8mb4 encoding: utf8 ...DB作成
cd birdtweet rails db:createGemfileの編集
プロジェクト直下にあるGemfileを開くGemfile# gem 'mysql2', '>= 0.4.4' gem 'mysql2', '>= 0.5.3' ........ (ファイル最下行) gem 'pry-rails'ターミナルで設定内容の更新
bundle updatemodelの作成
ターミナルにて
rails g model birdカラムを追記
db/migrate/2020********create_birds.rb... create_table :birds do |t| t.string :name t.text :pic t.timestamps end ...コマンドにて、変更内容の更新!
rails db:migrateコンソールでDBにデータをいくつか入れます。
rails c Bird.create(name: "ツノメドリ", pic: "https://cdn.pixabay.com/photo/2020/05/26/13/22/puffins-5223057_1280.jpg") Bird.create(name: "カワセミ", pic: "https://cdn.pixabay.com/photo/2017/02/07/16/47/kingfisher-2046453_1280.jpg") exitコントローラの作成
以下のコマンドで、コントローラを作成します。
rails g controller birds複数形にしたり、しなかったり混乱しますが、
モデルだけが単数形です!ここからの流れ
各機能作成の流れはほぼほぼ同じです!
routes.rbに追記
↓
index.html.erbに各機能へのリンクを追記(index意外)
↓
birds_controller.rbに追記
↓
機能名.html.erb作成一覧表示機能
railsには7つのアクションがある。
- index:一覧
- show:詳細
- new:新規作成画面への遷移
- create:新規データの保存
- edit:編集画面への遷移
- update:編集内容の更新
- destroy:削除
全機能を使わない場合は、onlyオプションで使うものだけを指定する。
config/routes.rb# resourcesの後ろは、モデル名の複数形 resources :birds, only: :indexapp/controllers/birds_controller.rb... def index # インスタンス変数にBirdモデルのデータを格納します。 @birds = Bird.all end ...index.html.erbファイル作成
ビュー内でインスタンス変数を、eachメソッドを使って全て表示します。app/views/birds/index.html.erb<% @birds.each do |bird| %> <%= bird.name %> <div style= "background-image: url(<%= bird.pic %>); background-position: center center; background-size: cover; width: 300px; height: 300px; margin-bottom: 10px; "> </div> <%end%>新規投稿機能
流れは同じく、routes → controller → viewなのですが、投稿画面への移動(new)からのデータ追加(create)なので、一連の流れを二回やります!
routes.rbRails.application.routes.draw do # resourcesの後ろは、モデル名の複数形 # アクションが複数あるときは、配列の形にしてあげます resources :birds, only: [:index, :new] endindex.html.erb<%=link_to '新規投稿', new_bird_path, method: :get%> ...birds_controller.rb... def new # Birdモデルのインスタンス化したものを、インスタンス変数に格納します。 @bird = Bird.new end ...new.html.erb作成
app/views/birds/new.html.erb<%# 遷移先urlを記載しなくても、インスタンス変数に入れたモデルから判断して、遷移してくれます %> <%=form_with(model: @bird, local: true) do |form| %> <%= form.text_field :name, placeholder: "鳥の名前" %> <%= form.text_field :pic, placeholder: "鳥の写真のURL" %> <%= form.submit "投稿" %> <%end%>http://localhost:3000/birds/new
にアクセスすると投稿画面ができてます!
次は、入力情報を登録する機能です。
routes.rbRails.application.routes.draw do # resourcesの後ろは、モデル名の複数形 # アクションが複数あるときは、配列の形にしてあげます resources :birds, only: [:index, :new, :create] endbirds_controller.rb
formからのハッシュの形でデータが送られてきます。
全てのデータを受け取るのは危険です!
名前と写真のURLだけでいいのに、ログイン情報のキーを悪意で追加されて、他人のログイン情報を勝手に変更し乗っ取るということができてしまいます。
そこで、ストロングパラメータを使います。
また、privateを記述した行より下は、他のファイルから呼び出せないメソッドとなります。メソッドが増えたときに、見るべきファイルを減らせるメリットがあります。birds_controller.rb... def create # private下に定義したbird_paramで指定したパラメータを受け取り、保存する。 Bird.create(bird_param) end private def bird_param # params.require(:モデル名).permit(:カラム名,:カラム名,......) params.require(:bird).permit(:name, :pic) end ...create.html.erb作成
app/views/birds/create.html.erb<h3>投稿完了!</h3> <a href="/birds">一覧へ</a>今のままだと、何も入力しないで登録ができてしまいます。そこでバリデーションチェックするための記述をします。
app/models/birds.rbclass Bird < ApplicationRecord # 入力必須にしたいカラム名を書きます。 validates :name, presence: true validates :pic, presence: true endこれでからのデータを登録できなくなりました!!
削除機能
routes.rb... resources :birds, only: [:index, :new, :create, :destroy] ...削除機能へのリンクの調べかたは、まずコマンドで
rails routesとします。
すると、以下の出力がされます。
Prefixの値に「_path」をつけると、URIに記載されているURLが出力されます。
今回は削除なので、VerbにDELETEと描かれている行に注目します。Prefixは「bird」となっているので、「bird_path」とすればいいですね。メソッドは、「Verb」に「DELETE」とあるので「delete」とすれば良いですね。あとは、idも渡します!
index.html.erb... <%= bird.name %><%=link_to "削除", bird_path(bird.id), method: :delete%> ...bird_controller.rb... def destroy # 今回は抽出したデータをどこにも送らないので、@をつけません。 bird = Bird.find(params[:id]) bird.destroy end ...destroy.html.erb<a href="/birds">一覧画面</a>
- 投稿日:2020-06-27T17:27:16+09:00
【Rails】form_withを使ったフォロー機能の実装手順を解説します
概要
form_withを使ってフォロー機能を実装する手順を書いていきます!
以下の機能を実装していきます
1.ユーザーをフォロー/フォロー解除できる機能
2.フォローユーザー/フォロワーの一覧表示機能Railsでフォロー機能を作る方法の記事の方を参考にしており、特にフォロー機能に関するアソシエーションの詳しい解説などはこの記事が大変参考になりました!
前提
環境
・Rails 5.2.4.2
・Ruby 2.6.5
・Slim
・devise加えて、User系機能が実装されていることが前提となります。
上記の環境でのRailsアプリケーションのセットアップ方法
・Railsアプリケーションをセットアップ後にdeviseとSlimを導入する手順↓実装後はこんな感じになります。(見栄えが簡素ですみません…)↓
フォロー/フォロー解除機能の実装
1.Relationshipモデル作成
$ rails g model Relationship user:references follow:references・ここで作成される
relationshipsテーブル
が、フォローするユーザー&フォローされるユーザーにとっての中間テーブルとなる。・
user
をフォローする側のユーザーモデル、follow
をフォローされる側のユーザーモデルとして、中間テーブルには認識させます。
2.relationshipsマイグレーションファイルの編集
db/migrate/[timestamps]_create_relationships.rbclass CreateRelationships < ActiveRecord::Migration[5.2] def change create_table :relationships do |t| t.references :user, foreign_key: true t.references :follow, foreign_key: { to_table: :users } t.timestamps t.index [:user_id, :follow_id], unique: true end end end・userとfollowでそれぞれ参照先のモデルを分けているのは、
フォローする側のユーザ
とフォローされる側のユーザー
とでは別々のモデルとして考える必要があるからです。・
t.references :user, foreign_key: true
:userモデルに対する外部キーを張っています。・
t.references :follow, foreign_key: { to_table: :users }
:followモデルに対する外部キーを張っています。followモデルというのは実在しない架空のモデル名で、今この時勝手に作成してます。よって、{ to_table: :users }とする事で、参照元のモデルを教えてあげています。・
t.index [:user_id, :follow_id], unique: true
:user_idとfollow_idの組み合わせに一意性を持たせることでデータの重複を防ぎます、つまり同じユーザーを2度フォローされる事を防いています。
3.DBの内容を保存
$ rails db:migrate
4.RelationshipモデルにUserに対するアソシエーションを記述する。
app/models/relationship.rbclass Relationship < ApplicationRecord belongs_to :user belongs_to :follow, class_name: "User" validates :user_id, presence: true validates :follow_id, presence: true end・
belongs_to :user
:これはいつも通りのアソシエーションです。・
belongs_to :follow, class_name: "User"
:followクラスに所有される事を記述していますが、上述したようにfollowは架空のクラスですので、class_name: "User"
によって参照元のモデルを教えてあげます。
5.UserモデルファイルにRelationshipに対するアソシエーションを記述する。
app/models/user.rbclass User < ApplicationRecord #==============あるユーザーがフォローしているユーザーとのアソシエーション================= has_many :relationships, foreign_key: "user_id", dependent: :destroy has_many :followings, through: :relationships, source: :follow #========================================================================== #==============あるユーザーをフォローしてくれてるユーザーとのアソシエーション================ has_many :passive_relationships, class_name: "Relationship", foreign_key: "follow_id", dependent: :destroy has_many :followers, through: :passive_relationships, source: :user #=========================================================================== end・上記のRelationshipモデルファイルでは、
あるユーザーがフォローしているユーザーにアクセスするためのアソシエーション
と、あるユーザーがフォローされているユーザーにアクセスするためのアソシエーション
を記述しています。
つまりどういうことか、詳しくは図で後述します。5-1.まずは、あるユーザーがフォローしているユーザーとのアソシエーションの解説です!
・
has_many :relationships, foreign_key: "user_id", dependent: :destroy
:これは、あるUserが中間テーブルrelationshipsの外部キーuser_idにアクセスする事を可能にするアソシエーション
を宣言をしています。以下のようにイメージすると分かり易いかと思います!
・
has_many :followings, through: :relationships, source: :follow
:これは、あるUserが中間テーブルrelationshipsのfollow_idを通して、followingモデルにアクセスする事を可能にするアソシエーションを宣言をしています。イメージで言うと以下のような感じです!
・上記の2行により、
User.followings
とする事でUserがフォローしているユーザー達を取得できるようになります。これが取得できるようになると、あるUserのフォローユーザーの一覧表示などが簡単に行うことができます。5-2.次は、あるユーザーをフォローしてくれているユーザーとのアソシエーションの解説です!
・
has_many :passive_relationships, class_name: "Relationship", foreign_key: "follow_id", dependent: :destroy
:これは、あるUserがpassive_relationshipsのfollow_idへアクセスする事を可能にするアソシエーションを宣言をしています。
passive_relationshipsは、この場で勝手に作った架空のモデルなので、class_name: "Relationship"として参照元のモデルを教えています。イメージは以下の通りです!
・
has_many :followers, through: :passive_relationships, source: :user
:これは、あるUserがpassive_relationshipsのuser_idを通してfollowersへアクセスする事を可能にするアソシエーションの宣言をしています。イメージは以下の通りです!
・上記の2行により、User.followersとすれば、Userをフォローしてくれているユーザー達を取得することが可能になります。これを使えば、あるユーザーをフォローしてくれているユーザーの一覧表示などが簡単に行えるようになります!
6.Userモデルファイルに、フォロー関連のインスタンスメソッドを定義する
app/models/user.rbclass User < ApplicationRecord . . . #<アソシエーション関連の記述省略> . . . def following?(other_user) self.followings.include?(other_user) end def follow(other_user) unless self == other_user self.relationships.find_or_create_by(follow_id: other_user.id) end end def unfollow(other_user) relationship = self.relationships.find_by(follow_id: other_user.id) relationship.destroy if relationship end end・
following?(other_user)
:User.followings.include?(@user)
などとすることで、Userが@userのことをフォローしてるかどうかを確かめます。フォローボタン実装の際に、フォローするボタンを表示するのか、それともフォローを解除するボタンを表示するのかを条件分岐させるために使います。・
follow(other_user)
:User.follow(@user)
とすることで、@userをフォローすることができるようにします。unless self == other_user
で、自分のことをフォローできないようにしてます。find_or_create_byを使って、@userのidレコードが存在する場合はそれを参照し、なければ作成するようにしてます。・
unfollow(other_user)
:User.unfollow(@user)
とする事で、@userのフォローを解除できるようにします。・ユーザーをフォローするメソッド、フォロー解除するメソッドの定義ができたので、次はこれらのメソッドを使って実際にDBへアクセスしてフォロー・フォロー解除する機能をrelationshipsコントローラを作成して、実装していきます!
7.relationshipsコントローラを作成する。
$ rails g controller relationshipsapp/controllers/relationships_controller.rbclass RelationshipsController < ApplicationController before_action :set_user def create following = current_user.follow(@user) if following.save flash[:success] = "ユーザーをフォローしました" redirect_to @user else flash.now[:alert] = "ユーザーのフォローに失敗しました" redirect_to @user end end def destroy following = current_user.unfollow(@user) if following.destroy flash[:success] = "ユーザーのフォローを解除しました" redirect_to @user else flash.now[:alert] = "ユーザーのフォロー解除に失敗しました" redirect_to @user end end private def set_user @user = User.find(params[:relationship][:follow_id]) end end・relationshipsコントローラでは、ユーザーをフォローするcreateアクション、フォローを解除するdestroyアクションしか機能しないので、createアクション、destroyアクションだけを記述します。
・フォロー/フォロー解除ボタンフォームからは、params[:relationship][:follow_id]と言う形でデータが送信される
ので、find(params[:relationships][:follow_id])と言う形でデータを受け取ります。・
before_action :set_user
:それぞれのアクションでは必ず@userを取得する事になるので、set_userプライベートメソッドを定義してからbefore_actionを使ってあらかじめ取得させています。・
createアクション
:ログインしているユーザー(current_user)が、取得した@userをフォローしています。Userモデルファイルで定義したfollow(other_user)インスタンスメソッドを使用しています。・
destroyアクション
:ログインしているユーザーが、取得したユーザーのフォローを解除しています。Userモデルファイルで定義したunfollow(other_user)インスタンスメソッドを使用しています。・実際にDBへアクセスしてフォロー・フォロー解除する機能が仕上がったので、次は実際に
フォロー・フォロー解除するためのボタン
の実装を行います!
8.フォロー/フォロー解除ボタンをform_withで実装する。
・始めに、app/viewsディレクトリ配下に、relationships/_follow_form.html.slimファイルを作成してください。
app/views/relationships/_follow_form.html.slim- unless current_user == user #フォロー解除ボタン - if current_user.following?(user) = form_with model: @relationship, url: relationship_path, method: :delete, local: true do |f| = f.hidden_field :follow_id, value: user.id = f.submit "フォローを解除する" #フォローボタン - else = form_with model: @set_relationship, url: relationships_path, local: true do |f| = f.hidden_field :follow_id, value: user.id = f.submit "フォロー"・
- unless current_user == user
:自分自身のことをフォローできないよう、ボタン自体の表示を切り替えています。ここでのuserとは、このパーシャルを配置するビューが取得する@userのことを指します。8-1.フォロー解除ボタンの解説
・
- if current_user.following?(user)
:ログインユーザーが相手ユーザーをフォローしているかどうかを確かめています。フォローしていればフォロー解除ボタンを表示し、フォローしていなければフォローボタンを表示するようにしています。・
= form_with model: @relationship, url: relationship_path, method: :delete, local: true do |f|
:こちらはフォロー解除用のボタンです。
model: @relationship
の@relationshipはインスタンス変数で、ログインユーザーと相手ユーザーとのRelationshipを取得しています。
(app/views/users/show.html.slimにこのフォローボタンのフォームを配置するなら、app/controllers/users_controller.rbファイルのshowアクションに、@relationshipインスタンス変数を定義する事になります。)
url: relationship_path
は、relationshipsコントローラのdestroyアクションへのルーティングです。ルーティングの記述はあとで行います。
method: :delete
では、HTTPリクエストでDELETEメソッドを指定しています。
local: true
は、これを付けないとフォームの送信の仕様がAjaxになり、データを送信できなくなるのでform_withでは必ず記述します。・
f.hidden_field :follow_id, value: user.id
:この部分は、実際に完成形のソースコードを見てみるとわかりやすいです。__
:follow_id
を指定することで、params[:relationship][:follow_id]と言う形でデータが送信されます。relationshipsコントローラのset_userプライベートメソッドで定義した部分では、このデータを受け取っています。
value: user.id
を指定することで、:follow_idにフォローしている相手ユーザーのidが格納されて、データが送信されます。8-2.フォローボタン
・
= form_with model: @set_relationship, url: relationships_path, local: true do |f|
:相手ユーザーをフォローするためのフォームです。
model: @set_relationship
の@set_relationshipインスタンス変数では空のモデルを生成しており、この空のモデルを参照して、params[:relationship][:follow_id]と言う形でデータが送信されるようにします。
url: relationships_path
は、relationshipsコントローラのcreateアクションへのルーティングです。ルーティングの記述は後で行います。・
= f.hidden_field :follow_id, value: user.id
:これも実際の完成後のソースコードを確認してみます。フォロー解除ボタンと同じで、params[:relationship][:follow_id]と言う形でデータが送信されてます。
・フォロー/フォロー解除ボタンの作成が完了しましたので、次はこのデータが正常にアクションへ送られるようルーティングを設定します!
9.relationshipsコントローラへのルーティングを追加する。
config/routes.rbRails.application.routes.draw do . . #<他のルーティングは省略> . . resources :relationships, only: [:create, :destroy]・
$ rails routes | grep relationship
コマンドで、追加されたルーティングを確認してみます。$ rails routes | grep relationship relationships POST /relationships(.:format) relationships#create relationship DELETE /relationships/:id(.:format) relationships#destroy・これで
relationships_path
でフォロー/relationship_path
でフォロー解除できるようになってるのが確認できたかと思います。
10.フォロー/フォロー解除ボタンを配置する。
・相手ユーザーのページに飛んだ際にフォローしたり、フォロー解除できるようにする場合を考えて、app/views/users/show.html.slimファイルに配置していきたいと思います。
app/views/users/show.html.slimh1 ユーザープロフィールページ p = "名前 : " = @user.username #================フォローボタンの追加============================= = render 'relationships/follow_form', user: @user #============================================================ p= link_to "プロフィール編集", edit_user_path(current_user)・user: @user__:パーシャルに記述したuserが、showアクションで定義されている@userを参照しています。__
・ボタンの配置はできましたが、このままではボタンは機能しません。先ほども述べたように、@relationshipインスタンス変数と、@set_relationshipインスタンス変数を、showアクションに定義してあげなければならないからです。
11.app/controllers/users_controller.rbのshowアクションに、インスタンス変数を定義する。
app/controllers/users_controller.rbclass UsersController < ApplicationController . . . def show @user = User.find(params[:id]) @relationship = current_user.relationships.find_by(follow_id: @user.id) @set_relationship = current_user.relationships.new end . . . end・
@relationship = current_user.relationships.find_by(follow_id: @user.id)
:フォロー解除フォームで参照しているインスタンス変数です。ここでcurrent_userと@userとのrelationshipsを取得することで、フォームにてparams[:relationship][:follow_id]のようにデータを送信することができるようになります
。・
@set_relationship = current_user.relationships.new
:フォローするフォームで参照しているインスタンス変数です。params[:relationship][:follow_id]と言う形にしてデータを送信したいので、このように空のインスタンス変数を生成してます。・以上で、ユーザーをフォロー/フォロー解除する機能の実装が完了しました!
次は、フォローしているユーザー/フォローしてくれているユーザーを一覧で表示する機能を実装していきます!
フォローユーザー/フォロワーの一覧表示機能
1.始めにフォローユーザー/フォロワーの一覧ページへのリンクをビューに作成する
・app/views/users/show.html.slimに、そのユーザーのフォローユーザー/フォロワーの一覧ページへのリンクを追加します。
app/views/users/show.html.slimh1 ユーザープロフィールページ p = "名前 : " = @user.username #==============フォロー/フォロワー一覧ページへのリンク================= = link_to "フォロー: #{@user.followings.count}", followings_user_path(@user.id) = "/" = link_to "フォロワー: #{@user.followers.count}", followers_user_path(@user.id) #============================================================ = render 'relationships/follow_form', user: @user p= link_to "プロフィール編集", edit_user_path(current_user)・フォローユーザー/フォロワーへのアクセスは、先ほどUserモデルファイルで定義したfollowings/followersを使います。
・
@user.followings.count
:ユーザーのフォローしているユーザーの数を表示してます。
・followings_user_path(@user.id)
:URLがusers/:id/followings
となるパスを指定したいので、左記のように記述します。この形のパスを指定できるように、ルーティングの記述を後で行ってあげます。・フォロワー一覧ページへのアクセスも、フォローユーザー一覧ページへアクセスするのと同じような方法で記述しています。
2.フォロー/フォロワー一覧ページへのルーティングを追加する。
config/routes.rbRails.application.routes.draw do . . . resources :users do get :followings, on: :member get :followers, on: :member end . . . end・上記のように記述したら
$ rails routes | grep follow
コマンドでルーティングを確認してみます。$ rails routes | grep follow followings_user GET /users/:id/followings(.:format) users#followings followers_user GET /users/:id/followers(.:format) users#followers・
followings_user_path
はフォローユーザー一覧のページへ、followers_user_path
はフォロワー一覧ページへ飛ぶようになったので、これでOKです。・followingsアクションも、followersアクションもusersリソースにネストさせたので、usersコントローラで2つのアクションを定義します。
3.usersコントローラにfollowingsアクション、followersアクションを追加する。
app/controllers/users_controller.rbclass UsersController < ApplicationController . . . def followings @user = User.find(params[:id]) @users = @user.followings.all end def followers @user = User.find(params[:id]) @users = @user.followers.all end . . .・followingsアクション内では、@userのフォローしているユーザー全てを、followersアクション内では、@userのフォロワー全てを取得しています。
4.フォローユーザー/フォロワー一覧を表示するビューを作成する。
・app/views/usersディレクトリに、
followings.html.slim
ファイルとfollowers.html.slim
ファイルを作成します。app/views/users/followings.html.slimh2 フォローしている方々 - @users.each do |user| hr = "username: " = link_to user.username, user_path(user.id)app/views/users/followers.html.slimh2 フォロワーの皆さん - @users.each do |user| hr = "username: " = link_to user.username, user_path(user.id)・以上で、フォローユーザー/フォローユーザー一覧ページの作成が完了しました!
参考にさせて頂いた記事
- 投稿日:2020-06-27T16:28:23+09:00
[Rails]ローカル環境の変更が本番環境に反映されない件
ローカル環境の変更が本番環境に反映されない
①ローカル環境でコードを変更
②localhost:3000で確認(問題なし)
③変更内容をコミットしてGitHubにプッシュ
④自動デプロイを実行
⑤本番環境にて変更を確認するが反映されていないなぜだろう...?
解決方法
④の自動デプロイを実行する前にUnicornをkillしなければならなかった。
なのでEC2サーバー内の対象アプリのリポジトリに移動し、ps aux | grep unicornを実行。
次にunicorn masterの行の2列目の数字列をコピーし、
EC2サーバー内の対象アプリのリポジトリでkill 'コピーした数字列'を実行。するとUnicornが停止するので改めて自動デプロイを実行。
そうするとローカル環境の変更が本番環境にも反映されます!手順をまとめると▼
①ローカル環境でコードを変更
②localhost:3000で確認(問題なし)
③変更内容をコミットしてGitHubにプッシュ
④EC2サーバの対象アプリのリポジトリに移動
⑤ユニコーンをkill
⑥自動デプロイを実行よかったら参考にしてください!
- 投稿日:2020-06-27T16:26:49+09:00
[Rails] ヘルパーメソッドform_withについて[基礎]
学習中に理解が浅かったところなのでアウトプットしながら整理したいと思います。
基礎から丁寧に書いていきます。もし指摘あればお願いいたします。ヘルパーメソッドとは
そもそもrailsでは、viewでHTMLタグを出現させたりテキストを加工するためのメソッドが予め用意されています。これらをヘルパーメソッドといいます。
form_withはヘルパーメソッドの一種です。*ヘルパーメソッドの一例
ヘルパーメソッド 使用用途
form_tag 投稿ページなどにおけるフォームの実装
link_to リンクの実装
simple_format 投稿した文章を自動で見やすく整形する
submit_tag submit機能をつけたいときに使う。
text_field_tag
などなど、、
自作することも可能らしいです。
【参考記事】
https://qiita.com/Yukaaaah/items/19e524fd0c0e4a3451f1form_withについて
Rails 5.1というバージョンから推奨されているフォーム実装のためのヘルパーメソッドです。
form_tag/form_forは非推奨となっているらしいです。(この2つのメソッドについては説明を省略します。)<!-- form_tagを使用した例 --> <%= form_tag('/posts', method: :post) do %> <input type="text" name="content"> <input type="submit" value="投稿する"> <% end %><!--form_withを使用した例--> <%= form_with model: @post, local: true do |form| %> <%= form.text_field :content %> <%= form.submit '投稿する' %> <% end %>form_withの特徴としては、
①自動でパスを選択してくれて、HTTPメソッドを指定する必要が無いこと
②コントローラーから渡された、ActiveRecordを継承するモデルのインスタンスが利用できること(上記では@postがそれに該当)またこの場合は、
①新規投稿の場合
②既存の投稿を呼び出した場合
で処理が変わってきます。①新規投稿の場合
posts_controller.rbdef new @post = Post.new end投稿ボタンをクリックしたらcreateアクションに送られます。
new.html.erb<%= form_with model: @post, class: :form, local: true do |form| %> <%= form.text_field :title, placeholder: :タイトル, class: :form__title %> <%= form.text_area :content, placeholder: :ブログ本文, class: :form__text %> <%= form.submit '投稿する', class: :form__btn %> <% end %>②既存の投稿を呼び出した場合
posts_controller.rbdef edit @post = Post.find(params[:id]) endedit.html.erb<%= form_with model: @post, class: :form, local: true do |form| %> <%= form.text_field :title, placeholder: :タイトル, class: :form__title %> <%= form.text_area :content, placeholder: :ブログ本文, class: :form__text %> <%= form.submit '投稿する', class: :form__btn %> <% end %>投稿ボタンをクリックしたらupdateアクションに送られます。
まとめ
比較してみるとnew.html.erbとedit.html.erbのフォーム部分は同じです!!!
そのためフォーム部分を部分テンプレート化できて記述量を減らせます。
モデルの@postの中身があるかどうかで自動で判断して送ってくれるのです。このほかにも
例えばform_with model: [@post, @comment]のように複数モデルを渡すことができます。
それは別記事で書ければと思います、、
- 投稿日:2020-06-27T16:18:25+09:00
rails db:〇〇 まとめ 随時更新
rails db:create
DBを作成
rails db:drop
DBを削除
rails db:migrate
DBにmigrationファイルの実行
自動的に db:schema:dump も実行され、schema.rbも更新されるrails db:seed
テーブルに初期データが追加
- 投稿日:2020-06-27T15:06:57+09:00
調べる力 各方法まとめ プロジェクト内とGemで定義されている場合
動機
新しいプロジェクトに参加した時、もうメソッドだらけでどこに定義されているか調べることにかなり苦労しました。早くキャッチアップするためには、「早く調べて理解する力」が非常に重要と感じまとめてみました。
調べ方も一長一短あります。プロジェクト内で定義されているメソッドの場合
1.
git grep -n <メソッド名>
- エディタの全文検索より、ターミナルで色付きで表示されるので見やすいです
- -n オプションで行番号がつくので、コマンド + パスクリックでエディタで開きます!
- デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とすると多少絞られる。
2. ブラウザでGithubの検索窓に入力し、"in this repository"で検索
- この方法は1.と結果は同じなのですが、マッチした箇所の上下数行もまとめて表示されます。
- エディタを使いたくない時にいいです
- デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とダブルクオーテーションをいれると絞られる
3. pry-docsのshow-source機能を使う
- Railsコンソールを開き、
$ <メソッド名>
ORshow-source <メソッド名>
- 定義箇所のdefからendまでを表示してくれます!
- パスも出るので、コマンド + クリックでエディタで表示できます。
- デメリット:user.method を調べたい時、Userインスタンスを作成してからでないと調べられないので手間。
4. Pryの"step"機能を使う
- binding.pryで停止した時に、stepを実行すると、そのメソッド内に"入る"ことができます。
- 処理の流れと変数の定義も見ることができ、深い理解ができます。
- Gemなど深いところも見れます。
- デメリット:binding.pryの設置と、処理を走らせ止めることがめんどくさい。
Gemなどプロジェクト外で定義されている場合
1. Dashで検索する
- Dashとは、素のRuby、Gem、JavaScriptなど色んなドキュメントの横断検索ができるツールです。
- ソースコードに加えて、そのメソッドの説明付きなので理解も早くなります。
- VSCodeに拡張機能"Dash"をいれることで、コマンド + H でDash検索に飛べます
- デメリット:たまに調べたいGemがなかったりする
2.
bundle show <gem名>
- Gemのインストールされたディレクトリが表示されるので、VSCodeならコマンド + クリックで別ウィンドウで開くことができます。
- デメリット:gitやpryは使えないので、エディタの横断検索でメソッドを見つける必要があります。
3. Pryの"step"機能を使う
- プロジェクト内で定義されているメソッドの場合と同じです。
4. ブラウザでGithubの検索窓に入力し、"in this repository"で検索
- プロジェクト内で定義されているメソッドの場合と同じです。
その他
1. Rubymineの定義元ジャンプを使う
- VSCode使用者なので使ったことないです。が、RubyやRails、Gem内の定義ならDashでほぼまかなえる気がします。
- デメリット:高い、遅い
2. VSCodeの拡張機能 Solargraphを使う
- Rubyメソッドの上にカーソルを載せるだけで、そのドキュメントや使用例が表示されます。
- 補完機能もあり
- デメリット:Dockerを使用する場合は辛い。SolargraphはそのLanguage serverを起動させ続ける必要がある。Solargrapコンテナを立ち上げ、Portの設定をVSCodeにする必要がある。参考:Docker環境でsolargraphを使う方法
最後に
- 皆様の「調べ方」が知りたいです。
- 他に良い方法があれば、コメントにて教えてくださいm(_ _)m
- 投稿日:2020-06-27T15:06:57+09:00
調べる力 各方法まとめ プロジェクト内とRails/Gem内で定義されている場合
動機
新しいプロジェクトに参加した時、もうメソッドだらけでどこに定義されているか調べることにかなり苦労しました。早くキャッチアップするためには、「早く調べて理解する力」が非常に重要と感じ、先輩エンジニアにも聞きながらまとめてみました。
調べ方も一長一短あります。プロジェクト内で定義されているメソッドの場合
1.
git grep -n <メソッド名>
- エディタの全文検索より、ターミナルで色付きで表示されるので見やすいです
- -n オプションで行番号がつくので、コマンド + パスクリックでエディタで開きます!
- デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とすると多少絞られる。
2. ブラウザでGithubの検索窓に入力し、"in this repository"で検索
- この方法は1.と結果は同じなのですが、マッチした箇所の上下数行もまとめて表示されます。
- エディタを使いたくない時にいいです
- デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とダブルクオーテーションをいれると絞られる
3. pry-docsのshow-source機能を使う
- Railsコンソールで、
$ <メソッド名>
ORshow-source <メソッド名>
- 定義箇所のdefからendまでを表示してくれます!
- パスも出るので、コマンド + クリックでエディタで表示できます。
- デメリット:user.method を調べたい時、Userインスタンスを作成してからでないと調べられないので手間。
4. Pryの"step"機能を使う
- binding.pryで停止した時に、stepを実行すると、そのメソッド内に"入る"ことができます。
- 処理の流れと変数の定義も見ることができ、深い理解ができます。
- Rails/Gemなど深いところも見れます。
- デメリット:binding.pryの設置と、処理を走らせ止めることがめんどくさい。
Gemなどプロジェクト外で定義されている場合
1. Dashで検索する
- Dashとは、素のRuby、Rails, Gem、JavaScriptなど色んなドキュメントの横断検索ができるツールです。
- ソースコードに加えて、そのメソッドの説明付きなので理解も早くなります。
- VSCodeに拡張機能"Dash"をいれることで、コマンド + H でDash検索に飛べます
- デメリット:たまに調べたいGemがなかったりする
2.
bundle show <gem名>
- Gemのインストールされたディレクトリが表示されるので、VSCodeならコマンド + クリックで別ウィンドウで開くことができます。
- デメリット:gitやpryは使えないので、エディタの横断検索でメソッドを見つける必要があります。
3. Pryの"step"機能を使う
- プロジェクト内で定義されているメソッドの場合と同じです。
4. ブラウザでGithubの検索窓に入力し、"in this repository"で検索
- プロジェクト内で定義されているメソッドの場合と同じです。
その他
1. Rubymineの定義元ジャンプを使う
- VSCode使用者なので使ったことないです。が、RubyやRails、Gem内の定義ならDashでほぼまかなえる気がします。
- デメリット:高い、遅い
2. VSCodeの拡張機能 Solargraphを使う
- Rubyメソッドの上にカーソルを載せるだけで、そのドキュメントや使用例が表示されます。
- 補完機能もあり
- デメリット:Dockerを使用する場合は辛い。SolargraphはそのLanguage serverを起動させ続ける必要がある。Solargrapコンテナを立ち上げ、Portの設定をVSCodeにする必要がある。参考:Docker環境でsolargraphを使う方法
最後に
- 皆様の「調べ方」が知りたいです。
- 他に良い方法があれば、コメントにて教えてくださいm(_ _)m
- 投稿日:2020-06-27T15:06:57+09:00
メソッドの定義場所 調べる方法まとめ プロジェクト内とRails/Gem内で定義されている場合
動機
新しいプロジェクトに参加した時、もうメソッドだらけでどこに定義されているか調べることにかなり苦労しました。早くキャッチアップするためには、「早く調べて理解する力」が非常に重要と感じ、先輩エンジニアにも聞きながらまとめてみました。
調べ方も一長一短あります。プロジェクト内で定義されているメソッドの場合
1.
git grep -n <メソッド名>
- エディタの全文検索より、ターミナルで色付きで表示されるので見やすいです
- -n オプションで行番号がつくので、コマンド + パスクリックでエディタで開きます!
- デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とすると多少絞られる。
2. ブラウザでGithubの検索窓に入力し、"in this repository"で検索
- この方法は1.と結果は同じなのですが、マッチした箇所の上下数行もまとめて表示されます。
- エディタを使いたくない時にいいです
- デメリット:あくまで文字列検索。かなり沢山ヒットしたりする。 "def メソッド名"とダブルクオーテーションをいれると絞られる
3. pry-docsのshow-source機能を使う
- Railsコンソールで、
$ <メソッド名>
ORshow-source <メソッド名>
- 定義箇所のdefからendまでを表示してくれます!
- パスも出るので、コマンド + クリックでエディタで表示できます。
- デメリット:user.method を調べたい時、Userインスタンスを作成してからでないと調べられないので手間。
4. Pryの"step"機能を使う
- binding.pryで停止した時に、stepを実行すると、そのメソッド内に"入る"ことができます。
- 処理の流れと変数の定義も見ることができ、深い理解ができます。
- Rails/Gemなど深いところも見れます。
- デメリット:binding.pryの設置と、処理を走らせ止めることがめんどくさい。
Gemなどプロジェクト外で定義されている場合
1. Dashで検索する
- Dashとは、素のRuby、Rails, Gem、JavaScriptなど色んなドキュメントの横断検索ができるツールです。
- ソースコードに加えて、そのメソッドの説明付きなので理解も早くなります。
- VSCodeに拡張機能"Dash"をいれることで、コマンド + H でDash検索に飛べます
- デメリット:たまに調べたいGemがなかったりする
2.
bundle show <gem名>
- Gemのインストールされたディレクトリが表示されるので、VSCodeならコマンド + クリックで別ウィンドウで開くことができます。
- デメリット:gitやpryは使えないので、エディタの横断検索でメソッドを見つける必要があります。
3. Pryの"step"機能を使う
- プロジェクト内で定義されているメソッドの場合と同じです。
4. ブラウザでGithubの検索窓に入力し、"in this repository"で検索
- プロジェクト内で定義されているメソッドの場合と同じです。
その他
1. Rubymineの定義元ジャンプを使う
- VSCode使用者なので使ったことないです。が、RubyやRails、Gem内の定義ならDashでほぼまかなえる気がします。
- デメリット:高い、遅い
2. VSCodeの拡張機能 Solargraphを使う
- Rubyメソッドの上にカーソルを載せるだけで、そのドキュメントや使用例が表示されます。
- 補完機能もあり
- デメリット:Dockerを使用する場合は辛い。SolargraphはそのLanguage serverを起動させ続ける必要がある。Solargrapコンテナを立ち上げ、Portの設定をVSCodeにする必要がある。参考:Docker環境でsolargraphを使う方法
最後に
- 皆様の「調べ方」が知りたいです。
- 他に良い方法があれば、コメントにて教えてくださいm(_ _)m
- 投稿日:2020-06-27T14:55:36+09:00
[Rails]本番環境(EC2)でエラーログを見る方法
エラーログとは
エラーログとはエラーが発生した場合にその情報を記録している場所のことです。
ローカル環境のエラーログ 確認方法
Railsではエラーが発生した場合、下記に添付している画像のようなエラー画面が発生する。
これはRailsの特徴の一つで、ローカル環境ではエラーログを探さなくても詳細を表示してくれます。本番環境のエラーログ 確認方法
一方、本番環境ではエラーが発生した場合、エラー情報を記録しているエラーログを確認しなければなりません。(マストではないが、エラーログを確認することは重要)
エラーログの確認方法は以下の通り▼
EC2サーバにログイン後、対象アプリのリポジトリに移動。
次に対象のリポジトリ直下のcurrentディレクトリに移動。[ec2-user@****** [対象のリポジトリ]]$ cd currencurrent直下のlogに移動▼
[ec2-user@****** current]$ cd loglogまで移動したらlsコマンドで直下のファイルを検索。すると以下のように表示される▼
[ec2-user@****** log]$ ls production.log unicorn.stderr.log unicorn.stdout.logproduction.log ▶︎ 本番環境に関するエラー情報が記録されている。
unicorn.stderr.log ▶︎ unicornの起動時にエラーが発生した場合にエラー情報が記録される。下記コードを実行すると対処のファイルへ移動し、エラーログを確認できる。
[ec2-user@****** log]$ tailf '対象のログ'
- 投稿日:2020-06-27T13:03:09+09:00
【RAILS】エラー対応記録-herokuデプロイ時「Uglifier::Error: Unexpected token name «of», expected punc «;». To use ES6 syntax,…」
ローカル環境でjavascriptを実装して、herokuの本番環境にデプロイした際に、エラーが出て対応したときの記録を残します。
環境
macOS Catalina 10.15.5
Ruby: 2.5.1
Rails: 5.2.4.1現象
terminal$ git push memo-space master Enumerating objects: 139, done. Counting objects: 100% (139/139), done. Delta compression using up to 16 threads Compressing objects: 100% (107/107), done. Writing objects: 100% (113/113), 15.19 KiB | 3.80 MiB/s, done. Total 113 (delta 71), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: ... remote: Tasks: TOP => assets:precompile remote: (See full trace by running task with --trace) remote: remote: ! remote: ! Precompiling assets failed. remote: ! remote: ! Push rejected, failed to compile Ruby app. remote: remote: ! Push failed remote: Verifying deploy... remote: remote: ! Push rejected to memo-space. remote: To https://git.heroku.com/memo-space.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'https://git.heroku.com/memo-space.git'heroku Build Log
Bundled gems are installed into `./vendor/bundle` Bundle completed (3.47s) Cleaning up the bundler cache. -----> Installing node-v10.15.3-linux-x64 -----> Detecting rake tasks -----> Preparing app for Rails asset pipeline Running: rake assets:precompile rake aborted! Uglifier::Error: Unexpected token name «of», expected punc «;». To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true). -- 51469 var month = d.getMonth() + 1; 51470 var day = d.getDate(); 51471 var hour = ( d.getHours() < 10 ) ? '0' + d.getHours() : d.getHours(); 51472 var min = ( d.getMinutes() < 10 ) ? '0' + d.getMinutes() : d.getMinutes(); 51473 var moment_end = year+"-"+month+"-"+day+" "+hour+":"+min; 51474 var end_time = moment(moment_end).add(-9, 'hour').format("YYYY-MM-DD HH:mm"); 51475 var cookies = document.cookie; 51476 var cookiesArray = cookies.split(';'); => for (var c of cookiesArray){ 51478 var cArray = c.split('='); 51479 if (cArray[0] == " user_id"){ 51480 var user_id = cArray[1] 51481 } 51482 } 51483 var data = { 51484 event: { 51485 title: title, ==Running: rake assets:precompile からの
rake aborted! からの
Uglifier::Error: Unexpected token name «of», expected punc «;». To use ES6 syntax, harmony mode must be enabled with Uglifier.new(:harmony => true). と出ています。メッセージを調べると、デプロイしたjavascriptの仕様(ES6)にrailsが対応してコンパイルするためには、harmony modeを有効にしてね。ということらしいです。
参考情報を参考に以下のように対応しました。
変更前
config/environments/production.rb# Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier変更後
config/environments/production.rb# Compress JavaScripts and CSS. # config.assets.js_compressor = :uglifier config.assets.js_compressor = Uglifier.new(harmony: true)再度デプロイ
terminal$ git push memo-space master Enumerating objects: 147, done. Counting objects: 100% (147/147), done. Delta compression using up to 16 threads Compressing objects: 100% (113/113), done. Writing objects: 100% (119/119), 16.29 KiB | 3.26 MiB/s, done. Total 119 (delta 74), reused 0 (delta 0) remote: Compressing source files... done. remote: Building source: remote: remote: -----> Ruby app detected ... remote: -----> Preparing app for Rails asset pipeline remote: Running: rake assets:precompile remote: I, [2020-06-27T03:30:44.728297 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/application-00e4778fee8872d97056857c240d7fb1daece9a066e9bf5801bd6075927cff8e.js remote: I, [2020-06-27T03:30:44.728919 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/application-00e4778fee8872d97056857c240d7fb1daece9a066e9bf5801bd6075927cff8e.js.gz remote: I, [2020-06-27T03:30:51.980973 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/application-f0b2b81e6c5ce3009be95d8ca8a958201d38ff5d8f2458e2102f7a093d200f57.css remote: I, [2020-06-27T03:30:51.981882 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/application-f0b2b81e6c5ce3009be95d8ca8a958201d38ff5d8f2458e2102f7a093d200f57.css.gz remote: I, [2020-06-27T03:30:51.991623 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/jquery-ui/ui-icons_444444_256x240-31d988765b4e6f56553c29588c500381dc3e6f0aa2980c8212202e5644aefd5d.png remote: I, [2020-06-27T03:30:51.992765 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/jquery-ui/ui-icons_555555_256x240-32175261daee76c82bb0edf0eea16a56421866fbc31e94f3c1d570aa114502f5.png remote: I, [2020-06-27T03:30:51.997797 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/jquery-ui/ui-icons_ffffff_256x240-350df1b7131037de20e83c5c0f3a41a770d2ac48b5762ea772b3f4a8a7b9d47a.png remote: I, [2020-06-27T03:30:51.998674 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/jquery-ui/ui-icons_777620_256x240-0b020fc6e696d88d296e7bb1f61f1eb2ad827848e2c7382a4c3e0999e702dd9b.png remote: I, [2020-06-27T03:30:51.999735 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/jquery-ui/ui-icons_cc0000_256x240-40985a64b4d5dd213fba27fcd862a1bd1b337a97674f6ff0b9ec20abcee4bc69.png remote: I, [2020-06-27T03:30:52.001638 #364] INFO -- : Writing /tmp/build_972372ee6575db82336ea12d69910b2d/public/assets/jquery-ui/ui-icons_777777_256x240-faf32007ae120c302213557626e660dd10e711c5dd4f1113d35f26dc05b78d2f.png remote: Asset precompilation completed (22.03s) ... remote: Verifying deploy... done. To https://git.heroku.com/memo-space.git 87fb9be..e4d0ecb master -> masterterminal$ heroku run rails db:migrate完了〜
参考
https://qiita.com/terufumi1122/items/27bf288414569e13e050
https://github.com/lautis/uglifier/issues/127
- 投稿日:2020-06-27T12:36:03+09:00
RailsとDockerでよく使うコマンドまとめ
docker-compose build #コンテナの作成 docker-compose up #コンテナ立ち上げ docker-compose down #コンテナをダウン ctrl+cでも止められるがserver.pidでエラーになる docker-compose stop #コンテナをストップ docker-compose up --build #docker関連のファイルの変更を反映した上に、サーバーを再起動 docker images #イメージ一覧 docker ps #動いているコンテナ一覧 docker ps -a #動いていないコンテナも含めた一覧 docker rm `docker ps -a -q` #コンテナの一括削除 docker rmi `docker images -a -q` #イメージの一括削除 mysql -u root -p -h localhost -P 3306 --protocol=tcp #DockerからMYSQLへ docker-compose run web bundle install #bundle install docker-compose run web rails db:create #db作成 docker-compose run web rails db:migrate #マイグレート以上、RailsとDockerでよく使うコマンドたちでした!
参考になれば幸いです。
間違えなどありましたらご指摘お願いします。
- 投稿日:2020-06-27T10:45:18+09:00
【Rails】ブラウザのページタイトルをページごとに変更する方法
目標
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina前提
下記実装済み。
実装
1.
application_helper.rb
を編集application_helper.rbmodule ApplicationHelper # 追記 def full_title(page_title = '') base_title = "Bookers" if page_title.empty? base_title else "#{ page_title } | #{ base_title }" end end end【解説】
◎ ベースとなるタイトル(アプリ名等)を設定し、変数へ代入する。
base_title = "Bookers"◎ 引数で受け取った各ページのタイトルが空の場合はベースタイトルのみを表示する。
if page_title.empty? base_title◎ 引数で受け取った各ページのタイトルが存在する場合は両タイトルを表示する。
else "#{ page_title } | #{ base_title }"
page_title
が「本一覧」だとすると、本一覧 | Bookers
と表示される。2.ビューを編集
①
application.html.slim
を編集する。application.html.slim/ 変更前 title | Bookers / 変更後 title = full_title(yield(:title))② 各ページのビューを編集する。
例として、
books/index.html.slim
のタイトルを設定します。books/index.html.slim/ 追記 = provide(:title, '本一覧')
- 投稿日:2020-06-27T10:08:08+09:00
【Rails】エラーメッセージを個別に表示する方法
目標
開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina前提
下記実装済み。
実装
1.
application.rb
を編集application.rbmodule Bookers2Debug class Application < Rails::Application config.load_defaults 5.2 # 追記 config.action_view.field_error_proc = Proc.new do |html_tag, instance| if instance.kind_of?(ActionView::Helpers::Tags::Label) html_tag.html_safe else class_name = instance.object.class.name.underscore method_name = instance.instance_variable_get(:@method_name) "<div class=\"has-error\">#{html_tag} <span class=\"help-block\"> #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")} #{instance.error_message.first} </span> </div>".html_safe end end end end【解説】
① エラーが出ていない場合はHTMLをそのまま表示する。
if instance.kind_of?(ActionView::Helpers::Tags::Label) html_tag.html_safe② エラーが出ている場合はエラーメッセージをフォームの下に表示する。
else class_name = instance.object.class.name.underscore method_name = instance.instance_variable_get(:@method_name) "<div class=\"has-error\">#{html_tag} <span class=\"help-block\"> #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")} #{instance.error_message.first} </span> </div>".html_safe◎ インスタンスのクラス名を変数へ代入
class_name = instance.object.class.name.underscore◎ インスタンスのメソッド名を変数へ代入
method_name = instance.instance_variable_get(:@method_name)◎ エラーメッセージ部分のHTMLを作成する。
"<div class=\"has-error\">#{html_tag} <span class=\"help-block\"> #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")} #{instance.error_message.first} </span> </div>".html_safe「タイトルを入力してください」と表示する場合、
#{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")}
が、
「タイトル」にあたる部分で、
#{instance.error_message.first}
が、
「を入力してください」にあたる部分になる。2.エラーメッセージを日本語化
① Gemを導入
Gemfile# 追記 gem 'rails-i18n'ターミナル$ bundle②
application.rb
を編集application.rbmodule Bookers2Debug class Application < Rails::Application config.load_defaults 5.2 config.i18n.default_locale = :ja # 追記 config.action_view.field_error_proc = Proc.new do |html_tag, instance| if instance.kind_of?(ActionView::Helpers::Tags::Label) html_tag.html_safe else class_name = instance.object.class.name.underscore method_name = instance.instance_variable_get(:@method_name) "<div class=\"has-error\">#{html_tag} <span class=\"help-block\"> #{I18n.t("activerecord.attributes.#{class_name}.#{method_name}")} #{instance.error_message.first} </span> </div>".html_safe end end end end③
ja.yml
を作成し、編集ターミナル$ touch config/locales/ja.ymlja.ymlja: activerecord: attributes: book: title: タイトル body: 本文
- 投稿日:2020-06-27T09:03:19+09:00
Railsチュートリアル 第1章 ゼロからデプロイまで【やってみた】
Railsチュートリアル第1章をやってみて終えたので、やったことや失敗したことを振り返ります。細かく見ていくので、チュートリアルしながらみてもらえれば嬉しいです。
※こちらの記事ではRailsチュートリアル第4版を使用しています。
現在はRailsチュートリアル第6版が出ています。
下記リリース時のnote
https://note.com/yasslab/n/n1543187c3ed6?magazine_key=md778735d3f77ちなみに細かなことですが、読む字体を明朝体かゴシック体に変更することができます。自分はゴシック体にするととても読みやすくなったので、お好みに合わせて変更すると良いかと思います。
また2章で新しいアプリを作るので、この章でデプロイできなくても大丈夫です。
1.1.1 前提知識
RailsチュートリアルでProgeteの関連講座を紹介してますが、
これは本当にやった方がいいと感じます。
第1章でコマンドラインとGitコースが紹介されていますが、
「後ででもいけるだろ」と思って結局コマンドのミスで、アプリが作り直しになったりと、大変なことになりました!
始める前にこちらのコースをすることをおすすめします。1.2.1 開発環境
クラウドIDEである、Cloud9をインストールする
1.2.2 Railsをインストールする
$ printf "install: --no-document \nupdate: --no-document\n" >> ~/.gemrc $ gem install rails -v 5.1.6 # -vでバージョンを指定 $ cd ~/environment # 'environment' ディレクトリに移動する $ rails _5.1.6_ new hello_app1.3.1 Bundler
Gemfile内にあるデフォルトの内容をバージョンを指定して記述、インストールします。
$ cd hello_app/ $ bundle install上手くいかない時は
bundle update
を実行1.3.2 rails sever
$ cd ~/environment/hello_app/ #hello_appディレクトリへ移動 $ rails server #サーバーを起動rails serverを起動した後は、このターミナル内はリアルタイムで更新されていくので、注意すること。
画面をプレビューするとRailsのぺージが!!Yay!1.3.3 Model-View-Controller
モデル・ビュー・コントローラーがそれぞれ関わっているというお話。
model: アプリケーションデータ、ビジネスルール、ロジック、関数
view: グラフや図などの任意の情報表現
controller: 入力を受け取りmodelとviewへの命令に変換する
--Wikipediaより引用ここで一つの疑問が。
RailsはこのMVCアーキテクチャパターンを採用しているということ。「このパターンを採用している」ということは他のパターンもあるということ...?調べてみました。・フォームとコントロール
・プレゼンテーション・モデル
・アプリケーション・モデル
・MVVM
・モデル・ビュー・プレゼンタ(MVP)参考記事 https://www.atmarkit.co.jp/fdotnet/chushin/greatblogentry_10/greatblogentry_10_01.html
内容は上手く理解できなかったけど、MVC以外ももちろんあるよ!ということが分かりました。
構造からもう自由なんだなと思うとプログラミングはすごい
この詳しい内容もまた勉強していきます。1.3.4 Hello,wold!
ビューも通さずHello,world!を表示させるため、以下のようなコードを記述しています。
titleapp/controllers/application_controller.rbdef hello render html: "hello, world!" endrenderメソッドは
render("フォルダ名"/"ファイル名")
のように使うと思っていましたが、こんな使い方もできるんですねRailsガイド 2.2 renderを使用する
Railsガイドによると最早何でも出力できます、みたいな勢い。ルーティングを設定してブラウザで表示させます。
1.4.1インストールとセットアップ
ここからGitでのバージョン管理ができるようにしていきます。
$ git config --global user.name "Your Name" $ git config --global user.email your.email@example.comここでの名前とメールアドレスは今後一般に公開されるので注意。
リポジトリを作成するため、以下の内容をターミナル内で記述する
$ git init #Gitの初期化 $ git add -A #現在のディレクトリにあるすべてのファイルを追加 #ファイル追加後ステージングされ、コミット待ちになる $ git status #現在のステージングの確認 $ git commit -m "Initialize repository" #リポジトリにコメント付きで反映させる $ git log #コミットメッセージの履歴を見るいきなりリポジトリとは何だろう?という感じでしたが、こちらを読んだらとても分かりやすかったです。
【イラストで覚える】初心者のためのGitとGitHub用語集1.4.3 Gitbucket
Gitbucketにソースコードをアップデートします。
他の開発者と共同作業できるのが大きなメリットです。手順の中の、「公開鍵・暗号鍵」ってなんだろう?
とりあえず言われるがまま作ってみたけどよくわかっていないので、調べてみました。インターネットを経由してデータのやりとりをする上で、情報が盗まれないようにするために暗号化が必要です。
そのために生まれたのが公開鍵暗号方式です。
この鍵はお互いが対応しています。
・公開鍵で暗号化したデータは秘密鍵(暗号鍵)でしかもとに戻せない
・秘密鍵(暗号鍵)で暗号化したデータは公開鍵でしかもとに戻せない公開鍵は誰でも見れるようになっています。
データを送信する側は公開鍵で情報を取得、暗号化して送信します。
受信側は誰にも見せていない秘密鍵(暗号鍵)で暗号化された情報を元に戻し、見ることができます。
これで第三者に情報を見られることはありません。このような方式をとっているため、情報のやりとりのために公開鍵を入れることが必要です。
参考記事
https://railstutorial.jp/chapters/beginning?version=5.1#sec-bundler1.4.4 ブランチ、編集、コミット、マージ
$ git checkout -b modify-README #一時的に使うトピックブランチを作成 $ git branch #すべてのローカルブランチを確認 $ git commit -a -m "Improve the README file" #すべてのファイルの変更を一括でコミットする $ git checkout master #masterブランチへ移動 $ git merge modify-README #masterブランチにトピックブランチmodify-READMEをマージ $ git push #プッシュする1.5.1 Herokuのセットアップ
HerokuではPostgreSQLデータベースを使う、とありますが、
PostgreSQLってなんだろう...PostgreSQL は、オープンソースのリレーショナル・データベースです。商用データベ>ースに匹敵する本格的な機能と、オープンソースならではの利用の柔軟度が魅力です。
https://lets.postgresql.jp/map/introリレーショナルデータベースは、テーブル型で、関連付けられたデータの集合ということのようです。まだまだ難しい
https://aws.amazon.com/jp/relational-database/SQLiteを加え、インストールします。
また、Herokuをインストールしてデプロイします。
$ heroku --version #Herokuがインストールされているかとバージョンの確認 $ source <(curl -sL https://cdn.learnenough.com/heroku_install) #HerokuをクラウドIDEにインストール $ heroku login --interactive $ heroku keys:add $ heroku create #Herokuに新しいアプリケーションを作る $ git push heroku master #Herokuにデプロイここで1章は終わりです。
ログを載せたかったのですが、デプロイが上手くいきませんでした。
後から考えると、ブランチを作り間違えたのと、Herokuはheroku create
で生成されたアドレスからアクセスする必要があるということをいまいち理解していなかったためだと思います。長くなってしまいましたが、ここまで読んでいただきありがとうございます。
間違いなどありましたら、教えていただけると嬉しいです。
- 投稿日:2020-06-27T07:25:57+09:00
slimでspanを挟みたくなったときの書き方
ブラウザにはこのように表示していきたいと思います。
「間」という文字をspanで間に挿入し、全て一行で表示させます。
左の文字(間)右の文字
コードは、こちらになります。
html.slimp | 左のもじ( span | 間 | )右の文字spanタグを書くときは、改行します。
そして、表示させる文字は、さらに改行し、インデントの後に「|」を書いて、その後に文字を書きます。
span以降の文字は、改行し、pタグの括りになるインデントで「|」を書き、その後に書きます。参考記事
https://stackoverflow.com/questions/13514660/nesting-a-text-inside-a-tag-in-slim
- 投稿日:2020-06-27T02:51:13+09:00
Herokuで一定期間経つとアップロードした画像が消えてしまう理由とその対処法
今回起きた問題
初めて制作したアプリをデプロイしたはいいものの、画像を投稿して一定期間経つと「あれ....画像が消えてる!?」と画像が全て消えてデータが投稿文章だけになっていました。
原因
一定時間経つとHeroku上のリポジトリ (Dyno) が最後のコミットの状態にリセットされるため、画像が保存できないとのこと。
解決法
自分はクラウドストレージを使用して解決しました。今回はfogとawsのS3と画像アップロードにCarrierWaveを使用しています。
1.fog
fogとはRubyでクラウドサービスを使いやすくするためのGemです。
まずはfogをインストールします。gemfileの以下の記述をしたら bundle installをしますgem 'fog'開発環境ではローカルファイルに画像保存で問題ありませんが、本番環境ではクラウドストレージサービス(fog)に保存するように条件分岐させます。
app/uploaders/〇〇〇〇_uploader.rbif Rails.env.production? storage :fog else storage :file end2.S3
S3はAWSのサービスの一つです。
ここでの流れは
①AWSのアカウントを作成する
②AWS Identity and Access Management (IAM)でユーザーとグループ(AmazonS3FullAccess)作成(アクセスキーとシークレットアクセスキーは後から使うのでcsvはダウンロードしておくと良い)
③作成したユーザーでログインし、サービス「S3」にてバケットを作成する
といったものです
参考記事
【AWS】【S3】作成手順 & アップロード手順 & アクセス権限設定手順3.CarrierWaveの設定
config/initializers/carrierwave.rbif Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { provider: 'AWS', aws_access_key_id: ENV['ACCESS_KEY_ID'], aws_secret_access_key: ENV['SECRET_ACCESS_KEY'], region: 'ap-northeast-1' # S3バケット作成時に指定したリージョン。 } config.fog_directory = 'food-pictures-bucket' # 作成したS3バケット名 end end上記についてファイルに直接鍵の名前を書いてしまうと悪用されることがあるので、環境変数で設定しおきましょう。
4.Herokuの環境変数設定
$ heroku config:set ACCESS_KEY_ID=アクセスキー $ heroku config:set SECRET_ACCESS_KEY=シークレットアクセスキーここまできたらターミナルで git push heroku master でデプロイしまししょう
終わりに
herokuでアップロードするだけでも他のクラウドサービスのことや秘密鍵のことについての知識が必要で大変でしたがこの方法でうまくいいきました。
この記事が少しでも参考になれば幸いです。
- 投稿日:2020-06-27T02:19:31+09:00
csvファイルのアップロードをRSpecでテストしたい
はじめに
新卒エンジニアの@yhorikawaです
csvをアップロードする機能を作っていたのですが、テストの方法がわからず苦戦したので
今後ファイルアップロード機能をテストしたいときのために備忘録として残します。controller
csv_upload.rbdef csv_upload # csv読み込み部分 csv = CSV.read(params[:csv]) # このあと保存処理 endこのような形のcontrollerにparams[:csv]といった形でcsvを渡します。
テストコード
csv_upload_request_spec.rbdescribe 'post #csv_upload' do let(:params) { { csv: fixture_file_upload('csv_file_path', 'text/csv') } } subject { post 'csv_upload', params } it 'upload_csv' do expect(subject).to be_success end endcsvファイルを
spec/fixtures/
などに保存して
fixture_file_upload('csv_file_path', 'text/csv')
にcsvファイルの相対パスを書くことで
ファイルをパラメーターとして渡すことができますおわりに
fixture_file_upload
を使うことで比較的簡単に実装することができました。
csvに限らずファイルのアップロード機能をテストしたいことはあると思うので記事を書きました。
- 投稿日:2020-06-27T00:02:41+09:00
【Redis】KEYSによるKey取得の危険性とSCANによる安全な対処
Redisにおける
KEYS
の危険性、及びSCAN
による対処をできる限り簡潔に紹介します。Redis , KEYSとは
※分かる方は飛ばしてOKです
Redisは、KVS型(Key Value Store)データベースの一つであり、オープンソース(BSDライセンス)のインメモリデータ構造ストア(ストレージではなくメインメモリで処理するもの)です。僕の知る限りWebによくあるキャッシュを保存するのに使われることが多いです。
構造は極めて単純で、ひとつの
Key
に対して一対のValue
があるというものです。キャッシュを扱う場合、Keyには「ページの部品のURL」、Valueには「CSSやJavaScriptなど」を保存します。
KEYS
は、特定のパターンにマッチするKeyを検索する手法です(Redis(KEYS))。全てのKeyとパターンを比較するため、時間計算量はO(N)
となります(Nはデータベース内のKeyの数)。つまり計算量は、保存されているKeyの数に直接影響します。以下、KEYSコマンドの例。
redis> KEYS *name* 1) "lastname" 2) "firstname" redis> KEYS a?? 1) "age" redis> KEYS * 1) "age" 2) "lastname" 3) "firstname"KEYSによる全検索の危険
While the time complexity for this operation is O(N), the constant times are fairly low. For example, Redis running on an entry level laptop can scan a 1 million key database in 40 milliseconds.
公式リファレンスRedis(KEYS)にあるように、単純な参照の処理速度は高速のようです。
問題は、保存されたKeyの数が「数百万、数千万」という膨大な数の場合に起こります。その悲劇の順序は以下の通りです。
1. KEYSのレスポンスが長くてRedisが何も返せない
Redisサーバは基本、単一の処理しか行えないシングルスレッドです。ゆえに、「数百万、数千万」という膨大な件数を参照しに行く場合、その処理が終わるまでレスポンスを返せない状態になります。
2. 他のRedisへのGETリクエストなどが詰まる
Redisが「数百万、数千万」という件数の参照を繰り返してる間にも、次々とRedisサーバに対するリクエストは増え続けます。ちなみに、もしRedisがマルチスレッド(シングルスレッドの逆で並列処理が可能)であれば、一つ重たいリクエストがあったとしても、軽い処理は次々とレスポンスされていくので最低限の動作は可能になります(後で詳しく紹介します)。
3. Redisのレスポンスを期待しているApp側(Railsなど)が詰まる
Redisはレスポンスを長時間返せないので、当然アプリケーション側は何もできない時間が増え、詰まります。
4. ユーザへリクエストを返せず、最悪の場合サーバダウン
レスポンスタイムが増えると、サーバへの負荷も増えます。結果、ユーザのリクエストに対し多くの時間を費やすことになり、最悪の場合高負荷によりサーバがダウンしてしまう危険性が高まるのです。
ちなみにこのような危険性が考慮されているため、公式リファレンスでも非推奨とされています。
Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using SCAN or sets.
SCANでカーソルベースで参照しに行く
KEYS
でのKey取得の危険性がわかったところで、解決策を考えます。先ほど軽く触れたように、マルチスレッドであれば一つの重いリクエストがあっても詰まることはありません。しかしそれは現実的に不可能なので、別のアプローチを考えます。それが、公式でも推奨されている
SCAN
という方法です。
SCAN
は、KEYS
と同じく、パターンマッチするKeyを検索する手法です。SCAN
の特徴は、参照をカーソルベースで行うという点です。これにより、参照を一括で行うのではなく、分割して参照することが可能になります。ここで言うカーソルとは「次参照する位置を示すもの」で、次のカーソルがない(参照が終わっている)場合SCAN
は"0"を返します。詳しくはRedis(SCAN)。
SCAN
コマンドの例。redis> scan 0 1) "17" 2) 1) "key:12" 2) "key:8" 3) "key:4" 4) "key:14" 5) "key:16" 6) "key:17" 7) "key:15" 8) "key:10" 9) "key:3" 10) "key:7" 11) "key:1" redis> scan 17 1) "0" 2) 1) "key:5" 2) "key:18" 3) "key:0" 4) "key:2" 5) "key:19" 6) "key:13" 7) "key:6" 8) "key:9" 9) "key:11"プログラムで実装する場合は、カーソルが"0"になるまで(参照が終わるまで)
SCAN
でリクエストを繰り返すようにします。ちなみに、2020/6/28(日)までに、「SCAN
によるKey取得をRailsで実装する方法」を紹介するので、できればフォローしてもらえるとありがたいです(投稿し次第リンクを追記します)。終わり
Redisそのもののデータ構造は単純でも、内部的な処理を調べていくと危険性も多くあるので非常に興味深いですね。
質問や編集リクエストがあればコメントにお願いします。
Greeting late
長期インターンを始めて2ヶ月目の@TsuboyaTaikiです。
現在Railsアプリの業務でRedisサーバを用いたキャッシュ周りの修正issueを担当しています。その過程で
KEYS
やSCAN
といったバリュー検索について知ったことが多くあったので書き残しておきます。