前提
Docker環境上でRuby on railsを用いて、自転車のレンタル機能を開発しております。
自転車一覧画面と自転車使用履歴画面があり、1(自転車一覧画面)対多(自転車の使用履歴の画面)で関連付けしております。自転車使用履歴画面には自転車一台に対して、持ち出し日時と返却日時があり、持ち出しと返却を行った回数分のデータが存在します。そのため、自転車一覧画面に返却日時を表示させようとした場合、複数のデータが表示されてしまう。
db/schema.rb
ruby
1create_table "bicycle_logs", comment: "自転車使用履歴", force: :cascade do |t| 2 t.bigint "bicycle_id", comment: "自転車id" 3 t.datetime "take_datetime", comment: "持ち出し日時" 4 t.bigint "take_user_id", comment: "持ち出し日時" 5 t.datetime "return_datetime", comment: "返却日時" 6 t.bigint "return_user_id", comment: "返却日時" 7 t.integer "before_weight", comment: "使用前重量" 8 t.integer "after_weight", comment: "使用後重量" 9 t.integer "used_weight", comment: "使用量" 10 t.datetime "created_at", precision: 6, null: false 11 t.datetime "updated_at", precision: 6, null: false 12 t.index ["bicycle_id"], name: "index_paintcan_logs_on_paintcan_id" 13 end
ruby
1create_table "bicycles", comment: "自転車", force: :cascade do |t| 2 t.datetime "arrival_datetime", comment: "入荷日時" 3 t.string "product_number", comment: "品番" 4 t.integer "weight", comment: "重量" 5 t.bigint "location_id", comment: "ロケーションid" 6 t.bigint "create_user_id", comment: "作成者id" 7 t.bigint "update_user_id", comment: "更新者id" 8 t.datetime "created_at", precision: 6, null: false 9 t.datetime "updated_at", precision: 6, null: false 10 end
実現したいこと
自転車一覧画面に自転車の使用履歴にある最新の返却日時のみを表示させたい。
発生している問題・エラーメッセージ
自転車一覧画面に返却日時を表示させようとした場合、複数のデータが表示されてしまう。
*更新日時に返却日時を代入している
該当のソースコード
app/views/bicycles/index.html.slim
ruby
1= render_with_pagination(bicycles) do |bicycles| 2 .table-sticky.max-vh-70 3 table.table.table-sm.table-bordered.table-striped.table-hover.text-nowrap 4 thead 5 tr 6 省略 7 th= sort_link_to :updated_at 8 |更新日時 9 省略 10 11 tbody 12 - bicycles.each do |bicycle| 13 tr 14 省略 15 - bicycle.bicycle_logs.each do |bicycle_log| 16 td= bicycle_log.return_datetime 17 省略
app/models/bicycle.rb
ruby
1include Order 2 3has_many :bicycle_logs, dependent: :restrict_with_error 4 5scope :search, ->(params){ 6 result = self 7 8 result 9 }
app/models/bicycle_log.rb
ruby
1include Order 2 3belongs_to :bicycle, optional: false 4 5scope :search, ->(params){ 6 result = self 7 8 result 9 }
app/controllers/bicycles_controller.rb
ruby
1def index 2 @bicycles = Bicycle 3 .search(params) 4 .order_by(params[:sort]) 5 end
試したこと
モデルにメソッドを定義し、VIEWに表示させました。以下のコメントアウトした様々な方法で返却日時であるreturn_datetimeを表示させた上で最新のデータのみを表示させようとしましたが、上手く行かず、何か思いつく方法があれば、教えて頂けると幸いです。
app/models/bicycle_log.rb
ruby
1def a 2 bicycle_logs = BicycleLog 3 # .search(params) 4 # .order_by(params[:sort]) 5 # .find(&:return_datetime).last 6 # .find(params[:return_datetime]) 7 # .find(&:return_datetime) 8 # .where(&:return_datetime) 9 # .pluck(:return_datetime) 10 # .order(return_datetime: :desc) 11 # .find{(_1.return_datetime) <= date.max} 12 end
app/views/bicycles/index.html.slim
ruby
1= render_with_pagination(bicycles) do |bicycles| 2 .table-sticky.max-vh-70 3 table.table.table-sm.table-bordered.table-striped.table-hover.text-nowrap 4 thead 5 tr 6 省略 7 th= sort_link_to :updated_at 8 |更新日時 9 省略 10 11 tbody 12 - bicycles.each do |bicycle| 13 tr 14 省略 15 - bicycle.bicycle_logs.each do |bicycle_log| 16 td= bicycle_log.a 17 省略
試したこと2
app/models/bicycle_log.rb
ruby
1def a 2bicycle_log_ids = BicycleLog.where.not(return_datetime: nil).group(:bicycle_id).maximum(:return_datetime).values 3Bicycle.left_joins(:bicycle_logs).merge(BicycleLog.where(id: bicycle_log_ids)).select("bicycles.*, bicycle_logs.*") 4end
app/views/bicycles/index.html.slim
ruby
1= render_with_pagination(paintcans) do |paintcans| 2.table-sticky.max-vh-70 3table.table.table-sm.table-bordered.table-striped.table-hover.text-nowrap 4thead 5tr 6tbody 7- bicycles.each do |bicycle| 8tr 9省略 10- paintcan.paintcan_logs.each do |paintcan_log| 11td= paintcan_log.a 12省略
補足情報(FW/ツールのバージョンなど)
バージョン情報
Rails 6.1.4.7
ruby 3.1.2
Docker 20.10.11
