dm-is-select 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +16 -0
- data/History.rdoc +24 -0
- data/LICENSE +20 -0
- data/README.rdoc +170 -0
- data/Rakefile +109 -0
- data/TODO +0 -0
- data/VERSION +1 -0
- data/dm-is-select.gemspec +62 -0
- data/lib/dm-is-select.rb +22 -0
- data/lib/dm-is-select/is/select.rb +160 -0
- data/lib/dm-is-select/is/version.rb +7 -0
- data/spec/integration/select_spec.rb +285 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +28 -0
- metadata +91 -0
data/.gitignore
ADDED
data/History.rdoc
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
=== 0.0.1 / 2009-07-12
|
2
|
+
|
3
|
+
* Release!
|
4
|
+
|
5
|
+
=== 0.0.2 / 2009-07-15
|
6
|
+
|
7
|
+
* Added Top Level Parent support in output.
|
8
|
+
|
9
|
+
=== 0.0.3 / 2009-08-20
|
10
|
+
|
11
|
+
* Fixed rendering bug in gem server when the description contained the <tt><select></tt> tag
|
12
|
+
* Converted History.txt to .rdoc
|
13
|
+
* Improved the Rakefile docs output
|
14
|
+
* Added support for custom SQL queries.
|
15
|
+
|
16
|
+
|
17
|
+
=== 0.0.4 / 2009-10-30
|
18
|
+
|
19
|
+
* Changed the output order of options array from [key, value] to [value, key] to link with options better.
|
20
|
+
|
21
|
+
=== 0.0.5 / 2009-10-30
|
22
|
+
|
23
|
+
* Somehow reintroduced the rendering bug in the gemspec description fixed in 0.0.3
|
24
|
+
* Updated History.rdoc
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 mats
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
= dm-is-select
|
2
|
+
|
3
|
+
A DataMapper plugin that makes getting the <tt><select></tt> options from a Model easier.
|
4
|
+
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
# Add Gemcutter to your RubyGems sources
|
9
|
+
$ gem sources -a http://gemcutter.com
|
10
|
+
|
11
|
+
$ (sudo)? gem install dm-is-select
|
12
|
+
|
13
|
+
=== Dependencies
|
14
|
+
|
15
|
+
The plugin depends upon the following:
|
16
|
+
|
17
|
+
* dm-core ( >= 0.10.0)
|
18
|
+
* dm-more ( >= 0.10.0) [not really, but your code will depend upon it]
|
19
|
+
|
20
|
+
|
21
|
+
<b>NB!</b> The plugin has been developed for and on DM's next branch[http://github.com/datamapper/dm-core/tree/next], so may NOT work on previous incarnations.
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
== Getting Started
|
26
|
+
|
27
|
+
Let's say you got a basic Category Model.
|
28
|
+
|
29
|
+
class Category
|
30
|
+
include DataMapper::Resource
|
31
|
+
property :id, Serial
|
32
|
+
property :name, String
|
33
|
+
|
34
|
+
is :select, :name
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
Through that simple declaration you get the following class method ..
|
39
|
+
|
40
|
+
Category.items_for_select_menu
|
41
|
+
|
42
|
+
...which returns an Array with the Model items in a structured way, ready for use.
|
43
|
+
|
44
|
+
[
|
45
|
+
[nil, "Select Category"],
|
46
|
+
["nil", " ------ "],
|
47
|
+
[1, "Category 1"],
|
48
|
+
[2, "Category 2"],
|
49
|
+
[3, "Category 3"],
|
50
|
+
[4, "Category 4"],
|
51
|
+
[5, "Category 5"]
|
52
|
+
]
|
53
|
+
|
54
|
+
Great, but you don't want the prompt to say "Select Category", but
|
55
|
+
|
56
|
+
Category.items_for_select_menu( :prompt => "Choose Whatever" )
|
57
|
+
|
58
|
+
|
59
|
+
...which returns the Array with the prompt changed
|
60
|
+
|
61
|
+
[
|
62
|
+
[nil, "Choose Whatever"],
|
63
|
+
["nil", " ------ "],
|
64
|
+
[1, "Category 1"],
|
65
|
+
...<snip>...
|
66
|
+
]
|
67
|
+
|
68
|
+
|
69
|
+
OK, but you don't like the divider node (2nd in output above). That’s fine, you remove it like this:
|
70
|
+
|
71
|
+
Category.items_for_select_menu( :divider => false )
|
72
|
+
|
73
|
+
|
74
|
+
...which returns the Array with the divider removed
|
75
|
+
|
76
|
+
[
|
77
|
+
[nil, "Select Category"],
|
78
|
+
[1, "Category 1"],
|
79
|
+
...<snip>...
|
80
|
+
]
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
Hmm, fine, but I don't want either a prompt or a divider, you say. That's fine too.
|
85
|
+
|
86
|
+
Category.items_for_select_menu( :prompt => false )
|
87
|
+
|
88
|
+
...which returns the Array with the prompt and divider removed
|
89
|
+
|
90
|
+
[
|
91
|
+
[1, "Category 1"],
|
92
|
+
[1, "Category 2"],
|
93
|
+
...<snip>...
|
94
|
+
]
|
95
|
+
|
96
|
+
|
97
|
+
OK, that's smooth, but my Category model is a tree with parents, children and so on. This won't work with that.
|
98
|
+
|
99
|
+
Sure, no problem, just do this when you declare the Model:
|
100
|
+
|
101
|
+
is :select, :name, :is_tree => true
|
102
|
+
|
103
|
+
|
104
|
+
Then you can just use this
|
105
|
+
|
106
|
+
Category.items_for_select_menu( :prompt => "Choose Parent" )
|
107
|
+
|
108
|
+
...and you get this nicely formatted <tt><select></tt> options array
|
109
|
+
|
110
|
+
[
|
111
|
+
[nil, "Choose Parent"],
|
112
|
+
["nil", " ------ "],
|
113
|
+
[0, "Top Level Category"],
|
114
|
+
["nil", " ------ "],
|
115
|
+
[1, "Parent-1"],
|
116
|
+
[2, "-- Parent-1-Child"],
|
117
|
+
[3, "-- -- Parent-1-Child-GrandChild"],
|
118
|
+
[4, "Parent-2"],
|
119
|
+
[5, "-- Parent-2-Child"],
|
120
|
+
[6, "-- -- Parent-2-Child-GrandChild"]
|
121
|
+
]
|
122
|
+
|
123
|
+
<b>NB!</b> It only supports 3 levels at this point in time, as I think that's enough in most use cases,
|
124
|
+
but IF not, fix the code and let me know and I'll add it.
|
125
|
+
|
126
|
+
Cool, but that "Top Level Category" node is a bit ugly, but easily fixed.
|
127
|
+
|
128
|
+
Category.items_for_select_menu( :root_text => "1st Parent (root)" )
|
129
|
+
|
130
|
+
...gives you:
|
131
|
+
|
132
|
+
[
|
133
|
+
...<snip>...
|
134
|
+
["nil", " ------ "],
|
135
|
+
[0, "1st Parent (root)"],
|
136
|
+
["nil", " ------ "],
|
137
|
+
...<snip>...
|
138
|
+
]
|
139
|
+
|
140
|
+
You can even remove it all together by doing this:
|
141
|
+
|
142
|
+
Category.items_for_select_menu( :show_root => false )
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
Obviously all the config options from above works with Tree models as well.
|
148
|
+
|
149
|
+
== Last Few Words
|
150
|
+
|
151
|
+
OK, I admit it, not the most impressive DM plugin there is, but hey, it sure helps keeping your model/views cleaner.
|
152
|
+
|
153
|
+
|
154
|
+
== RTFM
|
155
|
+
|
156
|
+
For a better understanding of this gem/plugin, make sure you study the '<tt>dm-is-select/spec/integration/select_spec.rb</tt>' file.
|
157
|
+
|
158
|
+
|
159
|
+
== Errors / Bugs
|
160
|
+
|
161
|
+
If something is not behaving intuitively, it is a bug, and should be reported.
|
162
|
+
Report it here: http://github.com/kematzy/dm-is-select/issues
|
163
|
+
|
164
|
+
== Credits
|
165
|
+
|
166
|
+
Copyright (c) 2009-07-12 Kematzy [ kematzy gmail com ]
|
167
|
+
|
168
|
+
== Licence
|
169
|
+
|
170
|
+
Released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "dm-is-select"
|
8
|
+
# gem.version = IO.read('VERSION')
|
9
|
+
gem.summary = %Q{A DataMapper plugin that makes getting the <tt>select</tt> options from a Model easier.}
|
10
|
+
gem.description = gem.summary
|
11
|
+
gem.email = "kematzy@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/kematzy/dm-is-select"
|
13
|
+
gem.authors = ["kematzy"]
|
14
|
+
gem.extra_rdoc_files = %w[ README.rdoc LICENSE TODO History.rdoc ]
|
15
|
+
gem.add_dependency('dm-core', '>= 0.10.0')
|
16
|
+
gem.add_dependency('dm-more', '>= 0.10.0')
|
17
|
+
# gem.add_dependency('dm-validations', '>= 0.10.0')
|
18
|
+
|
19
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
20
|
+
end
|
21
|
+
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'spec/rake/spectask'
|
27
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
30
|
+
end
|
31
|
+
|
32
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
33
|
+
spec.libs << 'lib' << 'spec'
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
35
|
+
spec.rcov = true
|
36
|
+
end
|
37
|
+
|
38
|
+
namespace :spec do
|
39
|
+
|
40
|
+
desc "Run all specifications verbosely"
|
41
|
+
Spec::Rake::SpecTask.new(:verbose) do |t|
|
42
|
+
t.libs << "lib"
|
43
|
+
t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Run specific spec verbosely (SPEC=/path/2/file)"
|
47
|
+
Spec::Rake::SpecTask.new(:select) do |t|
|
48
|
+
t.libs << "lib"
|
49
|
+
t.spec_files = [ENV["SPEC"]]
|
50
|
+
t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
task :default => :spec
|
56
|
+
|
57
|
+
require 'rake/rdoctask'
|
58
|
+
Rake::RDocTask.new do |rdoc|
|
59
|
+
version = File.exist?('VERSION') ? IO.read('VERSION').chomp : "[Unknown]"
|
60
|
+
|
61
|
+
rdoc.rdoc_dir = 'rdoc'
|
62
|
+
rdoc.title = "dm-is-select #{version}"
|
63
|
+
rdoc.rdoc_files.include('README*')
|
64
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
desc 'Build the rdoc HTML Files'
|
70
|
+
task :docs do
|
71
|
+
version = File.exist?('VERSION') ? IO.read('VERSION').chomp : "[Unknown]"
|
72
|
+
|
73
|
+
sh "sdoc -N --title 'DM::Is::Select v#{version}' lib/dm-is-select README.rdoc"
|
74
|
+
end
|
75
|
+
|
76
|
+
namespace :docs do
|
77
|
+
|
78
|
+
desc 'Remove rdoc products'
|
79
|
+
task :remove => [:clobber_rdoc] do
|
80
|
+
sh "rm -rf doc"
|
81
|
+
end
|
82
|
+
|
83
|
+
desc 'Force a rebuild of the RDOC files'
|
84
|
+
task :rebuild => [:docs]
|
85
|
+
|
86
|
+
desc 'Build docs, and open in browser for viewing (specify BROWSER)'
|
87
|
+
task :open => [:docs] do
|
88
|
+
browser = ENV["BROWSER"] || "safari"
|
89
|
+
sh "open -a #{browser} doc/index.html"
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# kept just as a reference for now.
|
96
|
+
#
|
97
|
+
# def sudo_gem(cmd)
|
98
|
+
# sh "#{SUDO} #{RUBY} -S gem #{cmd}", :verbose => false
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# desc "Install #{GEM_NAME} #{GEM_VERSION}"
|
102
|
+
# task :install => [ :package ] do
|
103
|
+
# sudo_gem "install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# desc "Uninstall #{GEM_NAME} #{GEM_VERSION}"
|
107
|
+
# task :uninstall => [ :clobber ] do
|
108
|
+
# sudo_gem "uninstall #{GEM_NAME} -v#{GEM_VERSION} -Ix"
|
109
|
+
# end
|
data/TODO
ADDED
File without changes
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.5
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{dm-is-select}
|
8
|
+
s.version = "0.0.5"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["kematzy"]
|
12
|
+
s.date = %q{2009-10-30}
|
13
|
+
s.description = %q{A DataMapper plugin that makes getting the <tt>select</tt> options from a Model easier.}
|
14
|
+
s.email = %q{kematzy@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"History.rdoc",
|
17
|
+
"LICENSE",
|
18
|
+
"README.rdoc",
|
19
|
+
"TODO"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".gitignore",
|
23
|
+
"History.rdoc",
|
24
|
+
"LICENSE",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"TODO",
|
28
|
+
"VERSION",
|
29
|
+
"dm-is-select.gemspec",
|
30
|
+
"lib/dm-is-select.rb",
|
31
|
+
"lib/dm-is-select/is/select.rb",
|
32
|
+
"lib/dm-is-select/is/version.rb",
|
33
|
+
"spec/integration/select_spec.rb",
|
34
|
+
"spec/spec.opts",
|
35
|
+
"spec/spec_helper.rb"
|
36
|
+
]
|
37
|
+
s.homepage = %q{http://github.com/kematzy/dm-is-select}
|
38
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = %q{1.3.5}
|
41
|
+
s.summary = %q{A DataMapper plugin that makes getting the <tt>select</tt> options from a Model easier.}
|
42
|
+
s.test_files = [
|
43
|
+
"spec/integration/select_spec.rb",
|
44
|
+
"spec/spec_helper.rb"
|
45
|
+
]
|
46
|
+
|
47
|
+
if s.respond_to? :specification_version then
|
48
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
49
|
+
s.specification_version = 3
|
50
|
+
|
51
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
52
|
+
s.add_runtime_dependency(%q<dm-core>, [">= 0.10.0"])
|
53
|
+
s.add_runtime_dependency(%q<dm-more>, [">= 0.10.0"])
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<dm-core>, [">= 0.10.0"])
|
56
|
+
s.add_dependency(%q<dm-more>, [">= 0.10.0"])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<dm-core>, [">= 0.10.0"])
|
60
|
+
s.add_dependency(%q<dm-more>, [">= 0.10.0"])
|
61
|
+
end
|
62
|
+
end
|
data/lib/dm-is-select.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Needed to import datamapper and other gems
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
# Add all external dependencies for the plugin here
|
6
|
+
gem 'dm-core', '~> 0.10.0'
|
7
|
+
require 'dm-core'
|
8
|
+
# gem 'extlib', '~> 0.9.13'
|
9
|
+
# require 'extlib'
|
10
|
+
gem 'dm-is-tree', '~> 0.10.0'
|
11
|
+
require 'dm-is-tree'
|
12
|
+
|
13
|
+
|
14
|
+
# Require plugin-files
|
15
|
+
require Pathname(__FILE__).dirname.expand_path / 'dm-is-select' / 'is' / 'select.rb'
|
16
|
+
|
17
|
+
DataMapper::Model.append_extensions(DataMapper::Is::Select)
|
18
|
+
|
19
|
+
# If you wish to add methods to all DM Models, use this:
|
20
|
+
#
|
21
|
+
# DataMapper::Model.append_inclusions(DataMapper::Is::Select::ResourceInstanceMethods)
|
22
|
+
#
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Is
|
3
|
+
|
4
|
+
##
|
5
|
+
# = dm-is-select
|
6
|
+
#
|
7
|
+
# A DataMapper plugin that makes getting the <tt><select></tt> options from a Model easier.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
#
|
11
|
+
module Select
|
12
|
+
|
13
|
+
##
|
14
|
+
# Defines the field to use for the select menu
|
15
|
+
#
|
16
|
+
# ==== Params
|
17
|
+
#
|
18
|
+
# * :field_name => the name of the field values shown in select
|
19
|
+
# * :options
|
20
|
+
# * :is_tree => whether if the current Model is an is :tree model. (Defaults to false)
|
21
|
+
#
|
22
|
+
# ==== Examples
|
23
|
+
#
|
24
|
+
#
|
25
|
+
# is :select, :name
|
26
|
+
# => creates a <select> options array on the :name attribute of the model
|
27
|
+
#
|
28
|
+
# is :select, :name, :is_tree => true
|
29
|
+
# => creates a <select> options array with the results ordered in hierarchical order
|
30
|
+
# parent > child > grandchild for each parent
|
31
|
+
#
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
def is_select(select_field = :name, options = {})
|
35
|
+
raise ArgumentError, "The :select_field, must be an existing attribute in the Model. Got [ #{select_field.inspect} ]" unless properties.any?{ |p| p.name == select_field.to_sym }
|
36
|
+
|
37
|
+
@select_options = {
|
38
|
+
# add specical features if we are working with Tree Model
|
39
|
+
:is_tree => false
|
40
|
+
}.merge(options)
|
41
|
+
|
42
|
+
@select_field = select_field
|
43
|
+
|
44
|
+
|
45
|
+
# Add class & Instance methods
|
46
|
+
extend DataMapper::Is::Select::ClassMethods
|
47
|
+
# include DataMapper::Is::Select::InstanceMethods
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
module ClassMethods
|
52
|
+
attr_reader :select_field, :select_options
|
53
|
+
|
54
|
+
##
|
55
|
+
# Provides the Model content in a ready to use <tt><select></tt> options array
|
56
|
+
#
|
57
|
+
# ==== Params
|
58
|
+
#
|
59
|
+
# * :options
|
60
|
+
# * :prompt [String/Boolean] => The text shown on the <tt><select></tt> field in the browser. (Defaults to "Select NameOfYourModel")
|
61
|
+
# * :divider [Boolean] => Whether to add a divider/separator between the prompt and the main options. (Defaults to +true+)
|
62
|
+
# * :order [Array] => A normal DM order declaration. (Defaults to [:name] or the name of the select_field declared)
|
63
|
+
# * :show_root [Boolean] => Whether to add the Top Level Parent in the choices. (Defaults to +true+)
|
64
|
+
# * :root_text [String] => The text to show as the Parent item in select list. (Defaults to "Top Level NameOfYourModel")
|
65
|
+
#
|
66
|
+
# ==== Examples
|
67
|
+
#
|
68
|
+
# Category.items_for_select_menu
|
69
|
+
# => [ [nil, 'Select Category'], [nil, '---'], [1, 'Category 1'] ,....]
|
70
|
+
#
|
71
|
+
# Category.items_for_select_menu(:prompt => "Custom Prompt")
|
72
|
+
# => [ [nil, 'Custom Prompt'],...]
|
73
|
+
#
|
74
|
+
# Category.items_for_select_menu(:prompt => false)
|
75
|
+
# => [ [1, 'Category 1'] ,...]
|
76
|
+
#
|
77
|
+
# Category.items_for_select_menu(:divider => false )
|
78
|
+
# => array without the [nil, '---'] node
|
79
|
+
#
|
80
|
+
# Category.items_for_select_menu(:order => [ :id.desc ] )
|
81
|
+
# => array with the order reversed. (Prompts & divider always comes first)
|
82
|
+
#
|
83
|
+
# Category.items_for_select_menu(:publish_status => "on", :order => [ :id.desc ] )
|
84
|
+
# => returns only those items that matches the query params or just an empty Select Menu
|
85
|
+
#
|
86
|
+
# If your model is a Tree:
|
87
|
+
#
|
88
|
+
# Category.items_for_select_menu(:root_text => "Custom Root Text") # sets the text for the Top Level (root) Parent
|
89
|
+
# => [ ..., [0, 'Custom Root Text'],...]
|
90
|
+
#
|
91
|
+
# Category.items_for_select_menu(:show_root => false) # removes the Top Level (root) Parent from the
|
92
|
+
#
|
93
|
+
#
|
94
|
+
# @api public
|
95
|
+
def items_for_select_menu(options = {})
|
96
|
+
# clean out the various parts
|
97
|
+
html_options = options.only(:prompt, :divider, :show_root, :root_text)
|
98
|
+
sql_options = options.except(:prompt, :divider, :show_root, :root_text)
|
99
|
+
# puts "sql_options=[#{sql_options.inspect}] [#{__FILE__}:#{__LINE__}]"
|
100
|
+
# puts "html_options=[#{html_options.inspect}] [#{__FILE__}:#{__LINE__}]"
|
101
|
+
|
102
|
+
options = {
|
103
|
+
:prompt => "Select #{self.name}",
|
104
|
+
:divider => true,
|
105
|
+
:show_root => true,
|
106
|
+
:root_text => "Top Level #{self.name}",
|
107
|
+
}.merge(html_options)
|
108
|
+
|
109
|
+
sql_options = {
|
110
|
+
:order => [self.select_field.to_sym],
|
111
|
+
}.merge(sql_options)
|
112
|
+
|
113
|
+
mi = self.select_options[:is_tree] ?
|
114
|
+
all({ :parent_id => 0 }.merge(sql_options) ) :
|
115
|
+
all(sql_options)
|
116
|
+
|
117
|
+
res = []
|
118
|
+
if options[:prompt]
|
119
|
+
res << [nil, options[:prompt]]
|
120
|
+
res << ['nil', " ------ "] if options[:divider]
|
121
|
+
if self.select_options[:is_tree]
|
122
|
+
if options[:show_root]
|
123
|
+
res << [0, options[:root_text]]
|
124
|
+
res << ['nil'," ------ "] if options[:divider]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
if self.select_options[:is_tree]
|
130
|
+
mi.each do |x|
|
131
|
+
res << [x.id, x.send(self.select_field)]
|
132
|
+
unless x.children.blank?
|
133
|
+
x.children.each do |child|
|
134
|
+
res << [child.id, "-- #{child.send(self.select_field)}"]
|
135
|
+
child.children.each do |grand_child|
|
136
|
+
res << [ grand_child.id, "-- -- #{grand_child.send(self.select_field)}"]
|
137
|
+
end unless child.children.blank?
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
else
|
142
|
+
mi.each do |x|
|
143
|
+
res << [x.id, x.send(self.select_field)]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
res
|
147
|
+
end
|
148
|
+
|
149
|
+
end # ClassMethods
|
150
|
+
|
151
|
+
# module InstanceMethods
|
152
|
+
#
|
153
|
+
# end # InstanceMethods
|
154
|
+
|
155
|
+
end # Select
|
156
|
+
end # Is
|
157
|
+
|
158
|
+
Model.append_extensions(Is::Select)
|
159
|
+
|
160
|
+
end # DataMapper
|
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
5
|
+
describe 'DataMapper::Is::Select' do
|
6
|
+
|
7
|
+
class Category
|
8
|
+
include DataMapper::Resource
|
9
|
+
property :id, Serial
|
10
|
+
property :name, String
|
11
|
+
property :publish_status, String, :default => "on"
|
12
|
+
|
13
|
+
is :select, :name
|
14
|
+
|
15
|
+
auto_migrate!
|
16
|
+
end
|
17
|
+
|
18
|
+
class TreeCategory
|
19
|
+
include DataMapper::Resource
|
20
|
+
property :id, Serial
|
21
|
+
property :name, String
|
22
|
+
property :publish_status, String, :default => "on"
|
23
|
+
|
24
|
+
is :tree, :order => :name
|
25
|
+
is :select, :name, :is_tree => true
|
26
|
+
|
27
|
+
auto_migrate!
|
28
|
+
end
|
29
|
+
|
30
|
+
5.times do |n|
|
31
|
+
Category.create(:name => "Category #{n+1}")
|
32
|
+
end
|
33
|
+
|
34
|
+
2.times do |parent_id|
|
35
|
+
parent_id += 1
|
36
|
+
parent = TreeCategory.create(:name => "TreeCategory-#{parent_id}" , :parent_id => 0 )
|
37
|
+
child = TreeCategory.create(:name => "TreeCategory-#{parent_id}-Child" , :parent_id => parent.id )
|
38
|
+
grandchild = TreeCategory.create(:name => "TreeCategory-#{parent_id}-Child-GrandChild" , :parent_id => child.id )
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
describe "Class Methods" do
|
43
|
+
|
44
|
+
describe "is :select" do
|
45
|
+
|
46
|
+
it "should work with both strings & symbols as the fieldname provided" do
|
47
|
+
lambda {
|
48
|
+
class Dummy
|
49
|
+
include DataMapper::Resource
|
50
|
+
property :id, Serial
|
51
|
+
property :name, String
|
52
|
+
|
53
|
+
is :select, 'name'
|
54
|
+
auto_migrate!
|
55
|
+
end
|
56
|
+
|
57
|
+
}.should_not raise_error(ArgumentError)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should raise an ArgumentError if non-existant field is provided" do
|
61
|
+
lambda {
|
62
|
+
class Dummy
|
63
|
+
include DataMapper::Resource
|
64
|
+
property :id, Serial
|
65
|
+
property :name, String
|
66
|
+
|
67
|
+
is :select, :does_not_exist
|
68
|
+
auto_migrate!
|
69
|
+
end
|
70
|
+
|
71
|
+
}.should raise_error(ArgumentError)
|
72
|
+
end
|
73
|
+
|
74
|
+
end #/ is :select
|
75
|
+
|
76
|
+
describe "#items_for_select_menu" do
|
77
|
+
|
78
|
+
describe "A Normal Model" do
|
79
|
+
|
80
|
+
it "should return the default select options when given no params" do
|
81
|
+
Category.items_for_select_menu.should == [
|
82
|
+
[nil, "Select Category"],
|
83
|
+
["nil", " ------ "],
|
84
|
+
[1, "Category 1"],
|
85
|
+
[2, "Category 2"],
|
86
|
+
[3, "Category 3"],
|
87
|
+
[4, "Category 4"],
|
88
|
+
[5, "Category 5"]
|
89
|
+
]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should return the select options with custom prompt when given the :prompt => ? " do
|
93
|
+
Category.items_for_select_menu(:prompt => "Custom Prompt " ).should == [
|
94
|
+
[nil, "Custom Prompt "],
|
95
|
+
["nil", " ------ "],
|
96
|
+
[1, "Category 1"],
|
97
|
+
[2, "Category 2"],
|
98
|
+
[3, "Category 3"],
|
99
|
+
[4, "Category 4"],
|
100
|
+
[5, "Category 5"]
|
101
|
+
]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return the select options without a prompt & divider when given :prompt => false" do
|
105
|
+
Category.items_for_select_menu(:prompt => false ).should == [
|
106
|
+
[1, "Category 1"],
|
107
|
+
[2, "Category 2"],
|
108
|
+
[3, "Category 3"],
|
109
|
+
[4, "Category 4"],
|
110
|
+
[5, "Category 5"]
|
111
|
+
]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should return the select options without a prompt & divider when given :prompt => true" do
|
115
|
+
# TODO:: this should be reworked, but right now it's good enough
|
116
|
+
Category.items_for_select_menu(:prompt => true ).should == [
|
117
|
+
[nil, true],
|
118
|
+
["nil", " ------ "],
|
119
|
+
[1, "Category 1"],
|
120
|
+
[2, "Category 2"],
|
121
|
+
[3, "Category 3"],
|
122
|
+
[4, "Category 4"],
|
123
|
+
[5, "Category 5"]
|
124
|
+
]
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should return the select options without the divider when given :divider => false" do
|
128
|
+
Category.items_for_select_menu(:divider => false ).should == [
|
129
|
+
[nil, "Select Category"],
|
130
|
+
[1, "Category 1"],
|
131
|
+
[2, "Category 2"],
|
132
|
+
[3, "Category 3"],
|
133
|
+
[4, "Category 4"],
|
134
|
+
[5, "Category 5"]
|
135
|
+
]
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should return the select options with reversed order when given :order => DESC" do
|
139
|
+
Category.items_for_select_menu(:order => [ :id.desc ] ).should == [
|
140
|
+
[nil, "Select Category"],
|
141
|
+
["nil", " ------ "],
|
142
|
+
[5, "Category 5"],
|
143
|
+
[4, "Category 4"],
|
144
|
+
[3, "Category 3"],
|
145
|
+
[2, "Category 2"],
|
146
|
+
[1, "Category 1"]
|
147
|
+
]
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should respect the SQL select options" do
|
151
|
+
c = Category.get(1)
|
152
|
+
c.publish_status = 'off'
|
153
|
+
c.save
|
154
|
+
|
155
|
+
Category.items_for_select_menu(:publish_status => "on", :order => [ :id.desc ] ).should == [
|
156
|
+
[nil, "Select Category"],
|
157
|
+
["nil", " ------ "],
|
158
|
+
[5, "Category 5"],
|
159
|
+
[4, "Category 4"],
|
160
|
+
[3, "Category 3"],
|
161
|
+
[2, "Category 2"],
|
162
|
+
# [1, "Category 1"]
|
163
|
+
]
|
164
|
+
end
|
165
|
+
it "should handle invalid SQL select options" do
|
166
|
+
Category.items_for_select_menu(:publish_status => "invalid", :order => [ :id.desc ] ).should == [
|
167
|
+
[nil, "Select Category"],
|
168
|
+
["nil", " ------ "],
|
169
|
+
# [5, "Category 5"],
|
170
|
+
# [4, "Category 4"],
|
171
|
+
# [3, "Category 3"],
|
172
|
+
# [2, "Category 2"],
|
173
|
+
# [1, "Category 1"]
|
174
|
+
]
|
175
|
+
end
|
176
|
+
|
177
|
+
end #/ Normal Model
|
178
|
+
|
179
|
+
describe "Tree Model" do
|
180
|
+
|
181
|
+
it "should return the default select options when given no params" do
|
182
|
+
TreeCategory.items_for_select_menu.should == [
|
183
|
+
[nil, "Select TreeCategory"],
|
184
|
+
["nil", " ------ "],
|
185
|
+
[0, "Top Level TreeCategory"],
|
186
|
+
["nil", " ------ "],
|
187
|
+
[1, "TreeCategory-1"],
|
188
|
+
[2, "-- TreeCategory-1-Child"],
|
189
|
+
[3, "-- -- TreeCategory-1-Child-GrandChild"],
|
190
|
+
[4, "TreeCategory-2"],
|
191
|
+
[5, "-- TreeCategory-2-Child"],
|
192
|
+
[6, "-- -- TreeCategory-2-Child-GrandChild"]
|
193
|
+
]
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should return the select options with reversed order when given :order => DESC" do
|
197
|
+
TreeCategory.items_for_select_menu(:order => [ :id.desc ] ).should == [
|
198
|
+
[nil, "Select TreeCategory"],
|
199
|
+
["nil", " ------ "],
|
200
|
+
[0, "Top Level TreeCategory"],
|
201
|
+
["nil", " ------ "],
|
202
|
+
[4, "TreeCategory-2"],
|
203
|
+
[5, "-- TreeCategory-2-Child"],
|
204
|
+
[6, "-- -- TreeCategory-2-Child-GrandChild"],
|
205
|
+
[1, "TreeCategory-1"],
|
206
|
+
[2, "-- TreeCategory-1-Child"],
|
207
|
+
[3, "-- -- TreeCategory-1-Child-GrandChild"]
|
208
|
+
]
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should return the select options without the Top Level Parent when given :show_root => false" do
|
212
|
+
TreeCategory.items_for_select_menu(:show_root => false).should == [
|
213
|
+
[nil, "Select TreeCategory"],
|
214
|
+
["nil", " ------ "],
|
215
|
+
[1, "TreeCategory-1"],
|
216
|
+
[2, "-- TreeCategory-1-Child"],
|
217
|
+
[3, "-- -- TreeCategory-1-Child-GrandChild"],
|
218
|
+
[4, "TreeCategory-2"],
|
219
|
+
[5, "-- TreeCategory-2-Child"],
|
220
|
+
[6, "-- -- TreeCategory-2-Child-GrandChild"]
|
221
|
+
]
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should return the select options with custom text for the Top Level Parent when given :root_text => ?" do
|
225
|
+
TreeCategory.items_for_select_menu(:root_text => "Custom Top Level Text").should == [
|
226
|
+
[nil, "Select TreeCategory"],
|
227
|
+
["nil", " ------ "],
|
228
|
+
[0, "Custom Top Level Text"],
|
229
|
+
["nil", " ------ "],
|
230
|
+
[1, "TreeCategory-1"],
|
231
|
+
[2, "-- TreeCategory-1-Child"],
|
232
|
+
[3, "-- -- TreeCategory-1-Child-GrandChild"],
|
233
|
+
[4, "TreeCategory-2"],
|
234
|
+
[5, "-- TreeCategory-2-Child"],
|
235
|
+
[6, "-- -- TreeCategory-2-Child-GrandChild"]
|
236
|
+
]
|
237
|
+
end
|
238
|
+
|
239
|
+
it "should respect the SQL select options" do
|
240
|
+
c = TreeCategory.get(1)
|
241
|
+
c.publish_status = 'off'
|
242
|
+
c.save
|
243
|
+
|
244
|
+
TreeCategory.items_for_select_menu( :publish_status => "on", :order => [ :id.desc ] ).should == [
|
245
|
+
[nil, "Select TreeCategory"],
|
246
|
+
["nil", " ------ "],
|
247
|
+
[0, "Top Level TreeCategory"],
|
248
|
+
["nil", " ------ "],
|
249
|
+
[4, "TreeCategory-2"],
|
250
|
+
[5, "-- TreeCategory-2-Child"],
|
251
|
+
[6, "-- -- TreeCategory-2-Child-GrandChild"],
|
252
|
+
# [1, "TreeCategory-1"],
|
253
|
+
# [2, "-- TreeCategory-1-Child"],
|
254
|
+
# [3, "-- -- TreeCategory-1-Child-GrandChild"]
|
255
|
+
]
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should handle invalid SQL select options" do
|
259
|
+
TreeCategory.items_for_select_menu( :publish_status => "invalid", :order => [ :id.desc ] ).should == [
|
260
|
+
[nil, "Select TreeCategory"],
|
261
|
+
["nil", " ------ "],
|
262
|
+
[0, "Top Level TreeCategory"],
|
263
|
+
["nil", " ------ "],
|
264
|
+
# [4, "TreeCategory-2"],
|
265
|
+
# [5, "-- TreeCategory-2-Child"],
|
266
|
+
# [6, "-- -- TreeCategory-2-Child-GrandChild"],
|
267
|
+
# [1, "TreeCategory-1"],
|
268
|
+
# [2, "-- TreeCategory-1-Child"],
|
269
|
+
# [3, "-- -- TreeCategory-1-Child-GrandChild"]
|
270
|
+
]
|
271
|
+
end
|
272
|
+
|
273
|
+
end #/ Tree Model
|
274
|
+
|
275
|
+
end #/ #item_for_select_menu
|
276
|
+
|
277
|
+
end #/ Class Methods
|
278
|
+
|
279
|
+
# describe "Instance Methods" do
|
280
|
+
#
|
281
|
+
# end #/ Instance Methods
|
282
|
+
|
283
|
+
end #/ DataMapper::Is::Select
|
284
|
+
|
285
|
+
end #/ if
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
gem 'rspec', '~>1.2.6'
|
5
|
+
require 'spec'
|
6
|
+
# gem 'dm-is-tree', '~>0.10.0'
|
7
|
+
# require 'dm-is-tree'
|
8
|
+
|
9
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'lib/dm-is-select'
|
10
|
+
|
11
|
+
def load_driver(name, default_uri)
|
12
|
+
return false if ENV['ADAPTER'] != name.to_s
|
13
|
+
|
14
|
+
begin
|
15
|
+
DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
|
16
|
+
DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
|
17
|
+
true
|
18
|
+
rescue LoadError => e
|
19
|
+
warn "Could not load do_#{name}: #{e}"
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
ENV['ADAPTER'] ||= 'sqlite3'
|
25
|
+
|
26
|
+
HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
|
27
|
+
HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
|
28
|
+
HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dm-is-select
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kematzy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-30 00:00:00 +08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: dm-core
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dm-more
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.10.0
|
34
|
+
version:
|
35
|
+
description: A DataMapper plugin that makes getting the <tt>select</tt> options from a Model easier.
|
36
|
+
email: kematzy@gmail.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- History.rdoc
|
43
|
+
- LICENSE
|
44
|
+
- README.rdoc
|
45
|
+
- TODO
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- History.rdoc
|
49
|
+
- LICENSE
|
50
|
+
- README.rdoc
|
51
|
+
- Rakefile
|
52
|
+
- TODO
|
53
|
+
- VERSION
|
54
|
+
- dm-is-select.gemspec
|
55
|
+
- lib/dm-is-select.rb
|
56
|
+
- lib/dm-is-select/is/select.rb
|
57
|
+
- lib/dm-is-select/is/version.rb
|
58
|
+
- spec/integration/select_spec.rb
|
59
|
+
- spec/spec.opts
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://github.com/kematzy/dm-is-select
|
63
|
+
licenses: []
|
64
|
+
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options:
|
67
|
+
- --charset=UTF-8
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "0"
|
81
|
+
version:
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 1.3.5
|
86
|
+
signing_key:
|
87
|
+
specification_version: 3
|
88
|
+
summary: A DataMapper plugin that makes getting the <tt>select</tt> options from a Model easier.
|
89
|
+
test_files:
|
90
|
+
- spec/integration/select_spec.rb
|
91
|
+
- spec/spec_helper.rb
|