質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

788閲覧

Railsで作成したオブジェクトをfind_byするとnilが返ってくる

rararuri

総合スコア11

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/11/16 11:43

前提・実現したいこと

Railsで動画共有サイトを作っています。
動画投稿機能を実装中にエラーが発生しました。
動画はAmazonS3で保存します。
動画のファイル名をS3fileモデルで管理しています。(カラム名:key, 型:String)

動画投稿の流れは以下の通りです。
1.newビューで動画をアップロードする。
2.createアクションで動画のファイル名を取得、加工し、S3にアップロードする動画のファイル名("assets22/マイビデオ.mp4")とする。S3に動画をアップロード。showアクションにリダイレクトする。
3.showアクションでファイル名でfind_byし、showビューの動画のリンクにファイル名を埋め込む。

発生している問題・エラーメッセージ

showアクションでファイル名でfind_byしてもnilが返ってきます。

NoMethodError in S3files#show Showing /home/ubuntu/environment/stream/app/views/s3files/show.html.erb where line #1 raised: undefined method `key' for nil:NilClass Extracted source (around line #1): 1 2 3 <video src="https://bucket-for-stream.s3.ap-northeast-1.amazonaws.com/<%= @s3file.key %>" controls> </video> Rails.root: /home/ubuntu/environment/stream Application Trace | Framework Trace | Full Trace app/views/s3files/show.html.erb:1 Request Parameters: {"id"=>"22"} Toggle session dump Toggle env dump Response Headers: None

該当のソースコード

###### ビュー(new.html.erb)

ruby

1<%= form_for @s3file do |f|%> 2 <%= f.label :key, '動画ファイル'%> 3 <%= f.file_field :key %> 4 <%= f.submit 'アップロード' %> 5<% end %>

###### ビュー(show.html.erb)

ruby

1<video src="https://bucket-for-stream.s3.ap-northeast-1.amazonaws.com/<%= @s3file.key %>" controls> 2 3</video>
コントローラー

ruby

1 2 def create 3 file = s3file_params[:key] 4 5 file_path = "tmp/s3/#{file.original_filename}" 6 File.binwrite(file_path, file.read) 7 8 s3file = S3file.new() 9 s3file.save 10 11 ##動画ファイル名にIDを含める。ファイル名を検索キーとし、s3file.find()を使う。 12 filename = "assets#{s3file.id.to_s}/#{file.original_filename}" 13 14 s3file.update_attribute(:key, filename) 15 16 bucket = @s3.bucket(@bucketname) 17 18 object = bucket.object(s3file.key) 19 20 object.upload_file(file_path, acl: 'public-read') 21 22 redirect_to s3file 23 end 24 25 def index 26 27 end 28 29 def show 30 @s3file = S3file.find_by(key: "assets#{params[:id]}/*") 31 end 32

サーバーのログ

