Reputation: 8461
I have a Group
model and a Message
model, each are HABTM. I'm trying to set a validation for my main form which is to send out a SMS to certain groups. Right now I have the body of message validated with presence: true
, that is working fine but in my Group model I want to validate name to be present but how to I have them both validate when I'm calling a create method in the messages controller? I'll show my code for more clarification.
Here is group.rb
class Group < ActiveRecord::Base
has_and_belongs_to_many :people
has_and_belongs_to_many :messages
validates :name, presence: true
end
Now message.rb
class Message < ActiveRecord::Base
has_and_belongs_to_many :groups
validates :body, presence: true
end
Here is my message_controller.rb
def create
@message = Message.create(message_params)
if @message.save
run_at_time = @message.send_at.present? ? @message.send_at : Time.zone.now
people = Person.in_groups(message_params[:group_ids])
if people.any?
people.each do |person|
person.delay(run_at: run_at_time).send_message(@message.body)
end
flash[:success] = "Messages on their way!"
end
redirect_to root_path
else
render "new"
end
end
For more understanding I want my form to display "Groups can't be blank" as well as "body can't be blank". If nothing is selected.
Upvotes: 1
Views: 704
Reputation: 26758
Using valid?
was the first thing that came to mind, but there is another way as well.
Model validations actually have built-in support for assoiations.
For example,
class Message
has_and_belongs_to_many :groups
validates :groups, presence: true
end
See this StackOverflow answer.
So this would cause save
to fail if the message had no groups.
There's always another way - you can override valid?
, which is called internally
by save
. For example:
class Message
def valid?(*args)
original_result = super(*args)
if self.groups.empty?
self.errors_add(:groups, "cannot be empty")
return false
end
return original_result
end
end
This is largely the same thing accomplished by validates :groups, presence: true
,
although I think presence: true
will also verify that the foreign keys refer to
valid records (rather than just checking that any associated record exist).
Calling valid?
has the side effect of loading up the errors
object. For example:
msg = Message.new
msg.errors.full_messages # => []
msg.valid? # => false
msg.errors.full_messages # => ["Name cant be blank", "Groups cant be blank"]
msg.save # => false
Upvotes: 1
Reputation: 61
If you want to validate multiple models before saving or collect all errors, you could do it by using model.valid?
method.
It will return true of false, depending on whether there are any errors. And errors will be added to model.errors
.
Upvotes: 2