2

I'm trying to add validation to foreign key fields in rails and constraints in postgres db.

Let's say there is a user. User has_many :products and product belongs_to :user. In this case the situation is easy since user is created for sure when a new product gets added. So validates: user, presence: true can be added to the product model and user_id, null: false can be added in the postgres db.

But what if the parent child object and the object get created at same time. Let's say in the product form I have product_features as nested attributes. So product has_many :product_features and product_feature belongs_to :product.

According to Rails 4 Way: "When you’re trying to ensure that an association is present, pass validates_presence_of its foreign key attribute, not the association variable itself. Note that the validation will fail in cases when both the parent and child object are unsaved (since the foreign key will be blank)."

How can I implement the model validations and the db constraints on foreign key fields in this case?

3 Answers 3

2

Truth is that validating the presence of the key itself (eg. product_id) is fairly useless anyway, because @product_feature.product_id = -25 will pass validation.

I always do the presence validation on the association:

validates :product, presence: true

That will work no matter which way you create your objects:

ProductFeature.new product: Product.new

...or...

Product.new product_features: [ ProductFeature.new ]

I'm not sure why anyone would recommend anything else, validating on the key itself does not guarantee that the key exists in the DB.

Sign up to request clarification or add additional context in comments.

7 Comments

Yeah, I do it that way in rails just didn't express myself properly. But as for db, there is nothing like that. Mike Perham http://www.mikeperham.com/2012/05/05/five-common-rails-mistakes/#more-833 recommends the foreign_key version. This validation is not perfect but way better than nothing. Okay so, there won't be problem on the rails side, but what about postgres? If I add the null constraint to db, will it work with nested attrs?
Also found this gem with 2 million DL: github.com/matthuhiggins/foreigner
Yes, the null constraint (and/or foreign key constraints) will be fine with nested attributes, Rails saves in the right order.
Thx Smathy, last question. What would you use in db on the foreign key field: null constraint or foreign key constraint or both? It's pretty hard to find clear answers on this topic.
Well they're for different purposes. The foreign key constraint makes sure that if the field is set then its set to a valid id, then the null constraint is whether that association is mandatory or not.
|
2

In this case, you can just create your custom validation method in model.

Write the following validation method in Product model to ensure that a product has product_features.

 validate :product_features

 def product_features
   product_features.present?
 end

8 Comments

Product_feature is not necessary. I need the other way around. If user decides to add product_feature to product then the app and db should make sure the product_id exists in the product_feature table.
That is simple. validates_presence_of :product in ProductFeature model. Use nested form for this case, you will never have any product_feature without product.
And what do you think about the db side? Null constraint can cause problems?
The call will never reach to db level unless you specify rails to avoid validations on save.
I know that officially this is the case, but db is way more important than app validation. mikeperham.com/2012/05/05/five-common-rails-mistakes/#more-833
|
1

This doesn't answer your question directly, but when using nested forms you should build the object like:

Product.product_features.new

This way you will be sure that you have product_id in product_feature

6 Comments

I use it that way. Just the rails 4 way comment made me confused, since I don't know what exactly happens in the case of nested attributes.
If you use it this way you don't need that validation, the object is created using product_id.
What do you think about the null constraints in the db side?
Null product_id or other attributes?
Exactly null constraint in the product_features table on the product_id field in postgres.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.