Ruby on rails 关于如何使用has_MUN:through关系正确设置验证的指导?

Ruby on rails 关于如何使用has_MUN:through关系正确设置验证的指导?,ruby-on-rails,Ruby On Rails,我已经建立了三个模型:User、List和UserList——后者是用户和List之间的连接模型,在关系中有多个连接 我正在尝试设置我认为应该是相当普通的唯一性约束——但它不太管用。非常感谢您的指导/建议 技术细节 我有3种型号: class User < ApplicationRecord has_many :user_lists has_many :lists, through: :user_lists, dependent: :destroy End class List

我已经建立了三个模型:User、List和UserList——后者是用户和List之间的连接模型,在
关系中有多个连接

我正在尝试设置我认为应该是相当普通的唯一性约束——但它不太管用。非常感谢您的指导/建议

技术细节 我有3种型号:

class User < ApplicationRecord
  has_many :user_lists
  has_many :lists, through: :user_lists, dependent: :destroy
End

class List < ApplicationRecord
  has_many :user_lists
  has_many :users, through: :user_lists, dependent: :destroy

  # no duplicate titles in the List table
  validates :title, uniqueness: true
End

class UserList < ApplicationRecord
  belongs_to :list
  belongs_to :user

  # a given user can only have one copy of a list item
  validates :list_id, uniqueness: { scope: :user_id }
end

这将正确地导致创建新的列表记录和关联的UserList记录。万岁

作为亚当,如果我再次尝试将相同的标题“黑暗骑士”添加到我的列表中,什么都不会发生——包括控制台上没有错误。万岁

但是--作为用户Beatrice,如果我登录并现在尝试将“黑暗骑士”添加到我的列表中,我现在会在控制台中收到一个错误:

POSThttp://localhost:3000/api/v1/lists 422(不可处理实体)

我的调试和假设 如果我删除List.title上的唯一性约束,这个错误就会消失,Beatrice可以将“黑暗骑士”添加到她的列表中

然而,这个列表包含了两条记录,都被命名为“黑暗骑士”,这似乎是多余的

作为Adam,它看起来可能是
current\u user.lists.find\u或\u create\u by!(list_params)
在我的控制器操作中,查找与我当前用户关联的现有“黑暗骑士”列表,并意识到它的存在——从而不会触发创建操作

然后作为Beatrice,似乎同一控制器操作没有找到与我当前用户关联的现有“黑暗骑士”列表项——因此它尝试触发创建操作

但是,此创建操作尝试创建一个标题已存在的新列表项,即它与List.rb模型唯一性验证冲突

我不知道如何修改find_或create_by action或模型验证,以确保为Beatrice创建新的UserList记录/关联,但不创建新的List记录(因为它已经存在)


我觉得我可能错过了一些简单的东西。也许不是。如果您能提供一些关于如何进行的指导,我将不胜感激。谢谢

我99%确定发生的是
当前用户。列表。查找或创建用户将只搜索用户有用户列表条目的列表记录。因此,如果列表存在,但当前用户没有关联,它将尝试创建一个与现有列表冲突的新列表

假设这就是问题所在,您需要独立于用户关联来查找列表:
@List=List.find\u或\u create\u by(List\u参数)


一旦有了该列表,就可以通过关联或UserList模型创建UserList记录。如果你想要简洁,我想你可以使用
current\u user.lists我99%确定发生的事情是
current\u user.lists.find\u或\u create\u by
将只搜索用户有用户列表条目的列表记录。因此,如果列表存在,但当前用户没有关联,它将尝试创建一个与现有列表冲突的新列表

假设这就是问题所在,您需要独立于用户关联来查找列表:
@List=List.find\u或\u create\u by(List\u参数)



一旦有了该列表,就可以通过关联或UserList模型创建UserList记录。如果您希望简洁,我想您可以使用
current_user.lists出于好奇,您将传递什么作为list_参数?此外,您的rails服务器控制台确切地说错误是什么?http错误对调试没有多大帮助以
End
结尾的代码不是有效的Ruby代码。@sawa您能解释一下为什么它不是有效的Ruby代码吗?我发现Ruby/Rails上的学习曲线非常陡峭,这里有点不对劲。我相信他们的观点是大写字母E最终使它不是Ruby的正确结束关键字,但我猜这是复制的结果?出于好奇,你传递的列表参数是什么?另外,Rails服务器控制台到底说错误是什么?http错误对调试没有多大帮助以
End
结尾的代码不是有效的Ruby代码。@sawa您能解释一下为什么它不是有效的Ruby代码吗?我发现Ruby/Rails上的学习曲线非常陡峭,这里有点不对劲。我相信他们的观点是大写字母E最终使它不是Ruby的正确结束关键字,但我猜这是复制的结果?很高兴我能提供帮助!我做了两次修改。但不完全确定它们为什么会起作用——也不确定它们是否值得提出一个新问题——但想知道你/其他人是否会这样做?1.a)使用
current\u user.lists 1.b)如果我将其更改为
current\u user.user\u lists.create(:list\u id=>list.id)
,如果Adam尝试两次添加相同的标题,我不会在浏览器开发控制台第二次出现错误,rails控制台显示:
UserList Exists(0.3ms)从“user\u list”中选择1作为一个,其中“user\u lists”。“list_id”=$1和“user_list”。“user_id”=$2 LIMIT$3…在10毫秒(ActiveRecord:1.6毫秒)内完成了204个没有内容的操作。
-->我是否对这两种不同的方法的工作原理缺乏一些基本的了解,以至于一种方法报告错误,而另一种方法不报告错误?其他修改:在我的user.rb模型中,我添加了一个
->{distinct}
选项。我的控制器“获取/索引”操作实际上从连接模型中提取额外的列(
当前用户列表。连接(:用户列表)。选择('lists.*,user\u lists.id作为用户列表id,user\u lists.rating作为评级
),这似乎导致了“黑暗骑士”和“为单个用户返回的条目。因此,1a是我所说的关于如果UserList已经存在,它将如何处理的不确定性。它似乎处理得不太好,因此您必须首先检查它是否存在,或者做一次检查。”
class AddIndexToUserLists < ActiveRecord::Migration[5.2]
  def change
    add_index :user_lists, [:user_id, :list_id], unique: true
  end
end
# POST /lists
    def create
      @list = current_user.lists.find_or_create_by!(list_params)
    end
def create
    @list = List.find_or_create_by!(list_params)
    current_user.lists << @list
end