🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

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

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

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

Q&A

解決済

1回答

3196閲覧

Ruby On Rails 複数テーブルから期待するデータを表示させたい

koh-s

総合スコア9

Ruby

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

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

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

0グッド

1クリップ

投稿2019/11/27 14:13

編集2019/11/28 02:41

前提・実現したいこと

イメージ説明
イメージ説明
イメージ説明
【実現したいこと】
・usersテーブルとattendancesテーブルより各取り出したいデータを取得。
・出勤中のユーザー(ここではSample User)のみ表示。
【試したこと】

ruby

1Attendance.where.not(started_at: nil)

ruby

1@users = User.all.includes(:attendances)

上記で各情報をざっくりですが取り出せていることをdebuggerで確認。

ruby

1(byebug) Attendance.where.not(started_at: nil) 2 Attendance Load (0.2ms) SELECT "attendances".* FROM "attendances" WHERE ("attendances"."started_at" IS NOT NULL) LIMIT ? [["LIMIT", 11]] 3#<ActiveRecord::Relation [#<Attendance id: 27, worked_on: "2019-11-27", started_at: "2019-11-27 04:13:00", finished_at: nil, note: nil, user_id: 1, created_at: "2019-11-25 12:45:42", updated_at: "2019-11-27 04:13:49">]> 4(byebug)

ruby

1(byebug) User.all.includes(:attendances) 2 User Load (0.3ms) SELECT "users".* FROM "users" LIMIT ? [["LIMIT", 11]] 3 Attendance Load (0.3ms) SELECT "attendances".* FROM "attendances" WHERE "attendances"."user_id" IN (1, 2, 3, 4, 5) 4#<ActiveRecord::Relation [#<User id: 1, name: "Sample User", email: "sample@email.com", created_at: "2019-11-25 12:23:13", updated_at: "2019-11-25 12:45:53", password_digest: "$2a$12$R6sK1xJNv2H3HNePLGSYyupr0QJ.3y8O/Av8rexJjOL...", remember_digest: nil, admin: true, affiliation: "テスト部", basic_time: "2019-11-24 23:00:00", work_time: "2019-11-24 22:30:00", superior: false, employee_number: 1, uid: "1", designated_work_start_time: "2019-11-25 00:00:00", designated_work_end_time: "2019-11-25 09:00:00", basic_work_time: "2019-11-24 23:00:00">, 5#<User id: 2, name: "Superior User", email: "superior@email.com", created_at: "2019-11-25 12:23:14", updated_at: "2019-11-25 12:23:14", password_digest: "$2a$12$9QBc.FAHnrY1zttzYHYUJuy1GKfqAJ0gtSmNEDPQiaf...", remember_digest: nil, admin: false, affiliation: "上長部", basic_time: "2019-11-24 23:00:00", work_time: "2019-11-24 22:30:00", superior: true, employee_number: 2, uid: "2", designated_work_start_time: "2019-11-25 13:00:00", designated_work_end_time: "2019-11-24 20:00:00", basic_work_time: "2019-11-24 23:00:00">, 6#<User id: 3, name: "山田 彩花", email: "sample-1@email.com", created_at: "2019-11-25 12:23:15", updated_at: "2019-11-25 12:23:15", password_digest: "$2a$12$W6q1Szgja0UjN4y/ldC7b.Y/1iqtoTnU23ujB3QuDxI...", remember_digest: nil, admin: false, affiliation: "フリーランス部", basic_time: "2019-11-24 23:00:00", work_time: "2019-11-24 22:30:00", superior: false, employee_number: 1, uid: "sample1", designated_work_start_time: "2019-11-25 00:00:00", designated_work_end_time: "2019-11-25 09:00:00", basic_work_time: "2019-11-24 23:00:00">, 7#<User id: 4, name: "松本 美桜", email: "sample-2@email.com", created_at: "2019-11-25 12:23:15", updated_at: "2019-11-25 12:23:15", password_digest: "$2a$12$ujsUYOEtEKtagDmc1HWzuewNj/mXAOhmyVJCO7XXfPj...", remember_digest: nil, admin: false, affiliation: "フリーランス部", basic_time: "2019-11-24 23:00:00", work_time: "2019-11-24 22:30:00", superior: false, employee_number: 2, uid: "sample2", designated_work_start_time: "2019-11-25 00:00:00", designated_work_end_time: "2019-11-25 09:00:00", basic_work_time: "2019-11-24 23:00:00">, 8#<User id: 5, name: "木下 明日香", email: "sample-3@email.com", created_at: "2019-11-25 12:23:16", updated_at: "2019-11-25 12:23:16", password_digest: "$2a$12$CZD7Svm8oq3NgJM8x1nVGeUxmLO7hoqcNBpRpsgKCEi...", remember_digest: nil, admin: false, affiliation: "フリーラン ス部", basic_time: "2019-11-24 23:00:00", work_time: "2019-11-24 22:30:00", superior: false, employee_number: 3, uid: "sample3", designated_work_start_time: "2019-11-25 00:00:00", designated_work_end_time: "2019-11-25 09:00:00", basic_work_time: "2019-11-24 23:00:00">]> 9(byebug)

