ゼロイチメモhttps://01memo.comThu, 25 May 2023 07:29:09 +0000jahourly1joinsしたいのにdefault_scopeが邪魔をするhttps://01memo.com/rails/default_scope/Thu, 25 May 2023 07:28:09 +0000https://01memo.com/?p=219

過去につくられたrailsアプリを改修していたときに出会ったdefault_scopeに悩まされた

Ruby
User.joins(:aaa_table, :bbb_table) .where.not('aaa_table.xxx_id = bbb_table.yyy_id')

これをやりたい。ただそれだけ… なのですが

aaa_tableテーブルにはdefault_scopeがいる。。

Ruby
default_scope { where(deleted_at: nil) }

こいつめ… いらぬ….

いらぬ…..

aaa_tableテーブルのdeleted_atに値があるレコードを除外するSQLが発行されてしまう..

JOIN するときに unscoped  を除外するのってRailsではあんまり想定されてなさそうです。コマッタ

そこでjoinの中身、SQLでかいちゃいました

Ruby
User.joins("INNER JOIN aaa_table ON user.aaa_table_id = aaa_table.id") .joins("INNER JOIN bbb_table ON User.bbb_table_id = bbb_table.id") .where.not('aaa_table.xxx_id = bbb_table.yyy_id')

これでちゃんとSQLが発行されているのでこの修正で良いと思います。

というかこれ以外思いつかんかった

default_scope は諸悪の根源だなぁ。。。 

]]>
Ruby | じゃんけんとあっち向いてホイhttps://01memo.com/ruby/janken/Mon, 20 Mar 2023 00:30:00 +0000https://01memo.com/?p=208ゲームのルールを理解する

まずはじめに、ゲームのルールを理解しましょう。

うさぎ
うさぎ

まずなにを書きたいか明確にしてから、コードにしていこう

じゃんけんのルール

  • グー、チョキ、パーの3つの手からランダムで出す
  • グーはチョキに勝ち、チョキはパーに勝ち、パーはグーに勝ち
  • あいこの場合は、もう一度じゃんけんをする

あっち向いてホイのルール

  • まずは、自分と相手が向きを決めます(上、下、左、右のいずれか)
  • じゃんけんで勝った方は、相手の向きを予想して「あっち向いて~」と声をかけます。
  • 自分の向きと予想した相手の向きを比べます。
  • もし予想が当たっていたら、勝ちです。当たっていなかったら、もう一度じゃんけんをします。

コードの書き方

じゃんけんのメソッドと、あっち向いてホイのメソッドをそれぞれかいて、それを呼び出そう

Ruby
# じゃんけんメソッド
def janken puts "0(グー) 1(チョキ) 2(パー) " player_hand = gets.chomp.to_i # 入力された数字をplayer_hand変数に代入 program_hand = rand(3) # ランダムな数字0~2をprogram_hand変数に代入 if player_hand >= 3 # 入力された数字が指定した数字以外だった場合 puts "0(グー) 1(チョキ) 2(パー) のいずれかを入力してください" return end jankens = ["グー", "チョキ", "パー"] puts "あなたの手:#{jankens[player_hand]}, 相手の手:#{jankens[program_hand]}" if player_hand == program_hand puts "あいこで..." return true elsif (player_hand == 0 && program_hand == 1) || (player_hand == 1 && program_hand == 2) || (player_hand == 2 && program_hand == 0) puts "あなたの勝ちです!" acchi_muite_hoi # acchi_muite_hoiメソッドの呼び出し return false else puts "あなたの負けです!" return false end
end
# あっち向いてホイメソッド
def acchi_muite_hoi puts "あっち向いてホイをしましょう!" puts "あっち向いて〜" puts "0(上) 1(下) 2(左) 3(右)" player_direction = gets.chomp.to_i program_direction = rand(4) if player_direction >= 4 # 入力された数字が指定した数字以外だった場合 puts "0(上) 1(下) 2(左) 3(右)のいずれかを入力してください" return end directions = ["上", "下", "左", "右"] puts "あなたの向き:#{directions[player_direction]}, 相手の向き:#{directions[program_direction]}" if player_direction == program_direction puts "あなたの勝ちです!" return false else puts "残念!" return false end
end
# 実行部分
puts "じゃんけん..."
janken_game = true # 初期値
while janken_game do janken_game = janken # じゃんけんメソッドの返り値がfalseになったらwhile文が終了する
end

