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

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

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

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Ruby on Rails

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

Q&A

解決済

2回答

8501閲覧

Railsのview画面のif分岐が反映されない

Dizzyboy

総合スコア13

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Ruby on Rails

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

0グッド

1クリップ

投稿2019/12/29 14:46

Railsのviewにてif文を記述し、DBに値が入っている、いない、で表示を変更させたいのですが思うように変わってくれず、助力を頂きたく質問をいたします。

実行したいこと

index画面にてuserをeach do で一覧表示している中で、userテーブル以外のDBに入っている値を取得し、その値が入っているかいないかでif文で表示を分けようとしています。

確認したこと

画面をリロードした際に、ターミナルを確認するとuserテーブルとは別のテーブルのDBに入っている値は取得できているように思います。(見方があっていれば…)

コード

index.html.erb抜粋

html

1 <div class="employee__box"> 2 <% @users.each do |user| %> 3 <ul class="employee__box__list"> 4 <%= render partial: "employee", locals: { user: user} %> 5 </ul> 6 <% end %> 7 </div>

<%= render partial: "employee", locals: { user: user} %></ul>のrender部分

html

1<% if @sch.present? %> 2 <li class="employee__box__list__name", id="leave", data-user-id="<%=user.id%>"><%= user.name %></li> 3 <% else %> 4 <li class="employee__box__list__name_select", id="attend", data-user-id="<%=user.id%>"><%= user.name %></li> 5<% end %>

すべて
<li class="employee__box__list__name", id="leave", data-user-id="<%=user.id%>"><%= user.name %></li>の方で表示されてしまいます。

users_controller.rbのindexアクション

Rails

1 def index 2 @users = User.all.order("id") 3 @users.each do |user| 4 @schedule = Schedule.find(user.schedules.ids.last) 5 @sch = @schedule.out 6 end 7 end

コントローラーの@users = User.all.order("id")でuserの一覧を表示しています。
usersとschedulesはmodel側でhas_manyとbelongs_toでアソシエーションを組んでいます。

@schedule = Schedule.find(user.schedules.ids.last)により@scheduleでschedulesテーブルでそれぞれのuser_idを持つ、最後のレコードを取得しています。
@sch = @schedule.outはoutカラムを指定し、view側で<% if @sch.present? %>とすることで、schedulesテーブルのoutカラムの中に値が入っているか、いないか、で分岐させようとしています。

index画面をリロードした際に、ターミナルでの表示の詳細を見ると

terminal

1Started GET "/" for ::1 at 2019-12-29 22:35:41 +0900 2Processing by UsersController#index as HTML 3 User Load (0.3ms) SELECT `users`.* FROM `users` ORDER BY id 4 ↳ app/controllers/users_controller.rb:5 5 (0.3ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 1 6 ↳ app/controllers/users_controller.rb:6 7 Schedule Load (0.5ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 14 LIMIT 1 8 ↳ app/controllers/users_controller.rb:6 9 (0.5ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 2 10 ↳ app/controllers/users_controller.rb:6 11 Schedule Load (0.2ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 5 LIMIT 1 12 ↳ app/controllers/users_controller.rb:6 13 (0.2ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 3 14 ↳ app/controllers/users_controller.rb:6 15 Schedule Load (0.2ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 15 LIMIT 1 16 ↳ app/controllers/users_controller.rb:6 17 (0.2ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 4 18 ↳ app/controllers/users_controller.rb:6 19 Schedule Load (0.2ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 18 LIMIT 1 20 ↳ app/controllers/users_controller.rb:6 21 (0.2ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 5 22 ↳ app/controllers/users_controller.rb:6 23 Schedule Load (0.2ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 16 LIMIT 1 24 ↳ app/controllers/users_controller.rb:6 25 (0.2ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 6 26 ↳ app/controllers/users_controller.rb:6 27 Schedule Load (0.2ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 17 LIMIT 1 28 ↳ app/controllers/users_controller.rb:6 29 (0.3ms) SELECT `schedules`.`id` FROM `schedules` WHERE `schedules`.`user_id` = 7 30 ↳ app/controllers/users_controller.rb:6 31 Schedule Load (0.2ms) SELECT `schedules`.* FROM `schedules` WHERE `schedules`.`id` = 12 LIMIT 1 32 ↳ app/controllers/users_controller.rb:6 33 Rendering users/index.html.erb within layouts/application 34 Rendered users/_header.html.erb (0.2ms) 35 Rendered users/_employee.html.erb (0.5ms) 36 Rendered users/_employee.html.erb (0.1ms) 37 Rendered users/_employee.html.erb (0.0ms) 38 Rendered users/_employee.html.erb (0.0ms) 39 Rendered users/_employee.html.erb (0.0ms) 40 Rendered users/_employee.html.erb (0.1ms) 41 Rendered users/_employee.html.erb (0.1ms) 42 Rendered users/index.html.erb within layouts/application (12.3ms) 43Completed 200 OK in 89ms (Views: 48.4ms | ActiveRecord: 9.4ms)