該当のソースコード

【users_controller.rb】

ruby

1 def index_attendance 2 Attendance.where.not(started_at: nil).each do |attendance| 3 if (Date.current == attendance.worked_on) && attendance.finished_at.nil? 4 @users = User.all.includes(:attendances) 5 end 6 end 7 end

【index_attendance.erb】

ruby

1<% provide(:title, "出勤中社員一覧") %> 2<h1>出勤中社員一覧</h1> 34<div> 5 <table class="table table-bordered table-condensed table-hover text-center table-striped" id="index_attendance"> 6 <thead> 7 <tr> 8 <th>社員番号</th> 9 <th>名前</th> 10 </tr> 11 </thead> 12 <tbody> 13 <% @users.each do |user| %> 14 <tr> 15 <td><%= user.employee_number %></td> 16 <td><%= user.name %></td> 17 </tr> 18 <% end %> 19 </tbody> 20 </table> 21</div>

【attendance.rb】

ruby

1class Attendance < ApplicationRecord 2 belongs_to :user 3 require 'csv' 4 5 validates :worked_on, presence: true 6 validates :note, length: { maximum: 50 } 7 8 # 出勤時間が存在しない場合、退勤時間は無効 9 validate :finished_at_is_invalid_without_a_started_at 10 validate :started_at_than_finished_at_fast_if_invalid 11 12 def finished_at_is_invalid_without_a_started_at 13 errors.add(:started_at, "が必要です") if started_at.blank? && finished_at.present? 14 end 15 16 def started_at_than_finished_at_fast_if_invalid 17 if started_at.present? && finished_at.present? 18 errors.add(:started_at, "より早い退勤時間は無効です") if started_at > finished_at 19 end 20 end 21end 22

【user.rb】

ruby

1class User < ApplicationRecord 2 has_many :attendances, dependent: :destroy 3 attr_accessor :remember_token 4 before_save { self.email = email.downcase } 5 validates :name, presence: true, length: { maximum: 50 } 6 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+.[a-z]+\z/i 7 validates :email, presence: true, length: { maximum: 100 }, format: { with: VALID_EMAIL_REGEX }, 8 uniqueness: true 9 has_secure_password 10 validates :password, presence: true, length: { minimum: 6 }, allow_nil: true 11 validates :affiliation, length: { in: 2..30 }, allow_blank: true 12 validates :basic_work_time, presence: true 13 validates :work_time, presence: true 14 15 def User.digest(string) 16 cost = 17 if ActiveModel::SecurePassword.min_cost 18 BCrypt::Engine::MIN_COST 19 else 20 BCrypt::Engine.cost 21 end 22 BCrypt::Password.create(string, cost: cost) 23 end 24 25 def User.new_token 26 SecureRandom.urlsafe_base64 27 end 28 29 def remember 30 self.remember_token = User.new_token 31 update_attribute(:remember_digest, User.digest(remember_token)) 32 end 33 34 def authenticated?(remember_token) 35 return false if remember_digest.nil? 36 BCrypt::Password.new(remember_digest).is_password?(remember_token) 37 end 38 39 def forget 40 update_attribute(:remember_digest, nil) 41 end 42 43 def self.import(file) 44 CSV.foreach(file.path, headers: true, encoding: 'Shift_JIS:UTF-8') do |row| 45 # IDが見つかれば、レコードを呼び出し、見つかれなければ、新しく作成 46 user = find_by(id: row["id"]) || new 47 # CSVからデータを取得し、設定する 48 user.attributes = row.to_hash.slice(*updatable_attributes) 49 # 保存する 50 user.save 51 end 52 end 53 54 def self.updatable_attributes 55 ["name", "email", "affiliation", "employee_number", "uid", "basic_work_time", 56 "designated_work_start_time", "designated_work_end_time", "superior", "admin", "password"] 57 end 58end

【schema.rb】

ruby