じゃんけんメソッド、あっち向いてホイメソット部分の解説

最初に、プレイヤーが入力するためのメッセージを表示します。

プレイヤーが入力した数字を、変数「player_hand」に代入します。「gets.chomp.to_i」は、ユーザーからの入力を文字列として受け取り、整数に変換します。

コンピューターの手をランダムに選び、変数「program_hand」に代入します。「rand(3)」は、0から2の間の整数をランダムに生成します。

もしプレイヤーが0~2以外の数字を入力した場合は、エラーメッセージを表示して、このメソッドを終了します。

選択された手を配列「jankens」に格納し、それを用いて、プレイヤーとコンピューターの手を表示します。

プレイヤーの手とコンピューターの手が同じ場合は、「あいこで…」と表示し、このメソッドを再度呼びだし、あっち向いてホイメソッドの実行を行います。

実行部分の解説

まず、janken_gameという変数にtrueを初期値として代入しています。

そして、while文でjanken_gametrueである間、jankenメソッドを実行します。

jankenメソッドはじゃんけんの結果を返し、その結果によってjanken_gameの値を変更します。

janken_gamefalseになった場合、while文が終了します。

このようにして、jankenメソッドを実行してじゃんけんゲームを行い、勝敗が決まるまで繰り返し行うことができます。

]]>
MySQL | 外部キー制約のチェックを無効にする方法(SET foreign_key_checks = 0;)https://01memo.com/mysql/foreignkey/Sun, 19 Mar 2023 15:12:55 +0000https://01memo.com/?p=202
うさぎ
うさぎ

ためしにテーブルにデータを入れたいんだけど外部キーエラーでうまくいれられない

うさぎ
うさぎ

一時的に外部キーをはずしたらいいんじゃない

SET foreign_key_checks = 0;


「SET foreign_key_checks = 0;」とはMySQLのSQLコマンドの1つで、外部キー制約のチェックを無効にするために使用されます。


外部キー制約は、異なるテーブル間の関係性を定義するために使用され、参照されるテーブルのキーと参照するテーブルのキーが一致することを強制します。

この制約が有効な場合、データベースの更新や削除操作に制限が加えられ、関連するデータが正しく維持されることを保証します。


しかし、外部キー制約が無効になっている場合、「SET foreign_key_checks = 0;」コマンドを使用することで、関連するデータが正しく維持される保証はありません。

これは、データベースに誤ったデータが挿入される可能性があるためです。

通常、外部キー制約を無効にすることは推奨されませんが、いくつかの特定のシナリオで必要になる場合があります。

例えば、大規模なデータベースの更新やバッチ処理を実行する場合、外部キー制約が無効になっていることで、処理時間を短縮できる場合があります。

しかし、必要な場合を除き、外部キー制約を無効にすることは避けることが推奨されます。データベースのデータ整合性を維持するために、外部キー制約を有効にすることが重要です。

「SET foreign_key_checks = 0;」を使用する手順


MySQLクライアントを開始します。MySQLクライアントには、コマンドラインから接続する方法とGUIツールを使用する方法があります。

  • 1. データベースに接続します。データベース接続には、ユーザー名とパスワードが必要です。データベース接続方法は、以下の例のようになります。
mysql -u username -p password
# ユーザーネームがusagi、パスワードがrabbitの場合
mysql -u usagi -p rabbit
  • 2. 外部キー制約のチェックを無効にするために、「SET foreign_key_checks = 0;」コマンドを実行します。
SET foreign_key_checks = 0;

おわり!簡単です

確認方法


外部キー制約が無効になったことを確認します。以下は、外部キー制約が無効になったかどうかを確認する方法です。