と表示され、
(0.3ms) SELECT schedules.id FROM schedules WHERE schedules.user_id = 1
で、@users = User.all.order("id")の一覧が表示され、Schedule Load (0.5ms) SELECT schedules.* FROM schedules WHERE schedules.id = 14 LIMIT 1
で、@schedule = Schedule.find(user.schedules.ids.last)の値が取得できているのが分かるのですが、上記viewのように設定してもifで分岐される表示になりません。

試したこと

html

1<% if @sch.present? %> 2 <li class="employee__box__list__name", id="leave", data-user-id="<%=user.id%>"><%= user.name %></li> 3 <% else %> 4 <li class="employee__box__list__name_select", id="attend", data-user-id="<%=user.id%>"><%= user.name %></li> 5<% end %>

<% if @sch.present? %><% if @sch.blank? %>にすると、全部 <li class="employee__box__list__name_select", id="attend", data-user-id="<%=user.id%>"><%= user.name %></li>側の表示になります。
present?、blank?の他に、<% if @sch.nil? %>では.blank?の時と同じくなりました。

controllerの@sch = @schedule.outの直下にbinding.pryを入れてリロードした場合、@schの値は取得できていて、@schの中には日時が入っています。そのため、あるか、ないかでtrue、falseの判定をさせて、falseの場合にelse側の表示をさせようとしておりますが、上記htmlのif文で分岐できておりません。
その理由が分からず、困っております。

エラーなどは出ず、.present?だと全部else前の表示になり、.blank?だと全部else後の表示になってしまう状態です。
何か、お気づきの点がございましたらご回答いただけましたら幸いです。
不明な点がありましたらコメントにてお伝えいただけましたら、ご提示いたします。

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

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

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

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

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

KazuSaka

2019/12/29 15:54 編集

気になるところがあっので… コントローラのIndexアクションの所ですが、 @usersには全ユーザーが入ってますが、@schにはeach文の最後のユーザーの日付データしか入ってないのでは?(上書きされるから) だから、ビューでは、ユーザー毎に処理しても、@schは毎回同じ値が使われるのでは? @schは配列にすべきかと思います。
Dizzyboy

2019/12/29 17:58

ご回答頂き、ありがとうございます。 @users.each do |user| @schedule = Schedule.find(user.schedules.ids.last) end のeachはuserは@schedule = Schedule.find(user.schedules.ids.last)をして、それぞれのuser_idを持っている、最後のschedule.idを取得するためにeachをかけております。(userが無いとuser.schedules.ids.lastでfindメソッドが使え無いのです…) 質問文内のterminalの表示をみる限りでは、user_idが1の時、schedule.idの14が取れてて、これがscheduleテーブル内でのuser_id1がついている、最後のレコードです。 今userは7名いて、それぞれに最後のレコードの値が付与されていますが、これが上書きされてしまっているということでしょうか? @schを配列にするという方法が、わかりません…調べてみたのですがmapメソッドというのを使えばよいのでしょうか? せっかくご回答をいただけたのに、理解が追いつかず申し訳ございません…。
KazuSaka

2019/12/29 19:55

回答欄に私の考えを記載しました。
guest

回答2

0

ベストアンサー

###ZIPメソッドについて

一つだけ気になったのですが、zipメソッドを使うとeachの文字がなくてもきちんと表示されるのはなぜなのでしょうか?試しに <% @users.zip(@sch).each do |user, sch| %>と記述しても、同じ挙動が得られたので、zipはeachも包括していると考えてよいのでしょうか?(この場合、eachを置くと重服する??)

他のサイトなどを確認すると、zipだけのところもあれば、eachもあわせて使用しているところもあり、どちらがより良い記述なのだろうか、と気になりました。
https://freesworder.net/ruby-each-multiple/
こちらのサイトも参照してzipについて、調べていた中でふと気になった所存です。

