Ruby on Rails: validate the presence and existence of an association - ruby-on-rails

I would like to know if there is a way in rails to validate the presence (AND existence in the database) of an association without using any additional gem if possible (i.e the associated "belongs_to" object is in the database and valid before saving).
validates_presence_of does not work because you can use a newly created and unsaved object.
I know all about the validates_existence gem but I would like to avoid it if possible.

You can use validates_associated in conjunction with validates_presence_of.
validates_associated will run validations on the associated model (which you have to define in that model).
validates_presence_of validates presence of the association.
EDIT
Addressing your comment: not a common scenario to validate presence in db specifically, but you can do this:
validate :association_exists
def association_exists
# query database for the association record and return true if it exists
# self is model instance inside this method
end

Related

Rails pattern or gem for notifying associations of model changes

In my app I have a number of issues which fall under the general pattern of:
Model with association
Association relies on some property of model and therefore caches it
Model changes
Association breaks because cached property is out of date
Is there a specific rails gem or pattern that would allow you to perform something like this on the model:
on_change :currency, notify: :booking
Then on the association:
on_notification :currency, :update_currency
Or something along those lines?
I can see that you could do it easily enough with observers or callbacks but would like to DRY this up

Rails: before_creating one model, go create a second model first

I have 2 models - User and Alias, where User has_many :aliases.
When creating a User, it must be unique to any Alias that already exists.
When a User is created, they also get an Alias saved with that User's name.
Here is the code for my User.rb model
validates_associated :aliases # bring in any validations from relationship models
before_create :create_alias
def create_alias
a = self.aliases.new
a.alias = username
return a.save
end
The alias model validation is validates_uniqueness_of :alias.
My theory is, that before I create a User model go create an Alias model and if that fails, then creating the User model should also fail.
However, when it fails, rails is exploding.
It's not doing the validates_associated properly.
How can I accomplish what I want to do?
check this http://guides.rubyonrails.org/association_basics.html#has-many-association-reference, you can use the :autosave and :validate options when you define the association so you can just remove that validates_associated and your before_create callback and let rails handle those actions
has_many :aliases
EDIT: I think the problem is that you are assigning new alias AFTER the validations! so, you have to build the new alias right when you assign the username of after validations
def username=(value) #custom setter for username
aliases.build(alias: value)
write_attribute(:username, value)
end
now the alias will be there before the validations and user.valid? will run the alias' valdations too when validating
This must be impossible to do in a model. At least with devise...
To fix this problem I just gave up trying and moved the config to the controller with something like this:
#user.aliases.build(:name => #user.username)

how can i validate the nested attributes field in rails 4?

I have two models
class Information < ActiveRecord::Base
belongs_to :study
validates_presence_of :email
end
and
class Study < ActiveRecord::Base
has_many :informations
accepts_nested_attributes_for :informations
end
I show up a form of study which contains few fields for the informations and i want to validate presence of those fields. Only on validation success i wanted to save the study field values as well and i wanted to show errors if the validation fails. How can i do this? Thanks in advance.
You write validations in the models that you require, as normal. So if you need to validate presence of field foo in the Information class you'd just write validates_presence_of :foo in that class. Likewise validations for Study fields just go in the Study class. With nested attributes, when you update a Study instance from a params hash that contains nested attributes, it'll update the Information instance(s) too, running validations in passing. That's what the accepts_nested_attributes_for call is doing - it's giving "permission" for the appropriate bits of a params hash to be used in this way.
You can use reject_if to only reject new nested records should they fail to meet criteria. So I might let someone create a Study and only create one or more nested Information instances associated with that Study if they'd filled in field(s) in the form, but if they left them blank, the nested stuff wouldn't be created and saved (so you don't get pointless blank associated records). The Study would still be saved. For example:
accepts_nested_attributes_for(
:informations,
reject_if: proc() { | attrs | attrs[ 'title' ] .blank? }
)
This and more is covered in the API documentation here:
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Beware that nested fields are intended for existing records only. If you were creating a new Study instance in a new/create action with no Information instances associated, you won't see any nested form fields for your Information class at all - when you might be expecting just one, for a blank new item. This can be very confusing if you aren't ready for it! You'll need to manually add a new Information instance to your Study instance in the controller or similar for the 'new' and 'create' actions, e.g. using before_filter :create_blank_object, only: [ :new, :create ], with, say:
def create_blank_object
#study = Study.new
#study.informations << Information.new
end
you can use validates_presence validation available in rails other wise you can write before_create or before_save callback method. write validation logic inside the before_create or before_save callback method.
Check out the API Doc for validates_associated:
Validates whether the associated object or objects are all valid. Works with any kind of association.
If you call a method on the parent object which runs validations (e.g. save), the validation on the associated objects will be called as well.

Ruby on Rails: How to validate a model without Active Record?

I'm currently trying to validate fields without having an ActiveRecord::Base inheritance.
My model stores the data on a cache server so I do not need ActiveRecord.
Anyway, I would like to validate the fields of the model like I would if I was using ActiveRecord (e.g validates_numericality_of :quantity, :greater_than => 0) ?
How can I do that?
Thank you very much for your help.
In Rails 3, Active Model contains the non-database functionality of Active Record.
Basically, you need to include ActiveModel::Validations, define your fields as attr_accessor, use an initialize method to initialize the attributes and make them non-persisted as your model isn’t persisted to a database.
This way you can have validations on the tableless model and your controller the same as if you were using Active Record. There's also a Railscast on this http://railscasts.com/episodes/219-active-model.
Check out our Veto gem instead if you're looking for a standalone validations for ruby objects. It's lightweight, and has no dependencies.. ActiveModel might be overkill.

How to validate that a parent object has a valid child object (Rails)

Let's say I have an ActiveRecord model called Book that has a has_many association with a model Pages.
class Book < ActiveRecord::Base
has_many :pages
end
I'd like to know if there is an established method of ensuring that a Book object cannot be saved to the database without having at least one valid Page object associated with it. My goal is not to test the presence of an association, but to validate that a parent object indeed has a valid child object. Does this make sense? Is this actually a case of testing an association? I'm familiar with the "validates_associated" method, but this validation will not fail if the association hasn't been assigned, but how do I ensure that there is a valid object on the other side of the association?
From the Rails 2.3.2 documentation for validates_associated:
NOTE: This validation will not fail if
the association hasn’t been assigned.
If you want to ensure that the
association is both present and
guaranteed to be valid, you also need
to use validates_presence_of.

Resources