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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

3回答

4214閲覧

Ruby on Rails nilへの対応方法を教えてください

riamk

総合スコア47

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2017/06/15 04:38

編集2017/06/16 10:45

###前提・実現したいこと
Ruby on Rails4で開発中。

現在勉強のため、twitterのようなアプリケーションを作成しました。
deviseでログイン機能を実装し、ログインしているユーザーしか投稿できないようにしています。
投稿された記事はどのユーザーが投稿したのかを関連づけています。

今まではユーザーが退会した場合、そのユーザーが投稿した記事も削除されるようにしていたのですが、今回ユーザーが退会した場合に、その退会したユーザーが投稿した記事は削除されず残しておくようにしたいと思い取り組んでいます。

退会したユーザーのユーザーnameは「退会したユーザー」として表示して記事を残そうと思っているのですが、その方法が分かりません。

ユーザーが退会した場合、投稿したユーザーは当たり前ですがnilになってしまいます。
そのユーザーnilへの対応の仕方が分からないのでご教授お願いします。

###発生している問題・エラーメッセージ
ユーザーが退会した場合、userがnilになるので
・user/showへのリンクでエラー
・userのprofile_imgでエラー
・user.nameでエラー
と上記のようなエラーが発生してしまいます。

どのように対応したらいいのでしょうか?

###該当のソースコード
timeline/index.html.erb

ruby

1<!-- 投稿一覧 --> 2 <% @timelines.each do |timeline| %> 3 <%= link_to user_path(timeline.user_id) do %> 4 <%= profile_img(timeline.user) %> 5 <% end %> 6 <%= timeline.user.name %> 7 <%= link_to timeline_path(timeline) do %> 8 <%= image_tag (timeline.photo_url) if timeline.photo.present? %> 9 <%= timeline.content %></p> 10 <% end %> 11 <% end %>

applicationHelper.rb

ruby

1module ApplicationHelper 2 # プロフィール画像の設定 3 def profile_img(user) 4 return image_tag(user.avatar, alt: user.name) if user.avatar? 5 6 unless user.provider.blank? 7 img_url = user.image_url 8 else 9 img_url = 'no_image.png' 10 end 11 image_tag(img_url, alt: user.name) 12 end 13end

###補足情報(言語/FW/ツール等のバージョンなど)
他に必要なコードなどあれば記載しますので、何卒よろしくお願いいたします。

nilに対して対応して試してみたこと
timeline/index.html.erb

ruby

1<!-- 投稿一覧 --> 2<% @timelines.each do |timeline| %> 3 <% if timeline&.user_id.present? %> 4 <%= link_to user_path(timeline.user_id) do %> 5 <%= profile_img(timeline.user)%> 6 <% end %> 7 <% else %> 8 # ユーザーIDがnilの場合のプロフィール画像の表示を記述 9 <% end %> 10 11 <% if timeline&.user_id.present? %> 12 <%= timeline.user.name %> 13 <%= link_to timeline_path(timeline) do %> 14 <%= image_tag (timeline.photo_url) if timeline.photo.present? %> 15 <%= timeline.content %> 16 <% end %> 17 <% else %> 18 # ユーザーIDがnilの場合の処理 19 <% end %> 20<% end %>

ユーザーが存在する場合と、存在しない(nil)場合の処理をif文で条件分岐して表示すればいいのかと思い、このコードを書きました。
ですが、nilの場合の判定ができていないのか、ユーザーが存在しない場合も<%= timeline.user.name %>などが呼び出されエラーになってしまいます。

*試したことへの補足
なぜnilの判定がうまくできないのか?
ユーザーがいなくなった(退会した)記事の中身を見てみたらユーザーIDは残っていた。
これが原因でユーザーIDのnil判定ができていませんでした。

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

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

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

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

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

guest

回答3

0

ベストアンサー

helperファイルがあると思います。

使い方は簡単で、
def sample
endってヘルパーに書いたあと

ビューに<%= sample %>で呼べると思います。

if timeline&.user_id ってところを

if has_user?(timeline)に書き換えてください

ヘルパーに
def has_user?(timeline)
uid=timeline.user_id
User.where(id: uid).first ? true : false
end
と書けばいけると思います。
user_idが必ず入ってるわけじゃないならif文で入ってないときに return false すればいけると思います!

我ながらスマホで頑張った…笑

投稿2017/06/16 13:37

drizzing20

総合スコア363

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

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

riamk

2017/06/16 15:29

ご回答ありがとうございます。 教えて頂いたようにヘルパーメソッドを使用して試してみたところ、無事にユーザーが存在する場合としない場合で表示できました! スマホからの回答は大変だったかと思いますが、ほんと助かりました! ありがとうございます!
drizzing20

2017/06/16 19:29

