Ruby on Rails Sunday, January 25, 2015

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

On Thursday, January 22, 2015 at 2:50:43 PM UTC-8, pruchai wrote:

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? 

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/c3890caa-7838-4426-97e9-7d70704212dd%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment