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

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

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

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

Q&A

解決済

1回答

344閲覧

rails NoMethodError in Farmers#indexを解消したい

tomo.work

総合スコア2

Ruby on Rails 6

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

1グッド

1クリップ

投稿2023/06/08 20:37

編集2023/06/09 04:27

rails NoMethodError in Farmers#indexを解消したい

エラーを解消してyoutube投稿機能を実装させたいです。

前提

rails 6.1.3.1でアプリでyoutube投稿機能を実装させる途中で、ヘルパーにコードを書いたところ表題のエラーが発生してしまい解決方法を探しています。

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

NoMethodError in Farmers#index
Showing /home/ubuntu/environment/minnanofarm/app/views/farmers/index.html.erb where line #59 raised:

undefined method `include?' for nil:NilClass

###該当のコード(app/controllers/helpers/famers_helper.rb)

module FarmersHelper def find_youtube_url(youtube_url) if youtube_url.include?("https://youtu.be/") #ここが59行目# binding.pry youtube_url.strip!.gsub("https://youtu.be/", "") # "https://youtu.be/WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする else youtube_url.strip!.gsub("https://www.youtube.com/watch?v=", "") # "https://www.youtube.com/watch?v=WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする end end end

###app/views/farmers/index.html.erb

<h1>働き手(Cast)を探す</h1> <div class="row"> <div class="col-sm-6 offset-sm-3"> <%= form_with(model: @work) do |f| %> <%= render 'layouts/error_messages', model: f.object %> <div class="mb-3"> <%= f.label :title, 'お仕事名' %> <%= f.text_field :title, class: 'form-control' %> </div> <div class="mb-3"> <%= f.label :description, 'お仕事詳細' %> <%= f.text_field :description, class: 'form-control' %> </div> <div class="mb-3"> <%= f.label :work_type, '作業種別' %> <%= f.select :work_type, ["準備・片付け","定植", "収穫","出荷","その他"], class: 'form-control' %> </div> <div class="mb-3"> <%= f.label :work_date, '作業日' %> <%= f.date_field :work_date, class: 'form-control' %> </div> <div class="mb-3"> <%= f.label :recruitment, '募集人数' %> <%= f.text_field :kana, class: 'form-control' %> </div> <div class="mb-3"> <%= f.label :youtube_url %> <%= f.text_field :youtube_url, :size => 140 %> </div> <div class="mb-3"> <%= f.label :body %> <%= f.text_field :body,class: 'form-control' %> </div> <%= f.submit '登録', class: 'btn btn-primary' %> <% end %> </div> <!-- col-sm-6 offset-sm-3 --> </div> <!-- row --> <div class="row mt-4"> <% if @works.any? %> <% @works.each do |work| %> <div class="col-md-4"> <%= work.title %><br> <%= work.work_date %><br> <%= work.work_type %><br>     <% if work.youtube_url.present? %> <iframe width="560" height="315" src="https://www.youtube.com/embed/<%= find_youtube_url(work.youtube_url) %>" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> </div> <% end %> <% end %> </div> <!-- row -->

試したこと

①エラーコードを読みincludeに原因がありと当たりをつけpryを試すも
[3] pry(#<#Class:0x00007f1e84947e48>)> include?
NoMethodError: undefined method `include?' for #ActionView::Base:0x00000000007260と出てしまう
②<% if work.youtube_url.present? %>をfarmersのindex.html.erbに追加したらタイムアウトするようになってしまい。
現在手詰まりになってしまっています。

shinoharat👍を押しています

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

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

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

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

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

winterboum

2023/06/08 23:40

code がぐちゃぐちゃで読めません。<code>を使って整形してください。 index.htmlはどこが59行目なのかわかるようにしてください
tomo.work

2023/06/09 04:29

ありがとうございます。 質問の仕方も勉強していきたいと思っています。 お忙しいと存じますが何卒、お願いいたします。
winterboum

2023/06/09 06:32

エラーメッセージに index.html.erb where line #59 ってありますね、famers_helper.rb の59行じゃないです
guest

回答1

0

ベストアンサー

原因

nil に対して include? メソッドを呼び出そうとしたことが原因のエラーです。

変数 youtube_url に String が入っていれば、

rb

1"aaa".include?("https://youtu.be/") 2#=>false

のように判定できますが、変数の中身が nil の場合は

rb

1(nil).include?("https://youtu.be/") 2#=> undefined method `include?' for nil:NilClass (NoMethodError)

が発生します。

対策

対策としては、「試したこと」に記載されている

②<% if work.youtube_url.present? %>をfarmersのindex.html.erbに追加

で問題ないと思いますが、それだとタイムアウトするようになったのですね。

view のコードをざっくり確認したところ、「if」や「each」の数と「end」の数が合っていないように見えます。
もしかして、「<% if ...present? %>」の追加時に、対応する「<% end %>」を追加し忘れていませんか?
以下の位置に end を追加してみてください。

diff

1 <div class="row mt-4"> 2 <% if @works.any? %> 3 <% @works.each do |work| %> 4 <div class="col-md-4"> 5 <%= work.title %><br> 6 <%= work.work_date %><br> 7 <%= work.work_type %><br> 8 <% if work.youtube_url.present? %> 9 <iframe src="https://www.youtube.com/embed/<%= find_youtube_url(work.youtube_url) %>" ... ></iframe> 10+ <% end %> 11 </div> 12 <% end # `@works.each` の終わり %> 13 <% end # `if @works.any?` の終わり %> 14 </div> <!-- row -->

おまけ

今の書き方だと、悪意のある HTML や JavaScript が挿入できてしまうため、「クロスサイトスクリプティング(XSS)」という攻撃が成立してしまいます。

攻撃例

画面の youtube_url のテキストボックスに以下の文字列を入力すると、アラートが出るはずです。

https://youtu.be/WGiUk8VakxQ" onload="alert('XSS!!')" x="

alert の部分を悪意あるコードに変えれば、「Cookie窃盗」や「Webページの汚損」などの攻撃が可能です。

修正例1

<%=u ... %> のように u を入れてURLエンコードします。

diff:修正例1

1- <iframe src="https://www.youtube.com/embed/<%= find_youtube_url(work.youtube_url) %>" ... ></iframe> 2+ <iframe src="https://www.youtube.com/embed/<%=u find_youtube_url(work.youtube_url) %>" ... ></iframe>

修正例2

または tag メソッドを使って HTML を組み立てます。

erb:修正例2

1<%= tag.iframe( 2 src: "https://www.youtube.com/embed/#{find_youtube_url(work.youtube_url)}", 3 width: 560, 4 height: 315, 5 title: "YouTube video player", 6 ... 7 allowfullscreen: true 8) %>

(追記 2023/6/12)undefined method `gsub' について

gsub でエラーが出る原因は String#strip! メソッドだと思います。

ドキュメントによると、『空白がある場合はそれを取り除いた文字列を返すが、空白が無い場合は nil を返す』そうです。

strip! は、内容を変更した self を返します。 ただし取り除く空白がなかったときは nil を返します。

https://docs.ruby-lang.org/ja/latest/method/String/i/strip=21.html より

空白を除去するメソッドには、破壊的な strip! と、非破壊的な strip があります。
もし引数を破壊的に変更することに特別な意味が無いなら、非破壊的な方の strip を使えば、今回のエラーは解消できると思います。

diff

1 module FarmersHelper 2 def find_youtube_url(youtube_url) 3 if youtube_url.include?("https://youtu.be/") 4- youtube_url.strip!.gsub("https://youtu.be/", "") 5+ youtube_url.strip.gsub("https://youtu.be/", "") 6 # "https://youtu.be/WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする 7 else 8- youtube_url.strip!.gsub("https://www.youtube.com/watch?v=", "") 9+ youtube_url.strip.gsub("https://www.youtube.com/watch?v=", "") 10 # "https://www.youtube.com/watch?v=WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする 11 end 12 end 13 end

投稿2023/06/09 06:15

編集2023/06/13 04:10
shinoharat

総合スコア1676

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

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

tomo.work

2023/06/10 05:00

返信遅くなり申し訳ありません。 また、素人の私でもわかりやすいご回答ありがとうございます! 早速、試してみました!(XSSも) 無事にエラー解決しました。ありがとうございます! しかし、別のエラーが 『NoMethodError in Farmers#index Showing /home/ubuntu/environment/minnanofarm/app/views/farmers/index.html.erb where line #60 raised: undefined method `gsub' for nil:NilClass』が出てしまったので・・・ 『既存コード app/controllers/helpers/famers_helper.rb 』 def find_youtube_url(youtube_url) if youtube_url.include?("https://youtu.be/") youtube_url.strip!.gsub("https://youtu.be/", "") # "https://youtu.be/WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする else youtube_url.strip!.gsub("https://www.youtube.com/watch?v=", "") ↑を修正して・・・『同じくapp/controllers/helpers/famers_helper.rb』 def find_youtube_url(youtube_url) if youtube_url.present? if youtube_url.include?("https://youtu.be/") youtube_url.strip!.gsub("https://youtu.be/", "") # "https://youtu.be/WGiUk8VakxQ" 11桁のyoutubeのURLが出力されるようにする else youtube_url.strip!.gsub("https://www.youtube.com/watch?v=", "") end end youtube_url end としyoutube_urlが存在する場合のみ処理するようにしたつもりなのですが上手く行きませんでした。 お忙しいとは存じますが何かアドバイスいただければ幸いです💦
tomo.work

2023/06/10 05:01

追加の質問をしておいて何なのですが・・・追加の場合は新たに質問を作成したほうが良いのでしょうか?💦
shinoharat

2023/06/12 00:15

返信が遅くなってすみません。 gsub のエラーについて追記しました。ご確認ください。
tomo.work

2023/06/13 03:13

返信おそくなりまして申し訳ございません。 gsubのエラーわかりやすくご説明頂きありがとうございました!!!!! ご教授いただいた通り修正したところエラー解消しました。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問