Started POST "/s3files" for 114.176.222.81 at 2021-11-16 10:16:46 +0000 Cannot render console from 114.176.222.81! Allowed networks: 127.0.0.0/127.255.255.255, ::1 Processing by S3filesController#create as HTML Parameters: {"authenticity_token"=>"4pEeZmAUoweHWKDv88oL+M9YfUIEQtsRVdNJ3IMCZkfAFHzmWFdx+B3Hpn8yzJ53I1dzDAc2G62aN91OmFvy5Q==", "s3file"=>{"key"=>#<ActionDispatch::Http::UploadedFile:0x00007fca8d7558a0 @tempfile=#<Tempfile:/tmp/RackMultipart20211116-15168-7irpoc.mp4>, @original_filename="マイヒテオ.mp4", @content_type="video/mp4", @headers="Content-Disposition: form-data; name=\"s3file[key]\"; filename=\"\xE3\x83\x9E\xE3\x82\xA4\xE3\x83\x92\xE3\x82\x99\xE3\x83\x86\xE3\x82\x99\xE3\x82\xAA.mp4\"\r\nContent-Type: video/mp4\r\n">}, "commit"=>"アップ ロード"} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/helpers/sessions_helper.rb:5:in `current_user' (0.1ms) begin transaction ↳ app/controllers/s3files_controller.rb:16:in `create' S3file Create (5.0ms) INSERT INTO "s3files" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2021-11-16 10:16:46.756767"], ["updated_at", "2021-11-16 10:16:46.756767"]] ↳ app/controllers/s3files_controller.rb:16:in `create' (8.7ms) commit transaction ↳ app/controllers/s3files_controller.rb:16:in `create' (0.0ms) begin transaction ↳ app/controllers/s3files_controller.rb:21:in `create' S3file Update (6.1ms) UPDATE "s3files" SET "key" = ?, "updated_at" = ? WHERE "s3files"."id" = ? [["key", "assets23/マイヒテオ.mp4"], ["updated_at", "2021-11-16 10:16:46.787081"], ["id", 23]] ↳ app/controllers/s3files_controller.rb:21:in `create' (6.0ms) commit transaction ↳ app/controllers/s3files_controller.rb:21:in `create' [Aws::S3::Client 200 0.11378 0 retries] put_object(acl:"public-read",bucket:"bucket-for-stream",key:"assets23/マイヒテオ.mp4",body:#<File:tmp/s3/マイヒテオ.mp4 (341072 bytes)>) Redirected to https://80317708b2c9470d881342ffecb8540d.vfs.cloud9.ap-northeast-1.amazonaws.com/s3files/23 Completed 302 Found in 184ms (ActiveRecord: 26.1ms | Allocations: 10126) Started GET "/s3files/23" for 114.176.222.81 at 2021-11-16 10:16:46 +0000 Cannot render console from 114.176.222.81! Allowed networks: 127.0.0.0/127.255.255.255, ::1 Processing by S3filesController#show as HTML Parameters: {"id"=>"23"} User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/helpers/sessions_helper.rb:5:in `current_user' S3file Load (0.1ms) SELECT "s3files".* FROM "s3files" WHERE "s3files"."key" = ? LIMIT ? [["key", "assets23/*"], ["LIMIT", 1]] ↳ app/controllers/s3files_controller.rb:37:in `show' Rendering s3files/show.html.erb within layouts/application Rendered s3files/show.html.erb within layouts/application (Duration: 0.8ms | Allocations: 1286) Completed 500 Internal Server Error in 14ms (ActiveRecord: 0.2ms | Allocations: 2856) ActionView::Template::Error (undefined method `key' for nil:NilClass): 1: <video src="https://bucket-for-stream.s3.ap-northeast-1.amazonaws.com/<%= @s3file.key %>" controls> 2: 3: </video> app/views/s3files/show.html.erb:1

試したこと

rails cでオブジェクトが作成されていることを確認。
find_by(key: "assets23/マイビデオ.mp4")しましたがnilが返ってきました。
サーバーのログには「マイヒテオ.mp4」と表示されていますが、このファイル名でfind_byしてもnilが返ってきました。

補足情報(FW/ツールのバージョンなど)

Rails6.0.3
Cloud9
OS:Ubuntu Server 18.04LTS

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ruby

1S3file.find_by(key: "assets#{params[:id]}/*")

これに対応するログは以下です。

SELECT "s3files".* FROM "s3files" WHERE "s3files"."key" = ? LIMIT ? [["key", "assets23/*"], ["LIMIT", 1]]

LIKE 検索ではないので文字列 assets23/* を検索しています。その結果 nil です。

params[:id] は S3file の ID なので、ID を検索すれば良いです。

ruby

1 def show 2 @s3file = S3file.find(params[:id]) 3 end

どうしても key で検索したいなら LIKE 検索にします。

ruby

1 def show 2 @s3file = S3file.find_by("key LIKE ?", "assets#{params[:id]}/%") 3 end

投稿2021/11/16 20:24

neko_daisuki

総合スコア2090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

key としてsaveされているのは"assets#{s3file.id.to_s}/#{file.original_filename}"です。実際の値は例えば "assets123/my_mov
それを"assets#{params[:id]}/*" すなわち"assets123/*" でfind_byしているので hit しません。

投稿2021/11/16 20:18

winterboum

総合スコア23333

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問