Project

selections

0.01
No commit activity in last 3 years
No release in over 3 years
There's a lot of open issues
Selection list management and form and view helpers. Manages one table to hold all selections items/dropdown lists ( tree ). Dynamic lookup to find parent or children ( eg. Selection.priorities ). Form helper to display lists ( eg. f.selections :priorities ). Handling of archived items ( displaying if selected only ).
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

Selections Gem Version

Selection list management and form and view helpers.

##Key Features

  • Manages one table to hold all selections items/dropdown lists or Radio Buttons ( tree )
  • Dynamic lookup to find parent or children ( eg. Selection.priorities )
  • Form helper to display lists
  • f.selections :priorities # dropdowns
  • f.radios :priorities # radio buttons
  • f.check_boxes :priorities # check boxes
  • Model helpers for joining tables ( eg. belongs_to_selection :priority )
  • Matchers eg. @ticket.priority_high?
  • Handling of archived items ( displaying if selected only )
  • Ordering of lists based on alpha or numbered
  • Default item handling

Installation

Add this line to your application's Gemfile:

gem 'selections'

And then execute:

$ bundle

Or install it yourself as:

$ gem install selections

Add this line to config/boot.rb under require 'bundler/setup' ... if using Rspec in your project

ENV["FIXTURES_PATH"] ||= 'spec/fixtures'

Usage

Generator

Scaffold generates basic model, controller views that support the tree adding and editing of selections. Also generates a sample selections.yml file.

rails generate selections_scaffold

Manual

First, you need to configure your selection model. We typically use Selection for this (although you can change the name), and should be generated such as:

rails generate model Selection name parent_id:integer system_code position_value:integer is_default:boolean is_system:boolean archived_at:datetime


class Selection < ActiveRecord::Base
  selectable
end

Selections

Selections table can contain one or many lists, it uses the acts_as_tree so each root is a new list meta example: (see below for example YML file).

  • priority
  • high
  • medium
  • low
  • user_role
  • admin
  • owner
  • user

From the rails console it is be possible to access these items directly using dynamic lookups:

Selection.priority => returns the parent row
Selection.user_role

Dynamic lookups support pluralization and will then return the children:

Selection.priorities  -> [high,med,low] records

Form Helper

If we had a controller for Ticket model with fields of:

  • name
  • priority_id

within the _form.html.erb just use the selections helper method:

<%= form_for(@ticket) do |f| %>

  <div>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>

  <div>
    <%= f.label :priority %><br />
    <%= f.selections :priority %>
  </div>

  <div>
    <%= f.submit %>
  </div>
<% end %>

Selection List Options

  f.selections :fieldname, options = {}, html_options = {}

The selections method excepts all the standard Ruby on Rails form helper options and html formatting - http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select

System Code Override

If you have a selection named differently to the foreign key eg. the foreign key is variety_id, you can use a system_code option.

<%= f.selections :variety, system_code: :category %>

As option override

Radio Buttons Options

If you want your input to be something other than a select tag then you can use the as tag to change it to a radio or check_boxes list. The as option will default to select.

  f.selections :ticket, options = { as: :radio }
  f.selections :ticket, options = { as: :check_boxes }

Scoped System Code

If you have naming conflicts/duplicates system_codes (parent codes) eg. category_id field for user and ticket models

Selections Data example

  • user_category
  • civilian
  • programmer
  • ticket_category
  • high
  • low

The fieldname within the user and ticket form can both be :category as the form helper will search for either 'category' or 'user_category' in the selections model.

users/_form.html.erb

  <%= f.selections :category %>

This will automatically look up the 'user_category' selections if 'category' does not exist

Related Models

Next, you need to tell models that have a selectable association. These are belongs_to associations which pull their values from the selections model. Assuming you have a Ticket model with a foreign key of priority_id, you can set this up like so:

class Ticket < ActiveRecord::Base

  belongs_to_selection :priority

end

If you want a model to have a has_many relationship to a selections list you can create an array field and use the has_many_selections method like so:

class Ticket < ActiveRecord::Base

  has_many_selections :priorities # DB attribute is priorities_ids

end

From an instance of a ticket within a view the belongs_to selection will return string (to_s). eg: show.html.erb

<p>
  <b>Priority:</b>
  <%= @ticket.priority %>  # Instead of this @ticket.priority.try(:name)
</p>

Predicates

Selections supports predicate methods if you add the predicates: true option to the belongs_to_selection model helper, as an example:

instead of needing to do

  if @ticket.priority == Selection.ticket_priority_high

you can check directly on the instance:

  if @ticket.priority_high?

Scopes

Selections supports scope methods if you add the scopes: true option to the belongs_to_selection model helper, as an example:

instead of create a scope for

  scope :ticket_priority_high, -> { where(priority_id: Selection.ticket_priority_high.id) }

this scope is provided for you:

  @ticket.ticket_priority_high

Name Methods

By default the belongs_to_selection model helper provides an instance method for displaying the name or names of the saved selection value as an example:

Instead of

  @ticket.priority.name

You can now just do

  @ticket.priority_name

Automatic Features

Include Blank

In a new form the selections list will have blank top row unless a default item is set in the selections eg. Medium Priority, then there will be no blank row and the default item will be selected.

When editing a form, by default the blank row will not be displayed. Use the options include_blank: true option to override.

Archived Item

On a new form items that are archived in Selections will not appear in the selection list. When editing an existing record the list will only contain un-archived items, unless the item selected is archived it will then appear.

eg. A ticket has a priority set to high, later the high selection list item was archived, when we edit the ticket record again the item will show in the list even though it is archived.

Order

The list will by default display in alphanumeric order, unless you add position values and then it will display in the values.

system_code generation

On creation of a new item in Selections the system_code field will be automatically generated based on parent and item name if left blank.

Configuration

If you use a class name other than Selection as your selection model, you must tell selections so by adding the following to a new file, config/initializers/selections.rb:

Selections.model { YourSelectionModel }

Fast Factories

label_to_id

When using fixtures with the label same as the system_code, use this method to return the ID of the of the fixture and use this in Factories instead of using a lookup as it does not need a DB search.

Fixture File

priority_high:
   name: Priorities
   system_code: priority_high
   parent: priority

In Factory

Don't do this as it will need a DB lookup

  priority: { Selection.priority_high }

Do this as it will be much quicker

 priority_id: { Selection.label_to_id(:priority_high) }

TODO

  • Suggestions please

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

example selections.yml to import into DB

priority:
  name: Priorities
  parent:
  position_value:
  system_code: priority
  is_system: false
priority_high:
  name: High
  parent: priority
  position_value: 30
  system_code: $LABEL
  is_system:
priority_medium:
  name: Medium
  parent: priority
  position_value: 20
  system_code: $LABEL
  is_system:
priority_low:
  name: Low
  parent: priority
  position_value: 10
  system_code: $LABEL
  is_system:
  is_default: true


contact_category:
  name: Contact Categories
  parent:
  position_value:
  system_code: contact_category
  is_system: false
contact_category_junior:
  name: Junior Tech
  parent: contact_category
  position_value:
  system_code: $LABEL
  is_system:
contact_category_senior:
  name: Senior Tech
  parent: contact_category
  position_value:
  system_code: $LABEL
  is_system:
contact_category_manager:
  name: Manager
  parent: contact_category
  position_value:
  system_code: $LABEL
  is_system:
  archived_at: <%= Time.now %>
contact_category_ceo:
  name: CEO
  parent: contact_category
  position_value:
  system_code: $LABEL
  is_system: