开发者

HABTM Double-Nested fields_for

Interesting segment of code that I can't get to work. I have the following models/relationships (unnecessary code excluded)

class Service < ActiveRecord::Base
  belongs_to :service_category, :foreign_key => "cats_uid_fk"
  belongs_to :service_type, :foreign_key => "types_uid_fk"
  has_and_belongs_to_many :service_subtypes, :join_table => "services_to_service_subs"
  belongs_to :service_request, :foreign_key => "audits_uid_fk"

  accepts_nested_attributes_for :service_subtypes
end

class ServiceSubtype < ActiveRecord::Base
  belongs_to :service_types, :foreign_key => "types_uid_fk"
  has_and_belongs_to_many :services, :join_table => "services_to_service_subs"
end

The form displaying all this info:

<% form_for(@request, :url => { :action => :create }) do |form| %>
 <table>   

...other data...

 <% form.fields_for :services do |fields| %>
  <%= fields.hidden_field :cats_uid_fk %>
  <%= fields.hidden_field :types_uid_fk %>
  <% fields.fields_for :service_subtypes do |subtype| %>
   <%= subtype.hidden_field :id %>
  <% end %> 
 <% end %>   

 <p>
   <%= form.submit "Create", :class=>"hargray" %>
 </p>         
<% end %> 

And the controller to handle the submit:

def create
 logger.debug params[:service_request].inspect

 @request = ServiceRequest.new(params[:service_request])
 if session[:cus_id]
  @request.customer = Customer.find session[:cus_id]
 end

 begin      
  @request.save!
  flash[:notice] = "Information submitted successfully. You will be contacted by a customer service representative regarding the services you selected."
  redirect_to :controller => "customer", :action => "index"
 rescue Exception => exc
  flash[:notice] = "#{ format_validations(@request) } - #{exc.message}"
  render :action => "new"
 end

end

The html looks clean:

<input id="service_request_services_attributes_0_cats_uid_fk" name="service_request[services_attributes][0][cats_uid_fk]" type="hidden" value="1" />
  <input id="service_request_services_attributes_0_types_uid_fk" name="service_request[services_attributes][0][types_uid_fk]" type="hidden" value="1" />
  <input id="service_request_services_attributes_0_service_subtypes_attributes_0_id" name="service_request[services_attributes][0][service_subtypes_attributes][0][id]" type="hidden" value="2" />
   <input id="service_request_services_attributes_0_service_subtypes_attributes_0_id" name="service_request[services_attributes][0][service_subtypes_attributes][0][id]" type="hidden" value="2" />
  <input id="service_request_services_attributes_0_service_subtypes_attributes_1_id" name="service_request[services_attribute开发者_如何学Cs][0][service_subtypes_attributes][1][id]" type="hidden" value="4" />
   <input id="service_request_services_attributes_0_service_subtypes_attributes_1_id" name="service_request[services_attributes][0][service_subtypes_attributes][1][id]" type="hidden" value="4" />

The submitted parameters look like this:

{
...other data...
 "services_attributes"=> {
  "0"=> {
   "types_uid_fk"=>"1", 
   "service_subtypes_attributes"=> {
    "0"=>{"id"=>"1"}, 
    "1"=>{"id"=>"2"}, 
    "2"=>{"id"=>"3"}
   }, 
   "cats_uid_fk"=>"1"
  }
 }
}

I get back "undefined method 'service_subtype' for #" error and the only table not updated is the join table between the HABTM models. Any idea how to solve this or what is happening behind the scenes? I'm not sure I understand the "magic" happening behind this procedure to see it working. It seems like most say that HABTM doesnt work with nested attributes. Seems to be the case. Work arounds?


Assuming this isn't a copy paste error in the Service model, it could be the source of your problem.

 accepts_nested_attributes_for :services_subtypes

Should be

 accepts_nested_attributes_for :service_subtypes

The first arguments to accepts_nested_attributes_for should be an association as defined by a has_many, has_and_belongs_to_many or belongs_to statement.

Your second minor problem about the double generating of the hidden field comes from your inserting it into the fields_for section. fields_for automatically includes a hidden field for the id. Making it safe to remove the hidden field line from the following block.

<% fields.fields_for :service_subtypes do |subtype| %>
  <%= subtype.hidden_field :id %>
<% end %> 


Found that error, was in my mailers. In any case, the fields_for :subtypes was still not generating the right parameters for the magic of nested attributes to pick up on what I was trying to do.

What I end up with is:

new.erb

<% form.fields_for :services do |fields| %>
    <%= fields.hidden_field :wsi_web_serv_cats_uid_fk %>
    <%= fields.hidden_field :wsi_web_serv_types_uid_fk %>
    <%= fields.hidden_field :service_subs_hash %>
<% end %>

service.rb

def service_subs_hash
    self.service_subtype_ids.join(", ")
end

def service_subs_hash=(ids)
    self.service_subtype_ids = ids.split(",")
end

This is kinda hackish I feel and I'm not sure I'm totally satisfied with it as the answer, but it puts a comma separated list in my hidden field that I can parse to service_subtype_ids again on submit.

If anyone knows how to do it without this extra virtual param, I'd love to know.

Thanks for the help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