SHOW VARIABLES LIKE 'foreign_key_checks';



このコマンドを実行すると、外部キー制約が有効かどうかが表示されます。

外部キー制約を有効に戻す方法


外部キー制約を有効に戻すにはSET foreign_key_checks = 1;」コマンドを実行します。

SET foreign_key_checks = 1;



以上が、「SET foreign_key_checks = 0;」を使用する手順です。ただし、外部キー制約を無効にする前に、必ずバックアップを取得することをお勧めします。また、外部キー制約を無効にしたまま、誤ったデータを挿入しないように注意してください。


]]>
Rails | attributesメソッドhttps://01memo.com/rails/attribute/Sun, 12 Mar 2023 02:48:49 +0000https://01memo.com/?p=192attributesは、Active Recordオブジェクトの属性のハッシュを返すメソッドです。これにより、Active Recordオブジェクトの属性にアクセスし、更新することができます。

以下は、簡単な例です。Userという名前のモデルがあり、その中にnameageaddressという属性があるとします。

Ruby
class User < ApplicationRecord
end

この場合、Userオブジェクトを作成し、その属性にアクセスする方法は次のとおりです。

Ruby
user = User.new(name: "John", age: 30, address: "123 Main St")

この場合、Userオブジェクトの属性は以下のようになります。

Ruby
{ "id" => nil, "name" => "John", "age" => 30, "address" => "123 Main St", "created_at" => nil, "updated_at" => nil }

このように、idcreated_at、およびupdated_atは自動的に設定されます。

次に、attributesメソッドを使用して、Userオブジェクトの属性を取得する方法を見てみましょう。

Ruby
attributes = User.attributes

この場合、attributes変数には以下のようなハッシュが格納されます。

Ruby
{ "id" => nil, "name" => "John", "age" => 30, "address" => "123 Main St", "created_at" => nil, "updated_at" => nil }

attributesを使用することで、Active Recordオブジェクトの属性に簡単にアクセスできます。例えば、personオブジェクトのname属性を変更するには、次のようにします。

Ruby
user.attributes = { name: "Jane" }

この場合、Userオブジェクトのname属性がJaneに変更されます。

]]>
git |「git pull –rebase」と「git rebase」の違いと使い方https://01memo.com/git/rebase/Sat, 11 Mar 2023 04:31:13 +0000https://01memo.com/?p=186
うさぎ
うさぎ

gitってよくわからんけど、特にrebaseがわからん

うさぎ
うさぎ

git pull rebase と git rebase なんか2種類あるしね

git pull –rebase とは

git pull –rebaseは、リモートリポジトリから最新のコミットを取得するためのコマンドです。

git pull --rebaseは、git fetchgit rebaseを組み合わせたものです。

git pull --rebaseは、リモートリポジトリから最新の変更を取得して、現在のブランチの変更とリベースすることができます。

リベースとは、履歴を整理するために、コミットの親子関係を変更することです。

具体的には、現在のブランチのコミットを最新のコミットに移動させ、その後に現在のブランチの変更を適用することで、履歴を綺麗に整理することができます。

また、共同作業している場合、他の人の変更をすばやく反映することができます。

つまり、リモートリポジトリのコミット履歴を自分の変更と一緒にまとめて、履歴を整理することができます。

git pull –rebaseの例

A — B — C (master)
\
D — E (feature)

featureブランチで作業中に、masterブランチに変更が加わった状況です。

git pull --rebase origin master

を実行!

A — B — C (master)
\
D’ — E’ (feature)

git pull --rebaseコマンドで、featureブランチの変更をmasterブランチにリベースし、新しいコミットD'E'を作成しました。

featureブランチがmasterブランチの変更を反映した状態に更新されました。

git rebase とは

git rebaseは、現在のブランチのコミットを変更することができます。

例えば、別のブランチからのコミットを現在のブランチに追加したり、コミットの順序を変更することができます。

しかし、他の人が既にそのブランチから変更を取得している場合、履歴が書き換わるため、共同作業に悪影響を与える可能性があります。git rebaseは、コミットの再ベースに使用されます。

