dm-is-select 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|