Ruby on rails 尝试在rails中添加具有重复索引的条目时避免异常
我有3种型号:Ruby on rails 尝试在rails中添加具有重复索引的条目时避免异常,ruby-on-rails,Ruby On Rails,我有3种型号: 使用者 谜题 解决方案 解决方案表示用户第一次解决给定的难题。我只想记录第一次的时间-后续尝试不算数。该解决方案有一个关于用户拼图组合的索引 我的迁移如下所示: class CreateSolutions < ActiveRecord::Migration[6.0] def change create_table :solutions do |t| t.integer :time t.integer :attempts t
- 使用者
- 谜题
- 解决方案
class CreateSolutions < ActiveRecord::Migration[6.0]
def change
create_table :solutions do |t|
t.integer :time
t.integer :attempts
t.references :user
t.references :puzzle
t.timestamps
end
add_index :solutions, [:user_id, :puzzle_id], unique: true
end
end
问题是,第二次尝试保存拼图时,我遇到了一个异常:
目标:我希望它只是默默地忽略后续的保存,而不是抛出异常
以下是我在solutions_controller.rb中尝试过的内容:
if@solution.save(验证:false).
if@solution.save(:validate=>false).
if@solution.save(false).
理想情况下,我只想跳过重复索引的验证-我想捕获其他错误。在解决方案模型中,您可以添加
验证以下内容的唯一性:用户id,范围::谜题id
每次尝试保存解决方案记录时,它都会运行select查询。如果存在select query solution.save的记录,则会出现错误
或者您可以使用first\u或\u初始化
Solution.where(user\u id:current\u user.id,puzzle\u id:params[:puzzle][:id])。首先\u或\u初始化(Solution\u params)
这将检查给定查询的记录是否存在。如果该记录不存在,它将在where条件和解决方案参数中分配属性
更新
def创建
@解决方案=解决方案。其中(用户\u id:current\u user.id,拼图\u id:params[:拼图][:id])。首先\u或\u初始化(解决方案\u参数)
回应待办事项|格式|
如果@solution.save
format.json{render:show,status::created}
其他的
format.json{render json:@solution.errors,status::unprocessable_entity}
结束
结束
结束
如果这样做,则无需检查错误消息,如果表中已存在该记录,则会将其分配给@solution,而不会分配solution params中的数据。如果记录不存在@solution将被分配where条件和解决方案参数中的数据(用户id和谜题id值将取自where条件中给出的值,其他值取自解决方案参数)。如果在where条件和解决方案参数中给出属性数据,则将采用解决方案参数值。在解决方案模型中,您可以添加
验证以下内容的唯一性:用户id,范围::谜题id
每次尝试保存解决方案记录时,它都会运行select查询。如果存在select query solution.save的记录,则会出现错误
或者您可以使用first\u或\u初始化
Solution.where(user\u id:current\u user.id,puzzle\u id:params[:puzzle][:id])。首先\u或\u初始化(Solution\u params)
这将检查给定查询的记录是否存在。如果该记录不存在,它将在where条件和解决方案参数中分配属性
更新
def创建
@解决方案=解决方案。其中(用户\u id:current\u user.id,拼图\u id:params[:拼图][:id])。首先\u或\u初始化(解决方案\u参数)
回应待办事项|格式|
如果@solution.save
format.json{render:show,status::created}
其他的
format.json{render json:@solution.errors,status::unprocessable_entity}
结束
结束
结束
如果这样做,则无需检查错误消息,如果表中已存在该记录,则会将其分配给@solution,而不会分配solution params中的数据。如果记录不存在@solution将被分配where条件和解决方案参数中的数据(用户id和谜题id值将取自where条件中给出的值,其他值取自解决方案参数)。如果在where条件和解决方案参数中给出了属性数据,则将采用解决方案参数值。谢谢-第一个
验证唯一性方法似乎捕捉到错误,但它可以工作。我可以检查@solution.errors.messages[:user\u id]
是否为“已采取”并仅忽略该情况。第二种方法也有效,但我对此感到困惑。只有当我仍然在控制器中使用@solution=solution.new(solution_params)
等初始化模型时,它才起作用。但我看不出我在哪里实际使用了我初始化的@解决方案。我的if块现在看起来是这样的:if Solution.where(user\u id:current\u user.id,puzzle\u id:@Solution.puzzle.id)。首先\u或\u初始化(Solution\u params).
-我不再调用@Solution.save
。我已经更新了答案,请查看。如果记录已经存在,我相信您不想更新它。我现在明白了-再次感谢。与您的示例不同的唯一一件事是指定puzzle\u id:params[:puzzle]
,而不是params[:puzzle][:id]
params
只是POST参数,所以它们是简单的名称/值对。除非有一种方法可以让拼图对象得到扩展,而我却忽略了这种方法?我的错误被弄糊涂了,理想情况下,它应该作为puzzle\u id发送到解决方案对象中。因为它被命名为puzzle,我认为它可能是来自params的puzzle对象。谢谢-第一个验证了方法的唯一性似乎捕捉到了错误,但它可以工作。我可以检查@solution.errors.messages[:user\u id]
是否为“已采取”并仅忽略该情况。第二种方法也有效,但我对此感到困惑。只有当我仍然在控制器中使用@solution=solution.new(solution_params)
等初始化模型时,它才起作用。但我看不出我在哪里实际使用了我初始化的@解决方案。我的if块现在看起来像这样:if解决方案。其中(user\u id:current\u user.id,puzzle\u id:@solu
def create
@solution = Solution.new(solution_params)
@solution.user = current_user
@solution.puzzle = Puzzle.find(params["puzzle"])
respond_to do |format|
if @solution.save
format.json { render :show, status: :created }
else
format.json { render json: @solution.errors, status: :unprocessable_entity }
end
end
end
ActiveRecord::RecordNotUnique in SolutionsController#create
Mysql2::Error: Duplicate entry '28-13' for key 'index_solutions_on_user_id_and_puzzle_id'