git rebaseの例

A — B — C (master)
\
D — E (feature)

featureブランチ(下の段)で作業を続けている間に、masterブランチ(上の段)に新しい変更(C)が加わりました。

git rebase

実行!

A — B — C (master)
\
D’ — E’ (feature)

git rebaseコマンドで、featureブランチのコミット履歴をmasterブランチの最新状態にリベースしました。

DEのコミット履歴が書き換わり、D'E'が新たに作成されました。

履歴が書き換わるため、共同作業中の場合、注意が必要です。

違い

「git pull –rebase」と「git rebase」の違いは、主に以下の点です。

  • 「git pull –rebase」は、リモートリポジトリの変更を取り込み、自分の変更と一緒に一つのコミットにまとめることができます。一方、「git rebase」は、自分のブランチの変更を整理して、一つのコミットにまとめることができます。
  • 「git pull –rebase」は、リモートリポジトリと自分のブランチの差分を解決する必要があります。これにより、衝突が発生する可能性があります。一方、「git rebase」は、自分のブランチ内のコミット履歴を整理するため、衝突が発生することはありません。
  • 「git pull –rebase」は、リモートリポジトリの変更を自分の変更と統合するため、チームメンバーとの共同作業に適しています。一方、「git rebase」は、自分のブランチ内のコミット履

まとめ

「git pull –rebase」と「git rebase」は、両方ともコミット履歴を整理するために使用されますが、目的や使用方法が異なります。

「git pull –rebase」は、チームメンバーとの共同作業での変更の統合や、リモートリポジトリの変更を自分の変更と一緒にまとめるために使用され、「git rebase」は、自分の個人的な作業でのコミット履歴の整理に使用されます。

リモートにあげたあとのブランチではgit rebaseはつかわない

適切なコマンドを使用することで、コミット履歴を整理し、開発の効率を上げることができます。

]]>
Rails | orderメソッドを使ったデータの並び替え方の基本的な書き方と使い方のまとめhttps://01memo.com/rails/order/Mon, 06 Mar 2023 00:00:00 +0000https://01memo.com/?p=119orderメソッドとは

orderメソッドは、Active Recordクラスであるモデルに対して、データの並び替えを行うためのメソッドです。デフォルトでは、created_atカラムが昇順で並び替えられますが、orderメソッドを使用することで、任意のカラムや条件で並び替えを行うことができます。

orderメソッドの書き方

orderメソッドの書き方は、以下のようになります。

Ruby
モデル名.order(並び替えるカラム名 並び順)

並び替えるカラム名には、並び替えたいカラムを指定します。並び順には、ASCまたはDESCを指定します。ASCは昇順、DESCは降順を意味します。

昇順と降順の指定方法

orderメソッドで昇順と降順を指定する方法は、以下の通りです

Ruby
モデル名.order(並び替えるカラム名 ASC) # 昇順
モデル名.order(並び替えるカラム名 DESC) # 降順

複数のカラムを指定する方法

複数のカラムを指定して並び替えを行う場合は、以下のように記述します。

Ruby
モデル名.order(並び替えるカラム名1 並び順1, 並び替えるカラム名2 並び順2)

例えば、usersテーブルのnameカラムを昇順、ageカラムを降順で並び替える場合は、以下のように記述します。

Ruby
User.order(name: "ASC", age: "DESC")

NULL値の扱い方

デフォルトでは、NULL値は最初に並び替えられます。NULL値を最後に並び替えるには、以下のように記述します。

Ruby
モデル名.order(並び替えるカラム名 並び順 NULLS LAST)

NULLS LASTを指定することで、NULL値が最後に並び替えられます。

クエリの指定

最後に、orderメソッドには複雑なクエリを指定することもできます。例えば、関連するテーブルからデータを取得し、特定のフィールドで並べ替えることができます。

Ruby
# idで昇順に並べ替える
@posts = Post.order(:id)
# idで降順に並べ替える
@posts = Post.order(id: :desc)
# 複数のフィールドで並べ替える
@posts = Post.order(:category_id, :created_at)
# 関連するテーブルのフィールドで並べ替える
@posts = Post.joins(:category).order("categories.name DESC")

