Sebastian Wramba
Sebastian Wramba

Reputation: 10127

Validate multiple belongs_to relations

Let's say we have the following data structure (imagine as a loop).

MyModel * -- 1 User 1 -- * Clients 0 -- * MyModel

Thus, the MyModel looks like:

class MyModel < ActiveRecord::Base
  belongs_to :client
  belongs_to :user

  attr_accessible :user_id, :client_id, # ...

  validates :user_id, :presence => true

So it can belong to a client but must belong to a user. Also a client must belong to a user.

But how can I assert, that if someone saves a MyModel instance belonging to a client, that the client actually belongs to the user? Do I have to write a custom validator for this or is there any validation shortcut I overlooked?

Solution:

Following p.matsinopoulos' answer, I now did the following. I don't assign the foreign keys to MyModel before saving but rather the objects directly.

  # my_model_controller.rb

  def create
    m = MyModel.create(whitelist_parameters(params[:my_model]))
    m.user = current_user

    if(params[:my_model][:client_id].present?)          
      client = Client.find params[:my_model][:client_id]
    end

    # ...
  end

This way I can at first validate if there is a Client with such an ID at all. Then I implemented the custom validator by p.matsinopoulos. It's not tested yet, but since I am now working with the objects, it should do the trick.

Upvotes: 2

Views: 93

Answers (2)

p.matsinopoulos
p.matsinopoulos

Reputation: 7810

If I were you, I would have written a custom validator.

validate :client_belongs_to_user

protected

def client_belongs_to_user
  errors[:client] << 'must own the user' if client.present? && client.user != user
end

Upvotes: 1

lurker
lurker

Reputation: 58324

I would suggest, building on what you have:

class MyModel < ActiveRecord::Base
  belongs_to :client
  has_one :user, :through => :client

  attribute_accessor :client_id

  validates :client_id, :presence => true
  ...
end

class Client < ActiveRecord::Base
  has_many :my_models
  belongs_to :user

  attribute_accessor :user_id

  validates :user_id, :presence => true
  ...
end

class User < ActiveRecord::Base
  has_many :clients

  ...
end

Upvotes: 0

Related Questions