selections 0.0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/{MIT-LICENSE → LICENSE.txt} +4 -2
- data/README.md +237 -0
- data/Rakefile +3 -29
- data/lib/selections.rb +22 -6
- data/lib/selections/belongs_to_selection.rb +20 -0
- data/lib/selections/form_builder_extensions.rb +86 -0
- data/lib/selections/selectable.rb +125 -0
- data/lib/selections/version.rb +1 -1
- data/selections.gemspec +38 -0
- data/spec/selections/selectable_spec.rb +220 -0
- data/spec/selections/selections_tag_spec.rb +203 -0
- data/spec/spec_helper.rb +30 -21
- metadata +99 -177
- data/README.rdoc +0 -3
- data/app/assets/javascripts/selections/application.js +0 -9
- data/app/assets/javascripts/selections/selections.js +0 -2
- data/app/assets/stylesheets/scaffold.css +0 -56
- data/app/assets/stylesheets/selections/application.css +0 -7
- data/app/assets/stylesheets/selections/selections.css +0 -4
- data/app/controllers/selections/application_controller.rb +0 -4
- data/app/controllers/selections/selections_controller.rb +0 -45
- data/app/helpers/selections/application_helper.rb +0 -4
- data/app/helpers/selections/selectors_helper.rb +0 -4
- data/app/models/selections/selection.rb +0 -83
- data/app/views/layouts/selections/application.html.erb +0 -1
- data/app/views/selections/selections/_form.html.erb +0 -41
- data/app/views/selections/selections/edit.html.erb +0 -6
- data/app/views/selections/selections/index.html.erb +0 -33
- data/app/views/selections/selections/new.html.erb +0 -5
- data/app/views/selections/selections/show.html.erb +0 -35
- data/config/initializers/selections.rb +0 -1
- data/config/routes.rb +0 -5
- data/db/migrate/20120114024459_create_selections_selections.rb +0 -15
- data/lib/selections/engine.rb +0 -5
- data/lib/selections/selection_select.rb +0 -24
- data/lib/tasks/selections_tasks.rake +0 -4
- data/spec/controllers/companies_controller_spec.rb +0 -10
- data/spec/controllers/selections/selections_controller_spec.rb +0 -165
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/assets/javascripts/application.js +0 -9
- data/spec/dummy/app/assets/javascripts/companies.js +0 -2
- data/spec/dummy/app/assets/stylesheets/application.css +0 -7
- data/spec/dummy/app/assets/stylesheets/companies.css +0 -4
- data/spec/dummy/app/assets/stylesheets/scaffold.css +0 -56
- data/spec/dummy/app/controllers/application_controller.rb +0 -2
- data/spec/dummy/app/controllers/companies_controller.rb +0 -83
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/helpers/companies_helper.rb +0 -2
- data/spec/dummy/app/models/company.rb +0 -7
- data/spec/dummy/app/views/companies/_form.html.erb +0 -3
- data/spec/dummy/app/views/companies/edit.html.erb +0 -4
- data/spec/dummy/app/views/companies/index.html.erb +0 -27
- data/spec/dummy/app/views/companies/new.html.erb +0 -5
- data/spec/dummy/app/views/companies/show.html.erb +0 -20
- data/spec/dummy/app/views/layouts/application.html.erb +0 -11
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/config/application.rb +0 -45
- data/spec/dummy/config/boot.rb +0 -10
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -30
- data/spec/dummy/config/environments/production.rb +0 -60
- data/spec/dummy/config/environments/test.rb +0 -42
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -10
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -6
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20120114125226_create_selections_selections.rb +0 -15
- data/spec/dummy/db/migrate/20120115055119_create_companies.rb +0 -12
- data/spec/dummy/db/schema.rb +0 -38
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +0 -94
- data/spec/dummy/log/test.log +0 -26360
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/helpers/selections/selections_helper_spec.rb +0 -15
- data/spec/models/company_spec.rb +0 -7
- data/spec/models/selections/selection_spec.rb +0 -219
- data/spec/routing/selections/selections_routing_spec.rb +0 -35
- data/spec/support/controller_route_fix.rb +0 -33
- data/spec/support/factories/company_factory.rb +0 -5
- data/spec/support/factories/selection_factory.rb +0 -5
- data/spec/views/companies/edit.html.erb_spec.rb +0 -76
- data/spec/views/companies/new.html.erb_spec.rb +0 -78
- data/spec/views/selections/selections/edit.html.erb_spec.rb +0 -28
- data/spec/views/selections/selections/index.html.erb_spec.rb +0 -40
- data/spec/views/selections/selections/new.html.erb_spec.rb +0 -28
- data/spec/views/selections/selections/show.html.erb_spec.rb +0 -30
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/{MIT-LICENSE → LICENSE.txt}
RENAMED
@@ -1,4 +1,6 @@
|
|
1
|
-
Copyright 2012
|
1
|
+
Copyright (c) 2012 Nigel Rausch
|
2
|
+
|
3
|
+
MIT License
|
2
4
|
|
3
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
6
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,237 @@
|
|
1
|
+
# Selections
|
2
|
+
|
3
|
+
Selection list management and form and view helpers.
|
4
|
+
|
5
|
+
##Key Features
|
6
|
+
|
7
|
+
* Manages one table to hold all selections items/ dropdown lists ( tree )
|
8
|
+
* Dynamic lookup to find parent or children ( eg. Selection.priorities )
|
9
|
+
* Form helper to display lists ( eg. f.selections :priorities )
|
10
|
+
* Model helpers for joining tables ( eg. belongs_to_selection :priority )
|
11
|
+
* Handling of archived items ( displaying if selected only )
|
12
|
+
* Ordering of lists based on alpha or numbered
|
13
|
+
* Default item handling
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
Add this line to your application's Gemfile:
|
18
|
+
|
19
|
+
gem 'selections'
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install selections
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
First, you need to configure your selection model. We typically use `Selection` for this (although you
|
32
|
+
can change the name), and should be generated such as:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
rails generate model Selection name parent_id:integer system_code position_value:integer is_default:boolean is_system:boolean archived_at:datetime
|
36
|
+
```
|
37
|
+
|
38
|
+
### Model
|
39
|
+
And next, edit this class to look like:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
class Selection < ActiveRecord::Base
|
43
|
+
selectable
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
Selections table can contain one or many lists, it uses the acts_as_tree so each root is a new list
|
48
|
+
meta example: (see below for example YAML file)
|
49
|
+
- priority
|
50
|
+
- high
|
51
|
+
- medium
|
52
|
+
- low
|
53
|
+
- user_role
|
54
|
+
- admin
|
55
|
+
- owner
|
56
|
+
- user
|
57
|
+
|
58
|
+
From the rails console it is be possible to access these items directly using dynamic lookups
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
Selection.priority => returns the parent row
|
62
|
+
Selection.user_role
|
63
|
+
```
|
64
|
+
|
65
|
+
Dynamic lookups support pluralization and will then return the children
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
Selection.priorities => [high,med,low] records
|
69
|
+
```
|
70
|
+
|
71
|
+
#### Form Helper
|
72
|
+
|
73
|
+
if we had a controller for Ticket model with fields of
|
74
|
+
- name
|
75
|
+
- priority_id
|
76
|
+
|
77
|
+
within the _form.html.erb just use the selections helper method
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
<%= form_for(@ticket) do |f| %>
|
81
|
+
|
82
|
+
<div>
|
83
|
+
<%= f.label :name %><br />
|
84
|
+
<%= f.text_field :name %>
|
85
|
+
</div>
|
86
|
+
|
87
|
+
<div>
|
88
|
+
<%= f.label :priority %><br />
|
89
|
+
<%= f.selections :priority %>
|
90
|
+
</div>
|
91
|
+
|
92
|
+
<div>
|
93
|
+
<%= f.submit %>
|
94
|
+
</div>
|
95
|
+
<% end %>
|
96
|
+
```
|
97
|
+
|
98
|
+
If you have naming conflicts/duplicates eg. user categories and ticket categories within in the selections name the parent/system_code
|
99
|
+
user_category & ticket_category. The foreign key within the user and ticket can both be category_id and the form_helper will still be
|
100
|
+
|
101
|
+
user form
|
102
|
+
```ruby
|
103
|
+
f.selections :category
|
104
|
+
```
|
105
|
+
this will automatically look up the user_category selections.
|
106
|
+
|
107
|
+
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
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
f.selections :variety, :system_code => :category
|
111
|
+
```
|
112
|
+
|
113
|
+
Next, you need to tell models that have a selectable association. These are `belongs_to` associations
|
114
|
+
which pull their values from the selections model. Assuming you have a `Ticket` model with a foreign key of priority_id,
|
115
|
+
you can set this up like so:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
class Ticket < ActiveRecord::Base
|
119
|
+
|
120
|
+
belongs_to_selection :priority
|
121
|
+
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
From an instance of a ticket within a view the belongs_to selection will return string (to_s).
|
126
|
+
eg: show.html.erb
|
127
|
+
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
ticket.priority.try(:name) # don't need to do this
|
131
|
+
|
132
|
+
ticket.priority # will default to return name
|
133
|
+
```
|
134
|
+
|
135
|
+
### Automatic Features
|
136
|
+
#### Include Blank
|
137
|
+
|
138
|
+
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
|
139
|
+
will be no blank row and the default item will be selected
|
140
|
+
|
141
|
+
When editing a form, by default the blank row will not be displayed
|
142
|
+
|
143
|
+
#### Archived Item
|
144
|
+
|
145
|
+
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
|
146
|
+
contain un-archived items, unless the item selected is archived it will then appear.
|
147
|
+
|
148
|
+
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
|
149
|
+
|
150
|
+
#### Order
|
151
|
+
|
152
|
+
The list will by default display in alphanumeric order, unless you add position values and then it will display in the values.
|
153
|
+
|
154
|
+
## Configuration
|
155
|
+
|
156
|
+
If you use a class name other than `Selection` as your selection model, you must
|
157
|
+
tell selections so by adding the following to a new file, `config/initializers/selections.rb`:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
Selections.model { YourSelectionModel }
|
161
|
+
```
|
162
|
+
|
163
|
+
# TODO
|
164
|
+
|
165
|
+
* Add model generators
|
166
|
+
* Add selections management scaffold/generator
|
167
|
+
|
168
|
+
## Contributing
|
169
|
+
|
170
|
+
1. Fork it
|
171
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
172
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
173
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
174
|
+
5. Create new Pull Request
|
175
|
+
|
176
|
+
## YAML example
|
177
|
+
|
178
|
+
```yaml
|
179
|
+
priority:
|
180
|
+
name: Priorities
|
181
|
+
parent:
|
182
|
+
position_value:
|
183
|
+
system_code: priority
|
184
|
+
is_system: false
|
185
|
+
priority_high:
|
186
|
+
name: High
|
187
|
+
parent: priority
|
188
|
+
position_value: 30
|
189
|
+
system_code: $LABEL
|
190
|
+
is_system:
|
191
|
+
priority_medium:
|
192
|
+
name: Medium
|
193
|
+
parent: priority
|
194
|
+
position_value: 20
|
195
|
+
system_code: $LABEL
|
196
|
+
is_system:
|
197
|
+
priority_low:
|
198
|
+
name: Low
|
199
|
+
parent: priority
|
200
|
+
position_value: 10
|
201
|
+
system_code: $LABEL
|
202
|
+
is_system:
|
203
|
+
is_default: true
|
204
|
+
|
205
|
+
|
206
|
+
contact_category:
|
207
|
+
name: Contact Categories
|
208
|
+
parent:
|
209
|
+
position_value:
|
210
|
+
system_code: contact_category
|
211
|
+
is_system: false
|
212
|
+
contact_category_junior:
|
213
|
+
name: Junior Tech
|
214
|
+
parent: contact_category
|
215
|
+
position_value:
|
216
|
+
system_code: $LABEL
|
217
|
+
is_system:
|
218
|
+
contact_category_senior:
|
219
|
+
name: Senior Tech
|
220
|
+
parent: contact_category
|
221
|
+
position_value:
|
222
|
+
system_code: $LABEL
|
223
|
+
is_system:
|
224
|
+
contact_category_manager:
|
225
|
+
name: Manager
|
226
|
+
parent: contact_category
|
227
|
+
position_value:
|
228
|
+
system_code: $LABEL
|
229
|
+
is_system:
|
230
|
+
archived_at: <%= Time.now %>
|
231
|
+
contact_category_ceo:
|
232
|
+
name: CEO
|
233
|
+
parent: contact_category
|
234
|
+
position_value:
|
235
|
+
system_code: $LABEL
|
236
|
+
is_system:
|
237
|
+
```
|
data/Rakefile
CHANGED
@@ -1,31 +1,5 @@
|
|
1
|
-
|
2
|
-
begin
|
3
|
-
require 'bundler/setup'
|
4
|
-
rescue LoadError
|
5
|
-
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
-
end
|
7
|
-
begin
|
8
|
-
require 'rdoc/task'
|
9
|
-
rescue LoadError
|
10
|
-
require 'rdoc/rdoc'
|
11
|
-
require 'rake/rdoctask'
|
12
|
-
RDoc::Task = Rake::RDocTask
|
13
|
-
end
|
14
|
-
|
15
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
-
rdoc.rdoc_dir = 'rdoc'
|
17
|
-
rdoc.title = 'Selections'
|
18
|
-
rdoc.options << '--line-numbers'
|
19
|
-
rdoc.rdoc_files.include('README.rdoc')
|
20
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
-
end
|
22
|
-
|
23
|
-
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
-
load 'rails/tasks/engine.rake'
|
25
|
-
|
26
|
-
|
27
|
-
Bundler::GemHelper.install_tasks
|
28
|
-
|
1
|
+
require "bundler/gem_tasks"
|
29
2
|
require 'rspec/core/rake_task'
|
3
|
+
|
30
4
|
RSpec::Core::RakeTask.new(:spec)
|
31
|
-
task :
|
5
|
+
task default: :spec
|
data/lib/selections.rb
CHANGED
@@ -1,7 +1,23 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require "selections/selection_select"
|
1
|
+
require 'selections/version'
|
2
|
+
require 'active_record'
|
3
|
+
require 'action_view'
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
module Selections
|
6
|
+
|
7
|
+
require 'selections/belongs_to_selection'
|
8
|
+
require 'selections/form_builder_extensions'
|
9
|
+
require 'selections/selectable'
|
10
|
+
|
11
|
+
# Given a block, will set how we find / detect the current model
|
12
|
+
# used for selections, without a block, will return the value.
|
13
|
+
# Note: Needed iff you are using a model other than Selection.
|
14
|
+
def self.model(&block)
|
15
|
+
if block
|
16
|
+
@model = block
|
17
|
+
else
|
18
|
+
@model ||= lambda { Selection }
|
19
|
+
@model.call
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Selections
|
2
|
+
module BelongsToSelection
|
3
|
+
|
4
|
+
# Helper for belongs_to and accepts all the standard rails options
|
5
|
+
#
|
6
|
+
#Example
|
7
|
+
# belongs_to_selection :priority
|
8
|
+
#
|
9
|
+
# by default adds - class_name: "Selection"
|
10
|
+
|
11
|
+
def belongs_to_selection(target, options={})
|
12
|
+
belongs_to target, options.merge(:class_name => "Selection")
|
13
|
+
end
|
14
|
+
|
15
|
+
ActiveSupport.on_load :active_record do
|
16
|
+
extend Selections::BelongsToSelection
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Selections
|
2
|
+
module FormBuilderExtensions
|
3
|
+
# Create a select list based on the field name finding items within Selection.
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# Example
|
7
|
+
# form_for(@ticket) do |f|
|
8
|
+
# f. select("priority")
|
9
|
+
#
|
10
|
+
# Uses priority_id from the ticket table and creates options list based on items in Selection table with a system_code of
|
11
|
+
# either priority or ticket_priority
|
12
|
+
#
|
13
|
+
# options = {} and html_options = {} suport all the keys as the rails library select_tag does.
|
14
|
+
#
|
15
|
+
# options
|
16
|
+
# * +system_code+ - Overrides the automatic system_code name based on the fieldname and looks up the list of items in Selection
|
17
|
+
|
18
|
+
def selections(field, options = {}, html_options = {})
|
19
|
+
SelectionTag.new(self, object, field, html_options, options).to_tag
|
20
|
+
end
|
21
|
+
|
22
|
+
class SelectionTag #:nodoc:
|
23
|
+
attr_reader :form, :object, :field, :html_options, :options, :selection, :field_id, :system_code_name
|
24
|
+
|
25
|
+
def initialize(form, object, field, html_options, options)
|
26
|
+
@form = form
|
27
|
+
@object = object
|
28
|
+
@field = field
|
29
|
+
@html_options = html_options || {}
|
30
|
+
|
31
|
+
@system_code_name = options[:system_code] || field
|
32
|
+
@selection = Selections.model
|
33
|
+
@field_id ||= (field.to_s + "_id").to_sym
|
34
|
+
@options = options || {}
|
35
|
+
end
|
36
|
+
|
37
|
+
def include_blank?
|
38
|
+
if options[:include_blank].nil?
|
39
|
+
!!((object.try(:new_record?) || !object.send(field_id))) && default_item.blank?
|
40
|
+
else
|
41
|
+
!!options[:include_blank]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def system_code
|
46
|
+
@system_code ||= selection.where(system_code: system_code_name.to_s).first
|
47
|
+
@system_code ||= selection.where(system_code: "#{form.object_name}_#{system_code_name}").first
|
48
|
+
end
|
49
|
+
|
50
|
+
def items
|
51
|
+
@items ||= system_code.children.filter_archived_except_selected(object.send(field_id))
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_tag
|
55
|
+
if system_code
|
56
|
+
#TODO add default style
|
57
|
+
#html_options[:style] ||=
|
58
|
+
options[:include_blank] = include_blank?
|
59
|
+
options[:selected] = selected_item
|
60
|
+
form.select field_id, items.map { |item| [item.name, item.id] }, options, html_options
|
61
|
+
else
|
62
|
+
"Invalid system_code of '#{system_code_name}'"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def selected_item
|
67
|
+
if object.new_record?
|
68
|
+
default_item
|
69
|
+
else
|
70
|
+
object.send(field_id).to_s
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def default_item
|
75
|
+
items.where(:is_default => true).first.try(:id).to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
ActiveSupport.on_load :action_view do
|
80
|
+
ActionView::Helpers::FormBuilder.class_eval do
|
81
|
+
include Selections::FormBuilderExtensions
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|