简体   繁体   中英

How to validate presence of associated fields in Ruby on Rails

I have tables applications and business.

Applications
  has_many :business

Business
  belongs_to :applications

If I will create an Application, I should have at least one Business . I used link_to_add in the same form where I create applications.

I used validate_association :applciations but it didn't work.

You may be better to use validates_associated :

#app/models/business.rb
class Business < ActiveRecord::Base
   belongs_to :application
   validates :name, :other, param, presence: true
end

#app/models/application.rb
class Application < ActiveRecord::Base
   has_many :businesses
   validates_associated :businesses
end 

This gives you the ability to check the validity of any associated data you pass through the model. However, this will not determine if there is at least one associated business passed through your model.

--

Numerical Validation

You'll want to look at the following

The reject_if method in Rails will not give you the ability to check the number of associated items which have been sent. This will have to be custom coded, which the author of the above post has addressed (in 2012) by setting a custom constant:

#app/models/company.rb
class Company < ActiveRecord::Base
  OFFICES_COUNT_MIN = 1

  validates :name, presence: true
  validate do
    check_offices_number
  end
  has_many :offices
  accepts_nested_attributes_for :offices, allow_destroy: true

  private

    def offices_count_valid?
      offices.count >= OFFICES_COUNT_MIN
    end

    def check_offices_number
      unless offices_count_valid?
        errors.add(:base, :offices_too_short, :count => OFFICES_COUNT_MIN)
      end
    end
end

I have not tested this myself, but to explain how it works, you'll basically have a custom validator, which allows you to check whether the number of associated objects is less than or equal to the CONSTANT you assign in the class.

You can, of course, achieve this without a constant, but the above example should demonstrate how you're able to create the functionality where at least 1 associated item should be sent

Not sure if this is what you meant but you could do the following in your models eg

  has_many :businesses, dependent: :destroy
  validates :title, presence: true

and in the other model:

  belongs_to :application  
  validates :name, presence: true

You can use validates_presence_of

Validates that the specified attributes are not blank (as defined by Object#blank?), and, if the attribute is an association, that the associated object is not marked for destruction. Happens by default on save.

Example:

Applications
  has_many :businesses
  validates_presence_of :business

Business
  belongs_to :applications

Update:

I think you will be better to using accepts_nested_attributes_for

Nested attributes allow you to save attributes on associated records through the parent . By default nested attribute updating is turned off and you can enable it using the accepts_nested_attributes_for class method. When you enable nested attributes an attribute writer is defined on the model.

app/models/application.rb

Class Application < ActiveRecord::Base
   has_many :businesses
   accepts_nested_attributes_for :businesses, reject_if: :all_blank
end

#app/models/business.rb

 Class Business < ActiveRecord::Base
       belongs_to :application
 end

This will give you the ability to call the reject_if: :all_blank method -

:reject_if

Allows you to specify a Proc or a Symbol pointing to a method that checks whether a record should be built for a certain attribute hash. The hash is passed to the supplied Proc or the method and it should return either true or false. When no :reject_if is specified, a record will be built for all attribute hashes that do not have a _destroy value that evaluates to true. Passing :all_blank instead of a Proc will create a proc that will reject a record where all the attributes are blank excluding any value for _destroy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM