One form, multiple models, custom validation

Hi everyone,

I hope someone can help me solve this problem.
I have a model called Project with :has_many => :tasks. In the new
Project form i allow the creation of 1 to n tasks on the fly thanks to
accepts_nested_attributes_for, where the task model has some validations
that block the creation of the new project if the required fields are
not correct.

This works just fine as it is supposed to work, but here's the problem:

At least one task needs to have some fields not empty, otherwise the
project should not be created. It can be any of the tasks but it's
imperative that at least one of them has those attributes, for the other
tasks these attributes are not required.
Is there a way of doing that without strange hacks?

Thanks in advance for your help

Hi Serafino,

I am assuming that you are using Javascript. If that is the case, then you can find the solution here http://stackoverflow.com/questions/1704142/unobtrusive-dynamic-form-fields-in-rails-with-jquery

All the best,

Fidel.

Would this not be the proper solution ?

User has many payments. I want the user to have at
least one payment with an amount, before a user is
valid.

class User < ActiveRecord::Base
  default_scope :order => :id
  has_many :payments
  validate :has_one_complete_payment

private

  def has_one_complete_payment
    errors.add(:base, :missing_complete_payment) unless payments.detect
{|p| p.amount}
  end
end

$ cat config/locales/en.yml
en:
  hello: "Hello world"
  activerecord:
    errors:
      models:
        user:
          attributes:
            base:
              missing_complete_payment: You need at least one payment
with amount filled out

That results in this behaviour:

$ rails c
Loading development environment (Rails 3.0.3)
001:0> user = User.new(:first_name => "Jon")
=> #<User id: nil, first_name: "Jon", last_name: nil, user_name: nil,
testing: nil, created_at: nil, updated_at: nil>
002:0> user.valid?
=> false
003:0> user.errors
=> #<OrderedHash {:base=>["You need at least one payment with amount
filled out"]}>
004:0> p1 = user.payments.build()
=> #<Payment id: nil, user_id: nil, testing: nil, created_at: nil,
updated_at: nil, amount: nil>
005:0> user.valid?
=> false
006:0> user.errors
=> #<OrderedHash {:base=>["You need at least one payment with amount
filled out"]}>
007:0> p2 = user.payments.build()
=> #<Payment id: nil, user_id: nil, testing: nil, created_at: nil,
updated_at: nil, amount: nil>
010:0> user.valid?
=> false
011:0> user.errors
=> #<OrderedHash {:base=>["You need at least one payment with amount
filled out"]}>
012:0> p2.amount = "123.45"
=> "123.45"
013:0> user.valid?
=> true
014:0> user.save
=> true
015:0> user.payments.inspect
=> "[#<Payment id: 1, user_id: 1, testing: nil, created_at: \"2010-12-23
21:57:01\", updated_at: \"2010-12-23 21:57:01\", amount: nil>, #<Payment
id: 2, user_id: 1, testing: nil, created_at: \"2010-12-23 21:57:01\",
updated_at: \"2010-12-23 21:57:01\", amount:
#<BigDecimal:b6cbb554,'0.12345E3',8(12)>>]"
015:0>

HTH,

Peter