0
votes

Using SimpleForm in a Rails 6 app, I have a nested object that is created multiple times on the new method for the parent object:

def new
    @issue = @issueable.issues.new
    @cat_patchvault = Catalog.find_by_slug("patchvault")
    @cat_bb6 = Catalog.find_by_slug("blue-book-6")
    @issue.catalog_entries.build(catalog_id: @cat_patchvault.id)
    @issue.catalog_entries.build(catalog_id: @cat_bb6.id)
    @issue.reorders.new
    @issue.issue_variations.new
    respond_with @issue
  end

These objects all create and the catalog entries partials are rendered and show the correct catalog in the select dropdown, however, I wanted to change the legend of the fieldset to reflect the catalog and move this to a hidden field.

The select in question:

<%= form.input :catalog_id,
               label: 'Catalog',
               as: :select,
               prompt: 'Choose Catalog',
               collection: Catalog.all.order(:name),
               label_method: lambda { |cl| "#{cl.name} #{cl.version if cl.version}"} %>

CatalogEntry is a through relationship between Issue and Catalog with a lot of additional listing data on each record. This is inside the nested fields partial for catalog_entry, which is called in the parent form:

<%= f.simple_fields_for :catalog_entries do |catalog_entry_form| %>
        <%= render "catalog_entry_fields", form: catalog_entry_form %>
      <% end %>

I've tried a few different things, including SimpleForm's as: :display ( https://github.com/heartcombo/simple_form/wiki/Create-an-%22input%22-just-for-displaying-attribute-value )custom form type, but they all break the form. Solving this with javascript just seems like the wrong way to do it, since the attribute value is already being passed in.

The Display Input code:

<%= form.association :catalog,
                        as: :display,
                        association_label: 'name',
                        label: false %> Listing

And if association_label is commented out, it does return an object, e.g. #<Catalog:0x00007fd7829b1098>. If it is not, it returns undefined method name' for nil:NilClass`, which is weird, because there is an object there...

1

1 Answers

1
votes

The problem is not with catalog_entry_fields. When the catalog_entry_fields is called at this line

<%= f.simple_fields_for :catalog_entries, CatalogEntry.new, child_index: 'NEW_RECORD' do |catalog_entry_form| %>
<%= render "catalog_entry_fields", form: catalog_entry_form %>

the Catalog object you send it does not have a category_id so when name is called on category_id it returns nil. If you remove this line, the form displays as expected. You can see this by inspecting the object in the custom display_input class.
When the display_input class is called here:

<%= f.simple_fields_for :catalog_entries do |catalog_entry_form| %>
   <%= render "catalog_entry_fields", form: catalog_entry_form %>
<% end %>

The returned object is #<CatalogEntry id: nil, catalog_id: 1, issue_id: nil, issue_type_id: nil, category_id: nil, issue_number: nil, variety: nil, combined: nil, event: false, notes: nil, created_at: nil, updated_at: nil, listed_in_error: nil, issueable_id: 5, issueable_type: "Lodge", patchscan_url: nil, slug: nil>

When the display_input class is called here:

<%= f.simple_fields_for :catalog_entries, CatalogEntry.new, child_index: 'NEW_RECORD' do |catalog_entry_form| %>
          <%= render "catalog_entry_fields", form: catalog_entry_form %>

The object returned by the form builder is #<CatalogEntry id: nil, catalog_id: nil, issue_id: nil, issue_type_id: nil, category_id: nil, issue_number: nil, variety: nil, combined: nil, event: false, notes: nil, created_at: nil, updated_at: nil, listed_in_error: nil, issueable_id: nil, issueable_type: nil, patchscan_url: nil, slug: nil> there is no catalog_id, so name is being called on nil which is causing the error.