Relationship issues....

Rails relationships that is

I am doing something wrong, and can’t figure out what and where.

I have 3 models - Command, Contact, and a joined CommandsContact via has_many through relationship, because commands_contacts table holds an extra column - notification_type, which could be either set to host of *service. *

**Models **

contact.rb

This one is a special case, because it has 2 extra “virtual” relationships**:host_notification_commands and :service_notification_commands, which gives me an ability to selectively get either host or service commands for a user (contact) like this:

Contact.first.host_notification_commands or

Contact.find(3).service_notification_commands etc.

class Contact < ActiveRecord::Base

 has_many :commands_contacts, :inverse_of => : contact
has_many :commands, :through => :
 commands_contacts
has_many :host_notification_commands, -> { where commands_contacts: { :notification_type => 'host' } },
          :through => :commands_contacts,
          :class_name => 'Command',           
:source => :
 command
has_many :service_notification_commands, -> { where commands_contacts: { notification_type: 'service' } },
          :through => :commands_contacts,
          :class_name => 'Command',           
:source => :
 command
accepts_nested_attributes_for : host_notification_commands
accepts_nested_attributes_for :
service_notification_commands
end

command.rb

class Command < ActiveRecord::Base

  has_many :commands_contacts, :inverse_of => :command
  has_many :contacts, :through => :
commands_contacts
  accepts_nested_attributes_for :
commands_contacts
end

commands_contracts.rb

class CommandsContact < ActiveRecord::Base

 belongs_to : command
belongs_to :
 contact
accepts_nested_attributes_for : command
accepts_nested_attributes_for :
contact
end

So far. So good. This works as expected (i think?) as I am able to manually create relationships, as long as i have a contact and a command already.

contact = Contact.first
command = Command.find(7)
contact.host_notification_commands << command

Aaand after this things start to go down south, because a Controller, strong_parameters and accepts_nested_attributes_for come into play, and this is where I fail.

My assumption is that Rails will be able to handle this for me and establish the relationship, right?

def create
contact = Contact.new safe_params
contact.save
end

Because I use accepts_nested_attributes_for, I have to append _attributes to the names of nested objects, right? So i do a simple re-assignment here and then permit them with strong_parameters.

private
def safe_params
params[:contact][:host_notification_commands_attributes] = params[:contact][:host_notification_commands]
  params[:contact][:service_notification_commands_attributes] = params[:contact][:service_notification_commands]

  params.require(:contact)
      .permit(:contact_name, 
        :host_notification_commands_attributes => [ :id, :command_name, :command_line, :command_description ],
        :service_notification_commands_attributes => [ :id, :command_name, :command_line, :command_description ])

As far as I understand, this is all that needs to be done and Rails should handle the rest, right? The problem is that it does not even try to to establish a relationship. It does a SELECT and immediately fails.

When I try to create a new record, it fails with:

ActiveRecord::RecordNotFound (Couldn’t find Command with ID=1 for Contact with ID=):

Because it hasn’t yet created a user a hasn’t established a relationship.

When I try to edit and existing contact and establish a relationship with existing command, it fails with

(0.1ms) BEGIN

Command Load (0.2ms) SELECT commands.* FROM commands INNER JOIN commands_contacts ON commands.id = commands_contacts.command_id WHERE commands_contacts.contact_id = 3 AND commands_contacts.notification_type = ‘host’ AND commands.id = 1

(0.1ms) ROLLBACK

Completed 404 Not Found in 6ms

ActiveRecord::RecordNotFound (Couldn’t find Command with ID=1 for Contact with ID=3):

Uhm… Of course this relationship record is not found. I am trying to create it! Why does it run SELECT instead of UPDATE / INSERT ?

So, something tells me I have this relationship defined incorrectly somewhere in my models… but where? How do i troubleshoot this?

I got a suggestion that format of the data i’m POSTing may be incorrect, so I made a simple Rake task to remove external factors from the equation, but getting the same result as before, which leads me to believe the problem is somewhere in my models. But where?

Take a look at this gist

https://gist.github.com/pruchai/6afe74b170da2a3d307f