上記の例では、Postモデルのデータをid、category_id、created_atの順で並べ替えています。また、最後の例では、categoriesテーブルのnameフィールドで並べ替えるために、joinsメソッドとともにorderメソッドを使用しています。

まとめ

これらの例を参考にして、orderメソッドを使用して簡単なクエリを作成することができます。しかし、複雑なクエリを作成する場合は、SQLの知識が必要になるため、事前に学習しておくことが望ましいです。

]]>
Rails | whereメソッドの使い方と基本的なクエリの書き方https://01memo.com/rails/where/Sun, 05 Mar 2023 10:34:34 +0000https://01memo.com/?p=107「whereメソッド」とは、RailsのActive Recordクラスであるモデルに対して簡単にクエリを作成できるためのメソッドの1つです。本記事では、初心者向けにwhereメソッドの基本的な使い方について解説します。

whereメソッドとは

whereメソッドは、指定した条件に合致するレコードを取得するためのメソッドです。引数にはハッシュ形式で条件を指定します。

以下に、例としてUserモデルから年齢が20歳のユーザーを取得するコードを示します。

Ruby
@users = User.where(age: 20)

このようにすることで、ageが20のユーザーを取得することができます。複数の条件を指定する場合には、複数のキー・バリューの組み合わせで指定します。

Ruby
@users = User.where(age: 20, gender: 'male')

この場合、ageが20かつgenderがmaleであるユーザーを取得します。

演算子の指定

whereメソッドでは、指定した条件をORでつなぐ場合や、比較演算子を使用する場合もあります。その場合は、ハッシュの値にハッシュを渡すことで指定します。

例えば、以下のコードはageが20または30のユーザーを取得するコードです。

Ruby
@users = User.where(age: [20, 30])

また、以下のコードはageが20以上のユーザーを取得するコードです。

Ruby
@users = User.where('age >= ?', 20)

ここでは、?を使用して、SQLインジェクションを防ぎつつ変数を埋め込んでいます。

結果の取得

whereメソッドで取得した結果は、Active Recordオブジェクトの配列として返されます。例えば、以下のコードは、Userモデルのnameが”John”のユーザーが存在するかどうかを判定するコードです。

Ruby
@user = User.where(name: 'John').first
if @user.present? # Johnが存在する場合の処理
else # Johnが存在しない場合の処理
end

また、Active Recordオブジェクトの配列から必要な情報を取り出す場合には、eachメソッドやeach_with_indexメソッドを使用します。

Ruby
@users = User.where(age: 20)
@users.each do |user| puts user.name
end

whereメソッドのオプション

whereメソッドには、いくつかのオプションがあります。

条件の論理演算子

whereメソッドでは、条件を複数指定することができます。指定した複数の条件は、AND条件で結合されます。

Ruby
User.where(name: "John", age: 25)

上記の例では、nameが”John”かつageが25のユーザーを検索します。

また、OR条件で複数の条件を指定することもできます。この場合は、whereメソッドを複数回呼び出すか、arelを使用する必要があります。

Ruby
User.where(name: "John").or(User.where(age: 25))

上記の例では、nameが”John”またはageが25のユーザーを検索します。

比較演算子

whereメソッドでは、以下のような比較演算子を使うことができます。

Ruby
User.where("age > ?", 25)

上記の例では、ageが25よりも大きいユーザーを検索します。

Ruby
User.where("created_at < ?", Time.now - 1.day)

上記の例では、created_atが1日前よりも古いユーザーを検索します。

IN句

whereメソッドでは、IN句を使うことができます。

Ruby
User.where(id: [1, 2, 3])

上記の例では、idが1、2、3のユーザーを検索します。

NOT句

whereメソッドでは、NOT句を使うことができます。

Ruby
User.where.not(name: "John")

上記の例では、nameが”John”ではないユーザーを検索します。

まとめ