設計としてはあまり良くなくて、timelineてことはおそらく結構な量になりますよね。 その量×ぶんのクエリを出し続けるのパフォーマンスとしてはあまり良くないのでユーザーIDが消せるならそれが良いと思います! アソシエーションとか調べればできそうなのと、 強引にユーザーが退会するときにユーザーのtimelineのユーザーIDを全部nilか何かに書き換えるとかですかね
riamk

2017/06/17 00:33

設計としては良くないんですね。 はい。タイムラインで投稿量は多くなります。 アソシエーションのdependentオプションで:nullifyに設定してユーザーが退会した場合に、そのユーザーに関連する投稿のユーザーIDをnilに書き換えることができました。 なので、最初に教えて頂いた if timeline&.user_id.pressent? でnil判定して処理を分けて対応してみようと思います。 分かりやすい説明と的確なアドバイス、ありがとうございます!
guest

0

indexでは

@users = 存在するusers

showでは

if userが存在しない then redirecct_to :users, notice: '存在しないuserです' end

とするのはどうですか?

投稿2017/06/15 05:55

編集2017/06/15 05:56
mbk

総合スコア130

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

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

riamk

2017/06/15 07:01

ご回答ありがとうございます。 ご教授頂いた内容はなんとなく理解はできるのですが、そこから具体的にどうコードを書いていけばいいかがまだ私に分かりません。 お手数をおかけして申し訳ありませんが、もう少しアドバイス頂けると嬉しいです。
mbk

2017/06/15 23:38

index, showでの処理をkanaさんなりに書いて頂けますか。 動かなくてOKです。
riamk

2017/06/16 08:44

畏まりました。 indexとshowのコードを書けたら質問に追記いたします。
riamk

2017/06/16 10:25

mbkさんに教えて頂いたものとは違う形になってしまったのですが、if文を使用してユーザーが存在しない場合の処理を分岐して表示させようとコードを書いてみました。 ですが、nilの場合の判定がうまくいかないのかエラーが出てしまいます。 コードとエラー内容は質問の補足情報に追記しました。 とりあえずindexのコードのみになりますが、アドバイス頂けると嬉しいです。
mbk

2017/06/16 11:29

ぼっち演算子は知らないのですが、これはどうですか? if timeline.user_id.present? && User.exists?(id: timeline.user_id)
riamk

2017/06/16 15:26

ご教授ありがとうございます。 if timeline.user_id.present? && User.exists?(id: timeline.user_id) 教えて頂いたこちらのコードでnilの判定がうまくでき、if文でユーザーがいない場合の条件分岐の表示ができました! ありがとうございました!
guest

0

ユーザーがいない投稿を消すかいなかみたいなのはモデルの定義でなんとか変えられると思います(もし、悩んでいたら)

そこまでができてるのを前提としてちょっとコード書きます!

erb

1<% @timelines.each do |timeline| %> 2 <%= if timeline&.user_id.pressent? %> # ← ユーザーIDがあったらっていう処理です 「&.」って書いてあるのはぼっち演算子って言って無くてもエラー返さないやつです 3 <%= link_to user_path(timeline.user_id) do %> 4 <%= profile_img(timeline.user) %> 5 <% end %> 6 <%= timeline.user.name %> 7 <%= link_to timeline_path(timeline) do %> 8 <%= image_tag (timeline.photo_url) if timeline.photo.present? %> 9 <%= timeline.content %></p> 10 <%= else%> 11 #ここにユーザーIDがnilだったときの処理をかきます! 12 13 <% end %> 14<% end %>

ユーザーIDがnilだったときどういうふうに表示したいのか分からない(書いてたらすいません)のでここらへんは適当に書いてください

↓みたいなのでも良いのかもしれないですね

<%= link_to リンク先は「ユーザーは削除されました」とか表示されるページに飛ばすとか do %> <%= #写真はTwitterの卵写真みたいなのを差し替える %> <% end %> ユーザーネームは引けないから ユーザーは削除されました とか書いておく <%= link_to timeline_path(timeline) do %> <%= image_tag (timeline.photo_url) if timeline.photo.present? %> <%= timeline.content %></p>

投稿2017/06/15 14:56

drizzing20

総合スコア363

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

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

riamk

2017/06/16 08:43

ご回答いただきありがとうございます。 ユーザーがいない投稿を消すかどうかなどは、モデルのほうで定義できてます。 drizzing20さんに書いて頂いたコードを参考に試行錯誤しながら試してみようと思います。
riamk

2017/06/16 10:29

drizzing20さんのコードを参考にif文を使用しユーザーが存在しない場合の処理を書いてみました。 ですが、<%= if timeline&.user_id.pressent? %> でnilの判定がうまくできないのか、エラーが出てしまいます。 書いてみたコードやエラーの内容は質問の補足情報に追記しました。 修正点や誤った箇所などあれば、ご指摘いただけると嬉しいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問