rails 4 validating associated object + db constraint
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?
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
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.
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
This doesn't answer your question directly, but when using nested forms you should build the object like:
This way you will be sure that you have product_id in product_feature