whereメソッドは、Active Recordクラスであるモデルに対して簡単にクエリを作成できるためのメソッドです。複数の条件を指定することができ、比較演算子やIN句、NOT句を使うことができます。ぜひ活用してみてください

]]>
Rails | 初心者向けのscopeの使い方https://01memo.com/rails/scope/Sun, 05 Mar 2023 10:01:26 +0000https://01memo.com/?p=103Railsには、Active Recordクラスであるモデルに対して簡単にクエリを作成できるためのメソッドがあります。このメソッドの一つが「scope」です。

scopeを使用すると、複数のクエリで共通して使用される条件を簡単に定義できます。これにより、コードの重複を避け、簡潔で保守しやすいコードを書くことができます。

例えば、以下のようなUserモデルがあるとします。

Ruby
class User < ApplicationRecord scope :active, -> { where(status: :active) }
end

この例では、このスコープは、Userモデルに対して、statusが「active」であるユーザーを取得するものです。

activeスコープの定義では、ブロックを使用して、where句を簡潔に記述しています。これにより、コードがシンプルで読みやすくなっています。スコープを使用することで、同じ条件でクエリを書く必要がある場合に、重複を避けることができます。

上記の例で定義したactiveスコープを呼び出す場合は、以下のように書きます。

Ruby
User.active

このようにすることで、Userモデルからstatusが「active」であるユーザーのみを取得することができます。

スコープは、単純なActiveRecordのクエリの再利用を可能にし、コードの再利用性を向上させます。また、可読性の高いコードを書くことができます。

スコープはどこで定義するの? どこで使用するの?

スコープは、モデルとコントローラーで定義できます。

モデルでスコープを定義することが一般的ですが、必要に応じてコントローラーでもスコープを定義することができます。

スコープの使用は、モデル、コントローラー、ビューのどこでも可能です。

ただし、ビューで複雑なクエリを実行するためのものではありません。ビューで必要となるデータをできるだけ限定し、ビジネスロジックはモデルに置くように心がけるべきです。

関連するモデルにも定義できる

関連するモデルにもスコープを定義することができます。

関連するモデルに対してスコープを定義することで、より簡潔なクエリを書くことができます。以下に例を示します。

Ruby
class User < ApplicationRecord has_many :posts
end
class Post < ApplicationRecord scope :published, -> { where(published: true) } belongs_to :user
end

上記の例では、UserモデルとPostモデルが関連付けられています。

Postモデルには、publishedスコープが定義されています。

このスコープは、publishedカラムがtrueであるPostモデルのみを取得するものです。

Userモデルから、関連するPostモデルに対してpublishedスコープを適用する場合は、以下のように書くことができます。

Ruby
user = User.find(1)
user.posts.published

このようにすることで、関連するPostモデルから、publishedカラムがtrueであるもののみを取得することができます。

スコープを関連するモデルに定義することで、簡潔なコードを書くことができ、可読性が向上します。

スコープで引数を取る

スコープは引数を取ることができます。引数を使うことで、動的なクエリを書くことができます。例えば、特定の条件に応じて異なる結果を返すスコープを定義することができます。

以下に例を示します。

Ruby
class Post < ApplicationRecord scope :published, -> { where(published: true) } scope :created_after, -> (date) { where("created_at > ?", date) }
end

上記の例では、Postモデルに2つのスコープが定義されています。

publishedスコープは、publishedカラムがtrueであるPostモデルのみを取得します。

created_afterスコープは、引数として渡された日付以降に作成されたPostモデルを取得します。

以下のように、引数を渡してスコープを呼び出すことができます。

Ruby
Post.published # publishedカラムがtrueであるPostモデルを取得
Post.created_after(Date.today - 1.week) # 1週間前以降に作成されたPostモデルを取得

このようにすることで、動的なクエリを簡単に書くことができます。

引数を使うことで、異なる条件に対して簡単にスコープを定義することができ、コードの可読性が向上します。

まとめ

今回はRailsでスコープを定義するためのいくつかの方法を紹介しました。

