Skip to content

Instantly share code, notes, and snippets.

@firewalker06
Created May 10, 2014 15:27
Show Gist options
  • Save firewalker06/1b06fcc13e156c2715f7 to your computer and use it in GitHub Desktop.
Save firewalker06/1b06fcc13e156c2715f7 to your computer and use it in GitHub Desktop.
Trying to validate an attribute inside a child model with a condition that depends on the parent's attribute value.

I have two models, Post and Tag. This is not my real scenario. In order to simplify it, lets assume that:

  • each Post can have many Tags,
  • Tag name can be saved as empty when Post's status is :draft. The reason is so that user could not be bothered with validation when all they want is just save Post as a draft.

This is the models that I have in mind:

# Post model
class Post < ActiveRecord::Base
  has_many :tags
  enum status: [:draft, :published]
  validates_presence_of :title
  accepts_nested_attributes_for :tags
end

# Tag model
class Tag < ActiveRecord::Base
  belongs_to :post
  # Validates Tag's name only when Post has published status
  validates_presence_of :name, if: post.published?
end

And it doesn't work because Post isn't accessible / defined inside Tag model. So, my code is plain wrong, but my question is, is this the right approach? What should I do to solve this scenario?

@jefflunt
Copy link

This might work:

http://stackoverflow.com/questions/9535012/rails-validate-that-object-has-one-or-more-associated-objects-has-many-relati

The idea is that you check to make sure there's at least one tag on the association. Combine that with your conditional if: published? and that should work for you.

It seems like putting the validation on the Post model is the way to go. Putting it on the tag model doesn't make sense, right, because you don't care about validating the tags based on the state of the post - you care about forcing the post to have at least one tag before being published, correct?

So, try this (or something very close to this) and let me know how it goes. On the Post model:

validates :tags, :length => { :minimum => 1 }, unless: 'status = "draft"'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment