Validating form data without saving

Hello,

I got a form that feeds data to 2 models: Topic and Post.

@topic = Topic.new(params[:topic])
@post = Post.new(params[:post])

if @topic.save

  @post.topic_id = @topic.id
  @post.save

end

Now if there is an error in the Topic data RoR will catch it. But if
the Post fails validation the Topic still gets created. So what would
like to do is doing a test on each object and then save.

Did google the topic but did not hit the nail on the head.

Best regards.
Asbjørn Morell.

Hello,

I got a form that feeds data to 2 models: Topic and Post.

@topic = Topic.new(params[:topic])
@post = Post.new(params[:post])

if @topic.save

@post.topic_id = @topic.id
@post.save

end

Now if there is an error in the Topic data RoR will catch it. But if
the Post fails validation the Topic still gets created. So what would
like to do is doing a test on each object and then save.

Just call the valid? method

Fred

Hmmm just gave it a try:

if @post.valid? and @topic.valid?

  @topic.save
  @post.topic_id = @topic.id
  @post.save

end

The "if" condition does not seem to care about the Post validation.
Topic validation works as it should :confused:

Any ideas?

Problem solved. valid? was the method I was looking for.

Thanks.

You could for example add

   validates_associated :topic

to the Post model and then:

   post = Post.new(params[:post])
   post.build_topic(params[:topic])
   if post.save
     # both post and topic are valid
   else
     # at least one of them is invalid, you got all errors in one shot
   end

That said, in AR I normally work from the parent downwards:

   topic = Topic.new(params[:topic])
   topic.posts.build(params[:post])
   topic.save

In any case, if the associated object is invalid you have an error in
the "root" object telling so, and the particular errors in the child.

I forgot to mention in that alternative you put

   validates_associated :posts

in the Topic model.

Watch out: "and" is not the same as "&&"

if @post.valid? and @topic.valid? # equivalent to @post.valid?; if
@topic.valid?

See http://www.pjhyett.com/posts/201-using-or-and-in-ruby for more
details.

I think you really just want a transaction here. If you don't want
the Topic created when the post fails, you can do the following:

Post.transaction do
  @topic = Topic.new(params[:topic])
  @post = Post.new(params[:post])

  if @topic.save
    @post.topic_id = @topic.id
    @post.save
  end
end

If one fails, all fail and you don't get the unwanted saves.

-Kevin

Problem is if @topic.save fails and @post is invalid you are not able
to show @post's validation errors to the user in the same view.