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