Administrate: Field type: array

Created on 11 Dec 2016  路  5Comments  路  Source: thoughtbot/administrate

How to create a field type that would support arrays?

The display can be a concatenation of all values of an array.

How to implement the splitting back and saving? Using a string type field just empties the field at the moment when the model is saved

Most helpful comment

For the googlers... The names have changed. This now needs to be:

module Admin
  class KlubsController < Admin::ApplicationController
    # ...
    def resource_params
      params["klub"]["categories"] = params["klub"]["categories"].split(' ')
      params.require(resource_name).permit(*dashboard.permitted_attributes, categories: [])
    end
  end
end

All 5 comments

I was able to get it working with this extra method:

module Admin
  class KlubsController < Admin::ApplicationController
    # ...
    def resource_params
      params["klub"]["categories"] = params["klub"]["categories"].split(' ')
      params.require(resource_name).permit(*permitted_attributes, categories: [])
    end
  end
end

For the googlers... The names have changed. This now needs to be:

module Admin
  class KlubsController < Admin::ApplicationController
    # ...
    def resource_params
      params["klub"]["categories"] = params["klub"]["categories"].split(' ')
      params.require(resource_name).permit(*dashboard.permitted_attributes, categories: [])
    end
  end
end

This seems to work for edit, but not while creating new object. Does anyone facing the same issue ?

In my app I have some resources with such arrays of strings, e.g Administrator.roles, which I implemented as below. This would work if all the string values are known in advance. Field::CollectionSelect is shown in #1603.

class AdministratorDashboard < BaseDashboard
  ATTRIBUTE_TYPES = {
    # ...
    roles: Field::CollectionSelect.with_options(
      multiple: true,
      collection: proc { Administrator::ROLES }
    )
  }

If it should be possible to provide any string, then administrate-field-jsonb might help? I tried it but it gave issues so I stopped using it. For this case, instead my approach has been this custom field:

# app/fields/administrate/field.rb
require "administrate/field/base"

module Administrate
  module Field
    class StringArray < Base
      class Engine < ::Rails::Engine; end

      def self.permitted_attribute(attribute, options = nil)
        { attribute.to_sym => [] }
      end
    end
  end
end

# app/dashboards/post_dashboard.rb
class PostDashboard < BaseDashboard
  ATTRIBUTE_TYPES = {
    # ...
    tags: Field::StringArray
  }

# app/views/fields/string_array/_show.html.erb
<%= field.data %>

# app/views/fields/string_array/_index.html.erb
<%= field.truncate %>

# app/views/fields/string_array/_form.html.erb
<div class="field-unit__label">
  <%= f.label field.attribute %>
</div>
<div class="field-unit__field">
  <% [2, (field.data&.size || 0) + 1].max.times do |i| %>
    <%= f.text_field field.attribute, value: field.data ? field.data[i] : nil, multiple: true %>
  <% end %>
</div>

The form is a bit hacky, would be nice to have add/remove buttons or to integrate something like Selectize or other ideas mentioned in #1611. Or maybe it is possible to modify CollectionSelect to enter new strings?

Thanks @sedubois for some reason I found out in my code for create action resource_params is getting called twice and that's the reason why it keeps sending empty array.

Was this page helpful?
0 / 5 - 0 ratings