From 3bccdb3fbda5d3965768655455f84aa8a6404659 Mon Sep 17 00:00:00 2001 From: Jason Berlinsky Date: Mon, 18 Jan 2016 22:33:23 -0500 Subject: [PATCH] Add support for selectable strings on edit pages Feature: As an admin I want to select values from a drop-down rather than enter them free-form So that I don't need to worry about data integrity And so that I have a streamlined experience. Implementation: Add `Administrate::Field::Select` as an option to present string attributes. The field displays its attribute as a drop-down field on form pages. Usage in a dashboard: ```ruby kind: Field::Select.with_options(collection: Customer::KINDS), ``` --- CHANGELOG.md | 6 ++++ app/views/fields/select/_form.html.erb | 31 +++++++++++++++++++ app/views/fields/select/_index.html.erb | 16 ++++++++++ app/views/fields/select/_show.html.erb | 16 ++++++++++ docs/customizing_dashboards.md | 1 + lib/administrate/base_dashboard.rb | 1 + lib/administrate/field/select.rb | 21 +++++++++++++ .../app/dashboards/customer_dashboard.rb | 8 ++++- spec/example_app/app/models/customer.rb | 5 +++ .../20160119024340_add_kind_to_customer.rb | 5 +++ spec/example_app/db/schema.rb | 11 ++++--- spec/features/edit_page_spec.rb | 11 +++++++ 12 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 app/views/fields/select/_form.html.erb create mode 100644 app/views/fields/select/_index.html.erb create mode 100644 app/views/fields/select/_show.html.erb create mode 100644 lib/administrate/field/select.rb create mode 100644 spec/example_app/db/migrate/20160119024340_add_kind_to_customer.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b685e74a9..d511638be3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,12 @@ ### Upcoming Release +* [#422] [FEATURE] Add a `Select` field for displaying a drop-down menu of + options on form pages. + Options: + ```ruby + Field::Select.with_options(collection: [:foo, :bar]) + ``` * [#458] [BUGFIX] Update the custom field generator to match the new HTML structure of forms diff --git a/app/views/fields/select/_form.html.erb b/app/views/fields/select/_form.html.erb new file mode 100644 index 0000000000..4ccf874644 --- /dev/null +++ b/app/views/fields/select/_form.html.erb @@ -0,0 +1,31 @@ +<%# +# Select Index Partial + +This partial renders a selectable text attribute, +to be displayed on a resource's edit form page. + +## Local variables: + +- `f`: + A Rails form generator, used to help create the appropriate input fields. +- `field`: + An instance of [Administrate::Field::Select][1]. + A wrapper around the attribute pulled from the database. + +[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Select +%> + +
+ <%= f.label field.attribute %> +
+
+ <%= f.select( + field.attribute, + options_from_collection_for_select( + field.selectable_options, + :to_s, + :to_s, + field.data.presence, + ) + ) %> +
diff --git a/app/views/fields/select/_index.html.erb b/app/views/fields/select/_index.html.erb new file mode 100644 index 0000000000..79878c08d4 --- /dev/null +++ b/app/views/fields/select/_index.html.erb @@ -0,0 +1,16 @@ +<%# +# Select Index Partial + +This partial renders a selectable text attribute, +to be displayed on a resource's index page. + +## Local variables: + +- `field`: + An instance of [Administrate::Field::Select][1]. + A wrapper around the attribute pulled from the database. + +[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Select +%> + +<%= field.data %> diff --git a/app/views/fields/select/_show.html.erb b/app/views/fields/select/_show.html.erb new file mode 100644 index 0000000000..0eda05864a --- /dev/null +++ b/app/views/fields/select/_show.html.erb @@ -0,0 +1,16 @@ +<%# +# Select Show Partial + +This partial renders a selectable text attribute, +to be displayed on a resource's show page. + +## Local variables: + +- `field`: + An instance of [Administrate::Field::Select][1]. + A wrapper around the attribute pulled from the database. + +[1]: http://www.rubydoc.info/gems/administrate/Administrate/Field/Select +%> + +<%= field.data %> diff --git a/docs/customizing_dashboards.md b/docs/customizing_dashboards.md index b157027b81..7f48367482 100644 --- a/docs/customizing_dashboards.md +++ b/docs/customizing_dashboards.md @@ -60,6 +60,7 @@ specify, including: - `Field::Image` - `Field::Number` - `Field::Polymorphic` +- `Field::Select` - `Field::String` Each of the `Field` types take a different set of options, diff --git a/lib/administrate/base_dashboard.rb b/lib/administrate/base_dashboard.rb index cf534d4b9d..83e993aa11 100644 --- a/lib/administrate/base_dashboard.rb +++ b/lib/administrate/base_dashboard.rb @@ -7,6 +7,7 @@ require "administrate/field/image" require "administrate/field/number" require "administrate/field/polymorphic" +require "administrate/field/select" require "administrate/field/string" require "administrate/field/text" diff --git a/lib/administrate/field/select.rb b/lib/administrate/field/select.rb new file mode 100644 index 0000000000..73b0ea570f --- /dev/null +++ b/lib/administrate/field/select.rb @@ -0,0 +1,21 @@ +require_relative "base" + +module Administrate + module Field + class Select < Field::Base + def self.searchable? + true + end + + def selectable_options + collection + end + + private + + def collection + @collection ||= options.fetch(:collection, []) + end + end + end +end diff --git a/spec/example_app/app/dashboards/customer_dashboard.rb b/spec/example_app/app/dashboards/customer_dashboard.rb index f62d2c01c9..f24824f41a 100644 --- a/spec/example_app/app/dashboards/customer_dashboard.rb +++ b/spec/example_app/app/dashboards/customer_dashboard.rb @@ -9,11 +9,17 @@ class CustomerDashboard < Administrate::BaseDashboard name: Field::String, orders: Field::HasMany, updated_at: Field::DateTime, + kind: Field::Select.with_options(collection: Customer::KINDS), } COLLECTION_ATTRIBUTES = ATTRIBUTE_TYPES.keys SHOW_PAGE_ATTRIBUTES = ATTRIBUTE_TYPES.keys - [:name] - FORM_ATTRIBUTES = [:name, :email, :email_subscriber] + FORM_ATTRIBUTES = [ + :name, + :email, + :email_subscriber, + :kind, + ].freeze def display_resource(customer) customer.name diff --git a/spec/example_app/app/models/customer.rb b/spec/example_app/app/models/customer.rb index bfc796ad14..a780e67da6 100644 --- a/spec/example_app/app/models/customer.rb +++ b/spec/example_app/app/models/customer.rb @@ -4,6 +4,11 @@ class Customer < ActiveRecord::Base validates :name, presence: true validates :email, presence: true + KINDS = [ + :standard, + :vip, + ].freeze + def lifetime_value orders.map(&:total_price).reduce(0, :+) end diff --git a/spec/example_app/db/migrate/20160119024340_add_kind_to_customer.rb b/spec/example_app/db/migrate/20160119024340_add_kind_to_customer.rb new file mode 100644 index 0000000000..3db41446c0 --- /dev/null +++ b/spec/example_app/db/migrate/20160119024340_add_kind_to_customer.rb @@ -0,0 +1,5 @@ +class AddKindToCustomer < ActiveRecord::Migration + def change + add_column :customers, :kind, :string, null: false, default: "standard" + end +end diff --git a/spec/example_app/db/schema.rb b/spec/example_app/db/schema.rb index be04bf567d..997fd815b3 100644 --- a/spec/example_app/db/schema.rb +++ b/spec/example_app/db/schema.rb @@ -11,17 +11,18 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150916011117) do +ActiveRecord::Schema.define(version: 20160119024340) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" create_table "customers", force: :cascade do |t| - t.string "name", null: false - t.string "email", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", null: false + t.string "email", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "email_subscriber" + t.string "kind", default: "standard", null: false end create_table "delayed_jobs", force: :cascade do |t| diff --git a/spec/features/edit_page_spec.rb b/spec/features/edit_page_spec.rb index 8083933ffe..0688ac898d 100644 --- a/spec/features/edit_page_spec.rb +++ b/spec/features/edit_page_spec.rb @@ -35,4 +35,15 @@ expect(page).to have_content("true") end + + it "displays selectable strings as dropdowns", :js do + customer = create(:customer, kind: :standard) + + visit edit_admin_customer_path(customer) + select "vip", from: "Kind" + click_on "Update Customer" + + expect(page).to have_content("KIND") + expect(page).to have_content("vip") + end end