Comments (7)
Currently, there's no other option to address this at the application level using validations.
One way to 'fix' this is by adding a unique index between order_line_id and resource_id.
Even if the validation worked, doing it at the DB level would also prevent invalid records from being saved due to race conditions, as explained hereAs you can see in the example I gave, this is what I did. That's also the reason why I have an
ActiveRecord::RecordNotUnique
error related to PG instead of the records being created successfully.But I wanted to have an
ActiveRecord::RecordInvalid
in order to fall in the "standard" error handling process, and gracefully manage localisation of the error & stuff like that, which is not very smooth with db-level errors.I'll go with a custom validation on the parent model. Probably something like this:
validate :unique_order_line_resources def unique_order_line_resources return if order_line_resources.length == order_line_resources.map(&:container_resource_id).uniq.length errors.add(:order_line_resources, :record_not_unique) endThanks for your help!
Oops, sorry! I should have read the example more carefully.
Another solution would be to rescue the ActiveRecord::RecordNotUnique
exception and add the error to the record. However, I know this can become messy and hard to maintain depending on the complexity of the codebase.
order_line = OrderLine.create!
begin
order_line.update!(order_line_resources_attributes: [{ resource_id: 1 }, { resource_id: 1 }])
rescue ActiveRecord::RecordNotUnique
order_line.errors.add(...)
end
from rails.
Can you create a reproduction test script using this template https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record.rb ?
from rails.
Of course 🙂 here it is:
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails"
# If you want to test against edge Rails replace the previous line with this:
# gem "rails", github: "rails/rails", branch: "main"
gem "sqlite3"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :order_lines, force: true do |t|
end
create_table :order_line_resources, force: true do |t|
t.belongs_to :order_line, foreign_key: true
t.integer :resource_id
end
add_index :order_line_resources, %i[order_line_id resource_id], unique: true
end
class OrderLine < ActiveRecord::Base
has_many :order_line_resources
accepts_nested_attributes_for :order_line_resources
validates_associated :order_line_resources
end
class OrderLineResource < ActiveRecord::Base
belongs_to :order_line
validates :order_line_id, uniqueness: { scope: :resource_id }
end
class BugTest < Minitest::Test
def test_association_stuff
order_line = OrderLine.create!
order_line.update!(order_line_resources_attributes: [{ resource_id: 1 }, { resource_id: 1 }])
end
end
I didn't write assertions, but the test should fail with this error ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: UNIQUE constraint failed: order_line_resources.order_line_id, order_line_resources.resource_id
, but I would expect an instance of ActiveRecord::RecordInvalid
.
from rails.
This is the same problem as described in #4568 and more linked issues/PRs. Uniqueness validation works only on the persisted records. When you assign order_line_resources_attributes
, both records are valid, because there are no duplicates in the database for each of them. But when you try to save, then the problem arises.
from rails.
This is the same problem as described in #4568 and more linked issues/PRs. Uniqueness validation works only on the persisted records. When you assign
order_line_resources_attributes
, both records are valid, because there are no duplicates in the database for each of them. But when you try to save, then the problem arises.
Yes, that's what I saw.
I was expecting a way to make it works properly without having to re-write a custom validation on the OrderLine
model, but I guess I have no other choice?
I'm probably too used to rails magic 😅 Thanks for your help!
from rails.
Currently, there's no other option to address this at the application level using validations.
One way to 'fix' this is by adding a unique index between order_line_id and resource_id.
Even if the validation worked, doing it at the DB level would also prevent invalid records from being saved due to race conditions, as explained here
from rails.
Currently, there's no other option to address this at the application level using validations.
One way to 'fix' this is by adding a unique index between order_line_id and resource_id.
Even if the validation worked, doing it at the DB level would also prevent invalid records from being saved due to race conditions, as explained here
As you can see in the example I gave, this is what I did. That's also the reason why I have an ActiveRecord::RecordNotUnique
error related to PG instead of the records being created successfully.
But I wanted to have an ActiveRecord::RecordInvalid
in order to fall in the "standard" error handling process, and gracefully manage localisation of the error & stuff like that, which is not very smooth with db-level errors.
I'll go with a custom validation on the parent model. Probably something like this:
validate :unique_order_line_resources
def unique_order_line_resources
return if order_line_resources.length == order_line_resources.map(&:container_resource_id).uniq.length
errors.add(:order_line_resources, :record_not_unique)
end
Thanks for your help!
from rails.
Related Issues (20)
- After Commit Callbacks Are Called When RELEASE SAVEPOINT HOT 3
- Downloading net-pop-0.1.2 HOT 3
- PG::SyntaxError on query serialize in Rails 7.2 HOT 13
- Association backed by ignored column can be accessed without error. HOT 4
- After touch callback does not run after destroy when using cache counter HOT 12
- ActiveJob::TestHelper#perform_enqueued_jobs no longer works in Rails 7.2 with default :async test adapter HOT 2
- Problem with cached_find_by and cached_find_by_statement HOT 1
- `BIND="::" rails s` fails HOT 6
- ActiveStorage `attach` errors in async context HOT 3
- Extend protect_from_forgery support to cross-domain frame embeds HOT 1
- Regression on `main` for `resources` with a hash
- Deprecate `config.active_job.enqueue_after_transaction_commit` config
- Enhanced I18n Interpolation with Piping HOT 3
- encrypts method must be called before using it on normalizes or attributes API HOT 11
- `require "active_support"` throws `cannot load such file -- active_support/core_ext/date_and_time/compatibility`
- `attributes_to_define_after_schema_loads` deprecation and recovery HOT 2
- Warnings for "Test is missing assertions" HOT 6
- It's not possible to override the `key_provider` or `key` using `ActiveRecord::Encryption.with_encryption_context` HOT 1
- Test names are missing after updating to 7.2 when running "rails test -v" HOT 4
- ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter equality is buggy
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rails.