1ActiveRecord::Schema.define(version: 20191118081810) do 2 3 create_table "attendances", force: :cascade do |t| 4 t.date "worked_on" 5 t.datetime "started_at" 6 t.datetime "finished_at" 7 t.string "note" 8 t.integer "user_id" 9 t.datetime "created_at", null: false 10 t.datetime "updated_at", null: false 11 t.index ["user_id"], name: "index_attendances_on_user_id" 12 end 13 14 create_table "users", force: :cascade do |t| 15 t.string "name" 16 t.string "email" 17 t.datetime "created_at", null: false 18 t.datetime "updated_at", null: false 19 t.string "password_digest" 20 t.string "remember_digest" 21 t.boolean "admin", default: false 22 t.string "affiliation" 23 t.datetime "basic_time", default: "2019-11-24 23:00:00" 24 t.datetime "work_time", default: "2019-11-24 22:30:00" 25 t.boolean "superior", default: false 26 t.integer "employee_number" 27 t.string "uid" 28 t.datetime "designated_work_start_time", default: "2019-11-25 00:00:00" 29 t.datetime "designated_work_end_time", default: "2019-11-25 09:00:00" 30 t.datetime "basic_work_time", default: "2019-11-24 23:00:00" 31 t.index ["email"], name: "index_users_on_email", unique: true 32 end 33 34end 35

【attendances_controller.rb】

ruby

1 UPDATE_ERROR_MSG = "勤怠登録に失敗しました。やり直してください。" 2 3 def update 4 @attendance = Attendance.find(params[:id]) 5 if @attendance.started_at.nil? 6 if @attendance.update_attributes(started_at: Time.current.change(sec: 0)) 7 flash[:info] = "おはようございます!" 8 else 9 flash[:danger] = UPDATE_ERROR_MSG 10 end 11 elsif @attendance.finished_at.nil? 12 if @attendance.update_attributes(finished_at: Time.current.change(sec: 0)) 13 flash[:info] = "お疲れ様でした!" 14 else 15 flash[:danger] = UPDATE_ERROR_MSG 16 end 17 end 18 redirect_to @user 19 end

試したこと

if文の条件分岐を潜っても全ユーザーが取得できてしまうことは何となくわかりますが、これをそれぞれに紐づける術がわからずギブアップになります。
モデルにはattendance.rbはbelongs_toを設定。
user.rbはhas_manyを設定しています。

お忙しい中恐れ入りますが、何卒ご教授のほど宜しくお願い致します。

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

ruby 2.6.3
rails 5.1.6

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

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

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

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

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

winterboum

2019/11/27 14:44

usersテーブルとattendancesテーブルより各取り出したいデータを取得 とありますが、どういうのが取り出したいデータなのかが書かれていないので回答しようが無いです。 取り出したいデータの条件を書いて下さい。 出勤中のユーザー(ここではSample User)のみ表示。 とありますが、出勤しているかどうかは何で判断するのでしょうか
koh-s

2019/11/28 02:37

ご回答ありがとうございます。 今回、取り出したいデータとして ・usersテーブルからは出社時間(started_atがDBに保存されている)かつ退社時間(finished_at)がnilのユーザー情報。 ・attendancesテーブルからは本日(Date.current)の日付。 この2点を紐付けてユーザーの名前(name)と従業員番(employee_number)を取り出すことを目的としています。 また、出勤判断は出社ボタンを押下されて、attendances_controller.rb内のupdateメソッドでif @attendance.started_at.nil?で条件分岐して判断しています。 表現が難しく適切にお伝えできているか自身がありません、何かご指摘などがございました際は是非勉強させてください。宜しくお願い致します。
winterboum

2019/11/28 03:29

User, Attendance のスキーマ(migration情報)を載せて下さい。
koh-s

2019/11/28 09:09

お世話になります。 「該当のソースコード」最後から2番目に【schema.rb】としてご用意しました。 お手数おかけして申し訳ございませんがご確認の程、宜しくお願い致します。
guest

回答1

0

ベストアンサー

ああ、やっぱり started_at は UserではなくAttendance の方ですね。
すると絞り込み条件が全て Attendanceの方か、、、、
条件に合うUserを探すのではなく、条件にあう Attendance を探してそのUserのデータを表示する方が、検索式が書きやすいかも。
つまり @attendances = Attendance.includes(:user).where()として、@attendances.each{|attencance| attendance.user.某 }とする。
その方針だと

date = Date.today Attendance.includes(:user). where.not(started_at: nil). where(finished_at: nil). where(started_at: date.beginning_of_day .. date.end_of_day)

でしょうか。
Userで検索するとどうなるのかな、自信ないですが

User.joins(:attendances). where.not(attendances: {started_at: nil}). where(attendances: {finished_at: nil}). where(attendances: {started_at: date.beginning_of_day .. date.end_of_day})

かなぁ

投稿2019/11/28 10:41

winterboum

総合スコア23567

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問