gpt4 book ai didi

ruby-on-rails - 在 Rails 中同时进行数据库级别和代码级别唯一性验证的目的是什么?

转载 作者:行者123 更新时间:2023-12-04 06:08:27 25 4
gpt4 key购买 nike

我在 Rails 中看到了一个同时具有数据库级和代码级验证的表。

CREATE UNIQUE INDEX some_index_name ON joined_table_name USING btree (user_id, restriction_id);

和代码级别:
class SomeJoinTable
validates_uniqueness_of :restriction_id, :scope => :user_id
end

两者兼得有什么好处?

最佳答案

引用 excellent article by thoughtbot :

When you persist a user instance, Rails will validate your model by running a SELECT query to see if any user records already exist with the provided email. Assuming the record proves to be valid, Rails will run the INSERT statement to persist the user. This works great in development and may even work in production if you’re running a single instance of a single process web server.

But you’re not running a lone instance of WEBrick, are you? No, to maximize requests per minute, you’re running Unicorn on multiple Heroku dynos, each with multiple web processes. Let’s take a look at what happens if just two of these processes are trying to create a user with the same email address at around the same time:


thoughtbot example image

...you can create the unique index when generating the migration or model with:

rails generate model user email:string:uniq

With the index in place, how does the above scenario play out now?


thoughtbot example image 2

Now we have the database acting as our last line of defense in our war on inconsistent data. The second save operation will generate an ActiveRecord::RecordNotUnique exception.

In Conclusion

Rails does many things, but data integrity validations are not one of them. Your relational database is designed to enforce data integrity; let it.


编辑
添加了为什么要使用 validates_uniqueness_of 的示例除了 db 约束(根据 OP 的评论):

I think it explains why you need database level validations, but my question also is asking why can't we just have database-level validations.


回答
进一步报价 thoughtbot's article :

The second save operation will generate an ActiveRecord::RecordNotUnique exception. In most cases, this will result in an application error. If you need to provide a better experience, you can rescue and handle that exception in the controller action or use rescue_from at the class level.


让我们在类里面看到这一点。
仅使用数据库级约束:
class Foo < ApplicationRecord
belongs_to :bar
validates_presence_of :name
end

class Bar < ApplicationRecord
has_many :foos
end

> Foo.create!(bar_id: 1, name: 'Poop')
> Foo.create!(bar_id: 1, name: 'Poop')
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_foos_on..."
使用数据库约束和应用程序级验证(a la validates_uniqueness_of):
class Foo < ApplicationRecord
belongs_to :bar
validates_presence_of :name
validates_uniqueness_of :name, scope: :bar_id
end

> Foo.create!(bar_id: 1, name: 'Poop')
> Foo.create!(bar_id: 1, name: 'Poop')
ActiveRecord::RecordInvalid: Validation failed: Name has already been taken

关于ruby-on-rails - 在 Rails 中同时进行数据库级别和代码级别唯一性验证的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44377495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com