スコープを使用することで、コードの重複を避け、複雑なクエリをシンプルにすることができます。ぜひ、活用してみてください!

]]>
Docker |「Error response from daemon: Ports are not available」というエラーが出た時の対処法https://01memo.com/docker/ports-error/Sun, 05 Mar 2023 08:53:56 +0000https://01memo.com/?p=98Dockerでコンテナを起動する際、ポートが他のプロセスで使用中であるために、「Error response from daemon: Ports are not available」というエラーが発生することがあります。このエラーに対する対処法を解説します。

出てきたエラー

Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:80 -> 0.0.0.0:0: listen tcp 0.0.0.0:80: bind: address already in use

エラーの原因

「Error response from daemon: Ports are not available」というエラーは、Dockerが指定されたポートを使用することができないために発生します。これは、他のプロセスがすでにそのポートを使用している場合によく発生します。

ポートを確認する

まず最初に、ポートが使用中かどうかを確認する必要があります。これには、次のコマンドを使用します。

sudo lsof -i :<ポート番号>

このコマンドを実行すると、ポート番号を使用しているプロセスのリストが表示されます。ポートを使用しているプロセスを終了することで、ポートを解放することができます。

// ターミナルに入力
sudo lsof -i:80
// 実行結果
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 12345 daemon 7u IPv6 0x90...(省略)..... 0t0 TCP *:http (LISTEN)
httpd 12346 daemon 7u IPv6 0x90...(省略).....
..(省略)...

ポートを解放する

ポートを使用しているプロセスが特定できたら、終了することができます。これには、次のコマンドを使用します。

sudo kill <PID>

ここで、<PID>はポートを使用しているプロセスのPIDです。

// ターミナルに入力
sudo kill 12345
sudo kill 12346

また、他の方法として、次のコマンドを使用して、ポートを解放することができます。

sudo fuser -k <ポート番号>/tcp

このコマンドを実行すると、ポートを使用しているプロセスが終了し、ポートが解放されます。

別のポートに変更する

もう一つの方法は、別のポートに変更することです。これには、Dockerの起動コマンドに指定されているポート番号を変更する必要があります。たとえば、次のようにします。

docker run -p <ホスト側のポート>:<コンテナ側のポート> <イメージ名>

ここで、<ホスト側のポート>と<コンテナ側のポート>を変更することができます。

Docker Composeを使用している場合

Docker Composeを使用している場合には、次のようにdocker-compose.ymlファイルを編集して、ポート番号を変更することができます。

services: web: ports: - "<ホスト側のポート>:<コンテナ側のポート>"

デバッグ方法

ポートがすでに使用されている場合、別のプロセスが既にそのポートを使用している可能性があります。その場合、次のようにして、ポートを使用しているプロセスを確認できます。

1. ポートを使用しているプロセスを確認する

sudo lsof -i :ポート番号

例えば、ポート番号80のプロセスを調べるには、次のように入力します。

sudo lsof -i :80

このコマンドは、ポート番号80を使用しているプロセスをリストアップします。

2. ポートを解放する

すでに使用されているポートを解放するには、使用しているプロセスを停止する必要があります。使用しているプロセスが不要な場合は、次のようにして停止できます。

sudo systemctl stop サービス名

例えば、Apache HTTPサーバーのプロセスを停止するには、次のように入力します。

sudo systemctl stop apache2

また、特定のポートを使用しているプロセスを強制終了することもできます。次のように入力します。

sudo fuser -k ポート番号/tcp

例えば、ポート番号80のプロセスを強制終了するには、次のように入力します。

sudo fuser -k 80/tcp

これにより、ポート80を使用しているプロセスが強制終了されます。

3. Dockerコンテナを再起動する

ポートが解放されたら、Dockerコンテナを再起動してポートを再利用できます。次のようにして、Dockerコンテナを再起動できます。

docker restart コンテナ名

例えば、コンテナ名がmyappの場合、次のように入力します。

docker restart myapp