本来、zipメソッドは複数の配列を多次元配列にして、返すメソッドです。
ですので、["apple","banana","orange"].zip([100,120,80])
の結果は[ ["apple",100], ["banana",120], ["orange",80] ](2次元配列)です。

eachを付けた場合、この2次元配列から順に要素を取り出して処理できます。

eachを省略した場合でも、同じ挙動になるのは、zipメソッドにブロックを渡すこともできるからです。これは、rubyのリファレンスに書いてあります。https://ref.xaio.jp/ruby/classes/array/zip
※ブロックとは、do|変数|...endのことです。

この場合、eachを置くと重服する??)

重複はしていないと思います。

eachを付けた場合
ブロックを受け取っているのは、eachメソッドなので、zipメソッドは2次元配列を返しているだけです。(zipメソッド自体はeachみたいな振る舞いはしない)

eachを省略した場合
zipメソッドにブロックを渡しているので、eachみたいな振る舞いをする。

どちらがより良い記述なのだろうか、と気になりました。

リファレンスに書いてありますが、ブロックを渡した時は、zipメソッドの返り値はnilになります。

ブロックを渡さない場合

ruby

1#retには[["apple",100],["banana",120],["orange",80]]が入ります。 2ret = ["apple","banana","orange"].zip([100,120,80]) 3

ブロックを渡す場合

ruby

1#retはnilになります。 2ret = ["apple","banana","orange"].zip([100,120,80]) do |fruit,price| 3 #処理 4end 5

ですので、eachを付けるか省略するかの違いは
zipメソッドの返り値(2次元配列)を使って、eachメソッドの繰り返し処理をする。
もしくは、返り値はnilだけど、eachみたいなループをさせるか。
の違いだと思います。
ビューではただ、ループさせたいだけなので、どちらの記述でも問題ないと思います。

以上

投稿2019/12/30 19:17

編集2019/12/30 23:23
KazuSaka

総合スコア640

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

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

Dizzyboy

2019/12/31 16:02

KazuSaka様 この度は、zipメソッドについての追加質問にも丁寧にお答えいただき誠にありがとうございます。 リファレンスのアドレスまでつけて頂き、より詳しく理解を深めることができました。 自分で書いたコードがどのように動いているのか、きちんと把握できて大変助かりました。 今回教えて頂いた情報を元に、引き続き勉強を続けていきます。 知らなかったメソッドなどの情報も得られ非常に勉強になりました。 本当にありがとうございました!
guest

0

質問の続きですが、

のeachはuserは@schedule = Schedule.find(user.schedules.ids.last)をして、それぞれのuser_idを持っている、最後のschedule.idを取得するためにeachをかけております。(userが無いとuser.schedules.ids.lastでfindメソッドが使え無いのです…)

ここはeach文で各ユーザーに紐づいたschedulesテーブルのレコードを取り出す処理なので問題ないと思います。ログからも確認できていると思います。

質問文内のterminalの表示をみる限りでは、user_idが1の時、schedule.idの14が取れてて、これがscheduleテーブル内でのuser_id1がついている、最後のレコードです。

今userは7名いて、それぞれに最後のレコードの値が付与されていますが、これが上書きされてしまっているということでしょうか?

@schには7人目のoutカラム情報しか入っていないと思います。
outカラム情報はユーザーによってユニークですよね?

以下のコードについて
each文:(1)(2)を7人分繰り返す。
(1)各ユーザーのscheduleテーブルの最終レコードを取り出す。
(2)(1)で取り出したレコードのoutカラムを@schに入れる。

eachループが終わった時にインスタンス変数として保持されているデータは下記だと思います。
@users => [id: 1, name: "hoge"]...[id:7, name: "xxx"]※7人分のユーザー情報
@sch => @usersの7人目のoutカラムのみ. ※7人分のoutカラム情報は保持できていない。
@schedule => @usersの7人目のscheduleテーブルの最終レコード.ビューで参照しないため、関係ない.

def index @users = User.all.order("id") @users.each do |user| @schedule = Schedule.find(user.schedules.ids.last) #(1) @sch = @schedule.out #(2) end end

@schを配列にするという方法が、わかりません…調べてみたのですがmapメソッドというのを使えばよいのでしょうか?

7人分のoutカラム情報をビューから参照するには、@schを配列にして、7人分保持すればいいかと思いました。(each文の中で配列に代入)
以下のように配列に値をプッシュします。
** @sch.push(@schedule.out) ** ※@sch = @schedule.outの書き換え

