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

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

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

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

Q&A

1回答

1800閲覧

中間テーブルにおけるユニーク制約のscopeの記述方法が分かりません

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby on Rails 6

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

0グッド

0クリップ

投稿2021/02/01 05:03

前提・実現したいこと

初質問です。
分かりにくいかもしれませんが、知恵を貸していただけたら有り難いです。

railsでスケジュール管理のアプリケーションを作成中です。
関係あるモデルは

- schedule   - item # スケジュール作成の際、使用する機材を選択 - schedule_item(中間テーブル)

の3つになります。
gem 'simple_calendar' を導入してしており、デフォルトで用意されている:start_date, :end_dateを使用して開始日と終了日を指定します。
スケジュール作成には複数のitem(機材)を選択でき、itemも複数のスケジュールに紐付いています。
ユニーク制約をかけたい点として、同じ日に同じitemを選択できないようにしたいのですが意図したように出来ません。

ruby

1class Schedule < ApplicationRecord 2 belongs_to :user 3 has_many :schedule_items 4 has_many :items, through: :schedule_items 5 6 with_options presence: true do 7 validates :start_date 8 validates :end_date 9 validates :client 10 validates :title 11 validates :content 12 validates :items 13 end 14end

ruby

1class Item < ApplicationRecord 2 belongs_to :user 3 has_many :schedule_items 4 has_many :schedules, through: :schedule_items 5 6 extend ActiveHash::Associations::ActiveRecordExtensions 7 belongs_to_active_hash :item_name 8 belongs_to_active_hash :status 9 10 with_options presence: true do 11 validates :item_name_id, numericality: { other_than: 0 }, uniqueness: true 12 validates :status_id, numericality: { other_than: 0 } 13 end 14end

ruby

1class ScheduleItem < ApplicationRecord 2 belongs_to :schedule 3 belongs_to :item 4 5 validates :item_id, uniqueness: { scope: [:start_date, :end_date] } 6end 7

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

イメージ説明

該当のソースコード

ruby

1class SchedulesController < ApplicationController 2 before_action :authenticate_user!, only: [:new, :create, :edit, :destroy] 3 before_action :set_schedule, only: [:show, :edit, :update, :destroy] 4 5 def index 6 @schedules = Schedule.all 7 end 8 9 def new 10 @schedule = Schedule.new 11 end 12 13 def create 14 @schedule = Schedule.new(schedule_params) 15 if @schedule.save 16 redirect_to schedule_path(@schedule.id) 17 else 18 render :new 19 end 20 end 21 22 def show 23 end 24 25 def edit 26 end 27 28 def update 29 if @schedule.update(schedule_params) 30 redirect_to schedule_path 31 else 32 render :edit 33 end 34 end 35 36 def destroy 37 @schedule.destroy 38 redirect_to root_path 39 end 40 41 private 42 43 def schedule_params 44 params.require(:schedule).permit(:start_date, :end_date, :client, :title, :content, { item_ids: [] }).merge(user_id: current_user.id) 45 end 46 47 def set_schedule 48 @schedule = Schedule.find(params[:id]) 49 end 50end

試したこと

  • uniqueness: { scope: [:start_date, :end_date] }の記述が間違っていないか
  • 中間テーブルにそもそも:start_date, :end_dateが存在していないためエラーになる?

 scheduleモデル側のitemsの部分に記述したが、別のエラー文が表示された

NoMethodError in SchedulesController#create undefined method `read_attribute' for #<Item::ActiveRecord_Associations_CollectionProxy:0x00007f9734056068> Did you mean? arel_attribute

エラー文の読み取りが足りていないことは承知していますが、ご指導いただければと思います。
宜しくお願いいたします。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

「中間テーブルにそもそも:start_date, :end_dateが存在していないためエラーに」なります。
「scheduleモデル側のitemsの部分に記述した」とはどう記述したのでしょう。

で、
この場合は標準のvalidationには無いのでは、とおもいます。
ので
validate :uniqueness_of_なんとか
として
def uniqueness_of_なんとか start_date = schedule.start_date end_date = schedule.end_date if Schedule.joins(:schedule_items).exists?(item と 時刻で条件書く) errors.add() false else true end end
とでもするのかな。
ああ、createはこれでよいけどupdateのときは、「自分以外で」の条件も必要

投稿2021/02/02 13:54

winterboum

総合スコア23347

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問