以上の手順で、ポートがすでに使用されているというエラーを解決できるはずです。

]]>
Rails | ファイル名をサニタイズする方法https://01memo.com/rails/sanitizedfilename/Sun, 05 Mar 2023 08:38:37 +0000https://01memo.com/?p=96Railsでファイル名をサニタイズする方法

Railsでアップロードされたファイルのファイル名を安全に扱うためには、サニタイズ(文字列を無害化する)する必要があります。ファイル名には、不正な文字や記号が含まれることがあるため、そのまま扱うとセキュリティ上のリスクにつながる可能性があります。

Railsでは、ActiveStorageを使ってアップロードされたファイルを扱うことができます。ActiveStorage::Filename.newメソッドを使うことで、ファイル名を扱いやすい形式に変換することができます。そして、sanitizedメソッドを使うことで、ファイル名をサニタイズすることができます。

ActiveStorage::Filename.newメソッド

ActiveStorage::Filename.newメソッドを使うことで、アップロードされたファイルのファイル名を扱いやすい形式に変換することができます。ファイル名の変換は、ASCII文字列に変換されます。

Ruby
filename = ActiveStorage::Filename.new("ファイル名")
puts filename #=> #<ActiveStorage::Filename:0x00007f98aa011858 @name="ファイル名", @extension=nil>

このように、ActiveStorage::Filename.newメソッドを使うことで、ファイル名を扱いやすい形式に変換することができます。この変換されたファイル名に対して、sanitizedメソッドを適用することで、ファイル名をサニタイズすることができます。

sanitizedメソッド

sanitizedメソッドを使うことで、ファイル名をサニタイズすることができます。このメソッドを適用することで、ファイル名に含まれる不正な文字や記号を置換することができます。

Ruby
filename = ActiveStorage::Filename.new("不正な/ファイル名?です")
sanitized_filename = filename.sanitized
puts sanitized_filename #=> "不正な_ファイル名_です"

このように、ファイル名に含まれる不正な文字や記号が”_(アンダースコア)”に置換され、無害化されます。

実際の使用例

実際の使用例として、ActiveStorageを使ってファイルをアップロードする際は下記のようになります。

Ruby
class UserController < ApplicationController def create # アップロードされたファイルから、ファイル名を取得 filename = params[:user][:avatar].original_filename # ファイル名をActiveStorage::Filename.newメソッドを使って扱いやすい形式に変換 active_storage_filename = ActiveStorage::Filename.new(filename) # ファイル名をサニタイズ sanitized_filename = active_storage_filename.sanitized # ユーザー情報を保存 @user = User.new(user_params) @user.avatar.attach(io: params[:user][:avatar].tempfile, filename: sanitized_filename) if @user.save redirect_to @user else render :new end end private def user_params params.require(:user).permit(:name, :email) end
end

上記のコードでは、アップロードされたファイルからファイル名を取得し、ActiveStorage::Filename.newメソッドを使ってファイル名を扱いやすい形式に変換しています。そして、sanitizedメソッドを適用してファイル名をサニタイズしています。

最後に、Active Storageを使ってファイルを保存する際に、サニタイズされたファイル名を指定しています。

正規表現を使ったサニタイズ

ActiveStorage::Filename.new(“ファイル名”).sanitizedメソッドを使ってファイル名をサニタイズする方法以外にも、正規表現を使ってサニタイズする方法もあります。正規表現を使った場合、どの文字を置換するかを自由に設定できるため、より柔軟なサニタイズが可能です。

例えば、次のような正規表現を使って、ファイル名から”?”や”#”を除外することができます。

Ruby
filename = "不正な/ファイル名?です#"
sanitized_filename = filename.gsub(/[?#]/, '_')
puts sanitized_filename #=> "不正な/ファイル名_です_"

このように、gsubメソッドを使って正規表現にマッチする文字列を置換することができます。

まとめ

Railsでファイル名をサニタイズする方法について、ActiveStorage::Filename.new(“ファイル名”).sanitizedメソッドを使った方法を説明しました。また、正規表現を使った方法についても説明しました。ファイル名をサニタイズすることで、アプリケーションのセキュリティを強化することができます。

]]>