以下が私の考えるコードになります。
一度、試していただけると嬉しいです。

###コントローラの記述
@schを配列にして7人分のoutカラム情報を入れる

def index @users = User.all.order("id") @sch=[] #配列初期化 @users.each do |user| @schedule = Schedule.find(user.schedules.ids.last) @sch.push(@schedule.out) #配列に格納 end end

##HTMLの記述
zipメソッドで@users配列と@sch配列から同時に値を取り出せます。
取り出したschをパーシャルでつかう。

html

1 <div class="employee__box"> 2 <% @users.zip(@sch) do |user, sch| %> 3 <ul class="employee__box__list"> 4 <%= render partial: "employee", locals: {user: user, sch: sch} %> 5 </ul> 6 <% end %> 7 </div>

##パーシャルの記述
@schから取り出した各ユーザーのout情報で分岐する。

<% if sch.present? %> <li class="employee__box__list__name", id="leave", data-user-id="<%=user.id%>"><%= user.name %></li> <% else %> <li class="employee__box__list__name_select", id="attend", data-user-id="<%=user.id%>"><%= user.name %></li> <% end %>

以上

投稿2019/12/29 19:54

編集2019/12/30 05:32
KazuSaka

総合スコア640

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

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

Dizzyboy

2019/12/30 13:29

ご回答ありがとうございます。 お返事が遅くなり、大変申し訳ございません。 追加の質問にも細かく答えて頂き、重ね重ねありがとうございます。 まだ、試すことができていないのですが、先にご返答を頂いたお礼をさせていただきたくコメントいたしました。 これからお伝え頂いた内容を、試してみたいと思います。 pushは知っていたのですがzipメソッドは初耳なので、調べつつ内容をきちんと理解しながら作業したく思います。 追って、結果をお伝えしたいと考えておりますのでお時間をいただけましたら幸いです。
Dizzyboy

2019/12/30 16:20

KazuSaka様、ご回答頂いた内容を元に記述いたしましたところ、無事希望する挙動を得ることができました。大変感謝いたします。 ご指摘頂いた、 eachループが終わった時にインスタンス変数として保持されているデータは下記だと思います。 @users => [id: 1, name: "hoge"]...[id:7, name: "xxx"]※7人分のユーザー情報 @sch => @usersの7人目のoutカラムのみ. ※7人分のoutカラム情報は保持できていない。 @schedule => @usersの7人目のscheduleテーブルの最終レコード.ビューで参照しないため、関係ない. の部分で、画面表示に適用される部分とされない部分が明確になりました。 自分の記述では @sch = @schedule.outに入る値が、eachで排出した最後の部分しか適用されないというのに気づけていなかった、ビューの表示に影響する部分と、されない部分が明確に判断できていなかったのが、自身の勉強不足と痛感しました。 terminalで表示されているからviewにも伝わっている、と誤った判断をしておりました。 zipメソッドについても調べて内容を把握いたしました。 2つの配列をループさせて値を取り出す、というメソッドがあるのを知りませんでした…。 今回調べた中で、https://qiita.com/Jwataru/items/923a11f9e97a84c7982f#zip%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89 の記事を読んだ時に「引き出しがないと「〇〇したいから〇〇メソッドを使えばいいか、そのメソッドどうやって使うんだっけ」という段階にすらいかない」という記載があり、正に今回の自分のケースだなと思いました。 pushについてもrubyでやった内容だったのにも関わらず、記憶から抜け落ちていて恥ずかしい限りです…。 zipのことを調べることで、色々メソッドについても勉強になり、知らなかったメソッドを知ることもできました。これに関しましても大変ありがたく感謝いたします。 一つだけ気になったのですが、zipメソッドを使うとeachの文字がなくてもきちんと表示されるのはなぜなのでしょうか?試しに <% @users.zip(@sch).each do |user, sch| %>と記述しても、同じ挙動が得られたので、zipはeachも包括していると考えてよいのでしょうか?(この場合、eachを置くと重服する??) 他のサイトなどを確認すると、zipだけのところもあれば、eachもあわせて使用しているところもあり、どちらがより良い記述なのだろうか、と気になりました。 https://freesworder.net/ruby-each-multiple/ こちらのサイトも参照してzipについて、調べていた中でふと気になった所存です。
KazuSaka

2019/12/30 19:20

色々と洞察されていて、素晴らしいです。 また、解決されたみたいで、良かったです。 zipメソッドについての解釈を回答欄にまとめました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問