merb-admin 0.8.1 → 0.8.3
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 +29 -27
- data/Gemfile +24 -22
- data/Gemfile.lock +86 -0
- data/LICENSE +20 -20
- data/README.rdoc +54 -58
- data/Rakefile +11 -44
- data/app/controllers/application.rb +6 -6
- data/app/controllers/main.rb +191 -191
- data/app/helpers/application_helper.rb +64 -64
- data/app/helpers/main_helper.rb +167 -167
- data/app/models/.gitkeep +0 -0
- data/app/views/layout/_message.html.erb +10 -10
- data/app/views/layout/dashboard.html.erb +34 -34
- data/app/views/layout/form.html.erb +48 -48
- data/app/views/layout/list.html.erb +42 -42
- data/app/views/main/_belongs_to.html.erb +29 -29
- data/app/views/main/_big_decimal.html.erb +12 -12
- data/app/views/main/_boolean.html.erb +7 -7
- data/app/views/main/_date.html.erb +12 -12
- data/app/views/main/_datetime.html.erb +12 -12
- data/app/views/main/_float.html.erb +12 -12
- data/app/views/main/_has_many.html.erb +16 -16
- data/app/views/main/_has_one.html.erb +30 -30
- data/app/views/main/_integer.html.erb +12 -12
- data/app/views/main/_properties.html.erb +18 -18
- data/app/views/main/_string.html.erb +15 -15
- data/app/views/main/_text.html.erb +11 -11
- data/app/views/main/_time.html.erb +12 -12
- data/app/views/main/_timestamp.html.erb +12 -12
- data/app/views/main/delete.html.erb +28 -28
- data/app/views/main/edit.html.erb +19 -19
- data/app/views/main/index.html.erb +22 -22
- data/app/views/main/list.html.erb +93 -93
- data/app/views/main/new.html.erb +16 -16
- data/config/init.rb +30 -0
- data/config/router.rb +4 -0
- data/lib/abstract_model.rb +84 -86
- data/lib/active_record_support.rb +147 -147
- data/lib/datamapper_support.rb +139 -140
- data/lib/generic_support.rb +13 -13
- data/lib/merb-admin.rb +99 -99
- data/lib/merb-admin/merbtasks.rb +103 -103
- data/lib/merb-admin/slicetasks.rb +174 -174
- data/lib/merb-admin/spectasks.rb +55 -55
- data/lib/merb-admin/version.rb +3 -0
- data/lib/sequel_support.rb +275 -275
- data/merb-admin.gemspec +42 -232
- data/public/javascripts/CollapsedFieldsets.js +85 -85
- data/public/javascripts/DateTimeShortcuts.js +255 -255
- data/public/javascripts/RelatedObjectLookups.js +96 -96
- data/public/javascripts/SelectBox.js +111 -111
- data/public/javascripts/SelectFilter2.js +113 -113
- data/public/javascripts/actions.js +39 -39
- data/public/javascripts/calendar.js +143 -143
- data/public/javascripts/core.js +176 -176
- data/public/javascripts/dateparse.js +233 -233
- data/public/javascripts/getElementsBySelector.js +167 -167
- data/public/javascripts/i18n.js +33 -33
- data/public/javascripts/ordering.js +137 -137
- data/public/javascripts/timeparse.js +94 -94
- data/public/javascripts/urlify.js +140 -140
- data/public/stylesheets/base.css +746 -746
- data/public/stylesheets/changelists.css +269 -269
- data/public/stylesheets/dashboard.css +24 -24
- data/public/stylesheets/forms.css +327 -327
- data/public/stylesheets/global.css +142 -142
- data/public/stylesheets/ie.css +50 -50
- data/public/stylesheets/layout.css +29 -29
- data/public/stylesheets/login.css +54 -54
- data/public/stylesheets/master.css +1 -1
- data/public/stylesheets/patch-iewin.css +7 -7
- data/public/stylesheets/rtl.css +206 -206
- data/public/stylesheets/widgets.css +506 -506
- data/screenshots/create.png +0 -0
- data/screenshots/delete.png +0 -0
- data/screenshots/edit.png +0 -0
- data/screenshots/index.png +0 -0
- data/screenshots/list.png +0 -0
- data/screenshots/new.png +0 -0
- data/spec/controllers/main_spec.rb +25 -25
- data/spec/migrations/activerecord/001_create_divisions_migration.rb +13 -13
- data/spec/migrations/activerecord/002_create_drafts_migration.rb +19 -19
- data/spec/migrations/activerecord/003_create_leagues_migration.rb +12 -12
- data/spec/migrations/activerecord/004_create_players_migration.rb +19 -20
- data/spec/migrations/activerecord/005_create_teams_migration.rb +22 -22
- data/spec/migrations/sequel/001_create_divisions_migration.rb +15 -15
- data/spec/migrations/sequel/002_create_drafts_migration.rb +21 -21
- data/spec/migrations/sequel/003_create_leagues_migration.rb +14 -14
- data/spec/migrations/sequel/004_create_players_migration.rb +21 -22
- data/spec/migrations/sequel/005_create_teams_migration.rb +24 -24
- data/spec/models/activerecord/division.rb +7 -7
- data/spec/models/activerecord/draft.rb +11 -11
- data/spec/models/activerecord/league.rb +6 -6
- data/spec/models/activerecord/player.rb +8 -8
- data/spec/models/activerecord/team.rb +13 -13
- data/spec/models/datamapper/division.rb +12 -12
- data/spec/models/datamapper/draft.rb +18 -18
- data/spec/models/datamapper/league.rb +11 -11
- data/spec/models/datamapper/player.rb +20 -21
- data/spec/models/datamapper/team.rb +22 -22
- data/spec/models/sequel/division.rb +15 -15
- data/spec/models/sequel/draft.rb +19 -19
- data/spec/models/sequel/league.rb +14 -14
- data/spec/models/sequel/player.rb +18 -18
- data/spec/models/sequel/team.rb +21 -21
- data/spec/requests/main_spec.rb +763 -763
- data/spec/spec_helper.rb +113 -112
- metadata +247 -41
- data/VERSION +0 -1
data/lib/merb-admin/spectasks.rb
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
require 'spec/rake/spectask'
|
|
2
|
-
|
|
3
|
-
namespace :slices do
|
|
4
|
-
namespace :"merb-admin" do
|
|
5
|
-
|
|
6
|
-
desc "Run slice specs within the host application context"
|
|
7
|
-
task :spec => [ "spec:explain", "spec:default" ]
|
|
8
|
-
|
|
9
|
-
namespace :spec do
|
|
10
|
-
|
|
11
|
-
slice_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
|
12
|
-
|
|
13
|
-
task :explain do
|
|
14
|
-
puts "\nNote: By running MerbAdmin specs inside the application context any\n" +
|
|
15
|
-
"overrides could break existing specs. This isn't always a problem,\n" +
|
|
16
|
-
"especially in the case of views. Use these spec tasks to check how\n" +
|
|
17
|
-
"well your application conforms to the original slice implementation."
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
Spec::Rake::SpecTask.new('default') do |t|
|
|
21
|
-
t.spec_opts = ["--format", "specdoc", "--colour"]
|
|
22
|
-
t.spec_files = Dir["#{slice_root}/spec/**/*_spec.rb"].sort
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
desc "Run all model specs, run a spec for a specific Model with MODEL=MyModel"
|
|
26
|
-
Spec::Rake::SpecTask.new('model') do |t|
|
|
27
|
-
t.spec_opts = ["--format", "specdoc", "--colour"]
|
|
28
|
-
if(ENV['MODEL'])
|
|
29
|
-
t.spec_files = Dir["#{slice_root}/spec/models/**/#{ENV['MODEL']}_spec.rb"].sort
|
|
30
|
-
else
|
|
31
|
-
t.spec_files = Dir["#{slice_root}/spec/models/**/*_spec.rb"].sort
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
desc "Run all request specs, run a spec for a specific request with REQUEST=MyRequest"
|
|
36
|
-
Spec::Rake::SpecTask.new('request') do |t|
|
|
37
|
-
t.spec_opts = ["--format", "specdoc", "--colour"]
|
|
38
|
-
if(ENV['REQUEST'])
|
|
39
|
-
t.spec_files = Dir["#{slice_root}/spec/requests/**/#{ENV['REQUEST']}_spec.rb"].sort
|
|
40
|
-
else
|
|
41
|
-
t.spec_files = Dir["#{slice_root}/spec/requests/**/*_spec.rb"].sort
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
desc "Run all specs and output the result in html"
|
|
46
|
-
Spec::Rake::SpecTask.new('html') do |t|
|
|
47
|
-
t.spec_opts = ["--format", "html"]
|
|
48
|
-
t.libs = ['lib', 'server/lib' ]
|
|
49
|
-
t.spec_files = Dir["#{slice_root}/spec/**/*_spec.rb"].sort
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
end
|
|
55
|
-
end
|
|
1
|
+
require 'spec/rake/spectask'
|
|
2
|
+
|
|
3
|
+
namespace :slices do
|
|
4
|
+
namespace :"merb-admin" do
|
|
5
|
+
|
|
6
|
+
desc "Run slice specs within the host application context"
|
|
7
|
+
task :spec => [ "spec:explain", "spec:default" ]
|
|
8
|
+
|
|
9
|
+
namespace :spec do
|
|
10
|
+
|
|
11
|
+
slice_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
|
12
|
+
|
|
13
|
+
task :explain do
|
|
14
|
+
puts "\nNote: By running MerbAdmin specs inside the application context any\n" +
|
|
15
|
+
"overrides could break existing specs. This isn't always a problem,\n" +
|
|
16
|
+
"especially in the case of views. Use these spec tasks to check how\n" +
|
|
17
|
+
"well your application conforms to the original slice implementation."
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Spec::Rake::SpecTask.new('default') do |t|
|
|
21
|
+
t.spec_opts = ["--format", "specdoc", "--colour"]
|
|
22
|
+
t.spec_files = Dir["#{slice_root}/spec/**/*_spec.rb"].sort
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc "Run all model specs, run a spec for a specific Model with MODEL=MyModel"
|
|
26
|
+
Spec::Rake::SpecTask.new('model') do |t|
|
|
27
|
+
t.spec_opts = ["--format", "specdoc", "--colour"]
|
|
28
|
+
if(ENV['MODEL'])
|
|
29
|
+
t.spec_files = Dir["#{slice_root}/spec/models/**/#{ENV['MODEL']}_spec.rb"].sort
|
|
30
|
+
else
|
|
31
|
+
t.spec_files = Dir["#{slice_root}/spec/models/**/*_spec.rb"].sort
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
desc "Run all request specs, run a spec for a specific request with REQUEST=MyRequest"
|
|
36
|
+
Spec::Rake::SpecTask.new('request') do |t|
|
|
37
|
+
t.spec_opts = ["--format", "specdoc", "--colour"]
|
|
38
|
+
if(ENV['REQUEST'])
|
|
39
|
+
t.spec_files = Dir["#{slice_root}/spec/requests/**/#{ENV['REQUEST']}_spec.rb"].sort
|
|
40
|
+
else
|
|
41
|
+
t.spec_files = Dir["#{slice_root}/spec/requests/**/*_spec.rb"].sort
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
desc "Run all specs and output the result in html"
|
|
46
|
+
Spec::Rake::SpecTask.new('html') do |t|
|
|
47
|
+
t.spec_opts = ["--format", "html"]
|
|
48
|
+
t.libs = ['lib', 'server/lib' ]
|
|
49
|
+
t.spec_files = Dir["#{slice_root}/spec/**/*_spec.rb"].sort
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/sequel_support.rb
CHANGED
|
@@ -1,275 +1,275 @@
|
|
|
1
|
-
require 'sequel'
|
|
2
|
-
require 'sequel/extensions/pagination'
|
|
3
|
-
|
|
4
|
-
class Sequel::Model
|
|
5
|
-
=begin
|
|
6
|
-
# Intialize each column to the default value for new model objects
|
|
7
|
-
def after_initialize
|
|
8
|
-
super
|
|
9
|
-
model.columns.each do |x|
|
|
10
|
-
if !@values.include?(x) && db_schema[x][:allow_null]
|
|
11
|
-
send("#{x}=", db_schema[x][:ruby_default])
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
=end
|
|
16
|
-
|
|
17
|
-
# Return an empty array for *_to_many association methods for new model objects
|
|
18
|
-
def _load_associated_objects(opts)
|
|
19
|
-
opts.returns_array? && new? ? [] : super
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
module MerbAdmin
|
|
24
|
-
class AbstractModel
|
|
25
|
-
module SequelSupport
|
|
26
|
-
def get(id)
|
|
27
|
-
model.first(:id => id).extend(InstanceMethods)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def count(options = {})
|
|
31
|
-
if options[:conditions] && !options[:conditions].empty?
|
|
32
|
-
model.where(options[:conditions]).count
|
|
33
|
-
else
|
|
34
|
-
model.count
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def first(options = {})
|
|
39
|
-
sort = options.delete(:sort) || :id
|
|
40
|
-
sort_order = options.delete(:sort_reverse) ? :desc : :asc
|
|
41
|
-
|
|
42
|
-
if options[:conditions] && !options[:conditions].empty?
|
|
43
|
-
model.order(sort.to_sym.send(sort_order)).first(options[:conditions]).extend(InstanceMethods)
|
|
44
|
-
else
|
|
45
|
-
model.order(sort.to_sym.send(sort_order)).first.extend(InstanceMethods)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def all(options = {})
|
|
50
|
-
offset = options.delete(:offset)
|
|
51
|
-
limit = options.delete(:limit)
|
|
52
|
-
|
|
53
|
-
sort = options.delete(:sort) || :id
|
|
54
|
-
sort_order = options.delete(:sort_reverse) ? :desc : :asc
|
|
55
|
-
|
|
56
|
-
if options[:conditions] && !options[:conditions].empty?
|
|
57
|
-
model.where(options[:conditions]).order(sort.to_sym.send(sort_order))
|
|
58
|
-
else
|
|
59
|
-
model.order(sort.to_sym.send(sort_order))
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def paginated(options = {})
|
|
64
|
-
page = options.delete(:page) || 1
|
|
65
|
-
per_page = options.delete(:per_page) || MerbAdmin[:per_page]
|
|
66
|
-
page_count = (count(options).to_f / per_page).ceil
|
|
67
|
-
|
|
68
|
-
sort = options.delete(:sort) || :id
|
|
69
|
-
sort_order = options.delete(:sort_reverse) ? :desc : :asc
|
|
70
|
-
|
|
71
|
-
if options[:conditions] && !options[:conditions].empty?
|
|
72
|
-
[page_count, model.paginate(page.to_i, per_page).where(options[:conditions]).order(sort.to_sym.send(sort_order))]
|
|
73
|
-
else
|
|
74
|
-
[page_count, model.paginate(page.to_i, per_page).order(sort.to_sym.send(sort_order))]
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def create(params = {})
|
|
79
|
-
model.create(params).extend(InstanceMethods)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def new(params = {})
|
|
83
|
-
model.new(params).extend(InstanceMethods)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def destroy_all!
|
|
87
|
-
model.destroy
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def has_many_associations
|
|
91
|
-
associations.select do |association|
|
|
92
|
-
association[:type] == :has_many
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def has_one_associations
|
|
97
|
-
associations.select do |association|
|
|
98
|
-
association[:type] == :has_one
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def belongs_to_associations
|
|
103
|
-
associations.select do |association|
|
|
104
|
-
association[:type] == :belongs_to
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def associations
|
|
109
|
-
model.all_association_reflections.map do |association|
|
|
110
|
-
{
|
|
111
|
-
:name => association_name_lookup(association),
|
|
112
|
-
:pretty_name => association_pretty_name_lookup(association),
|
|
113
|
-
:type => association_type_lookup(association),
|
|
114
|
-
:parent_model => association_parent_model_lookup(association),
|
|
115
|
-
:parent_key => association_parent_key_lookup(association),
|
|
116
|
-
:child_model => association_child_model_lookup(association),
|
|
117
|
-
:child_key => association_child_key_lookup(association),
|
|
118
|
-
}
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def properties
|
|
123
|
-
model.columns.map do |property|
|
|
124
|
-
{
|
|
125
|
-
:name => property,
|
|
126
|
-
:pretty_name => property.to_s.gsub(/_id$/, "").gsub("_", " ").capitalize,
|
|
127
|
-
:type => property_type_lookup(property),
|
|
128
|
-
:length => property_length_lookup(property),
|
|
129
|
-
:nullable? => model.db_schema[property][:allow_null],
|
|
130
|
-
:serial? => model.db_schema[property][:primary_key],
|
|
131
|
-
}
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
private
|
|
136
|
-
|
|
137
|
-
def property_type_lookup(property)
|
|
138
|
-
case model.db_schema[property][:db_type]
|
|
139
|
-
when /\A(?:medium|small)?int(?:eger)?(?:\((?:\d+)\))?\z/io
|
|
140
|
-
:integer
|
|
141
|
-
when /\Atinyint(?:\((\d+)\))?\z/io
|
|
142
|
-
:boolean
|
|
143
|
-
when /\Abigint(?:\((?:\d+)\))?\z/io
|
|
144
|
-
:integer
|
|
145
|
-
when /\A(?:real|float|double(?: precision)?)\z/io
|
|
146
|
-
:float
|
|
147
|
-
when 'boolean'
|
|
148
|
-
:boolean
|
|
149
|
-
when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/io
|
|
150
|
-
:text
|
|
151
|
-
when 'date'
|
|
152
|
-
:date
|
|
153
|
-
when /\A(?:small)?datetime\z/io
|
|
154
|
-
:datetime
|
|
155
|
-
when /\Atimestamp(?: with(?:out)? time zone)?\z/io
|
|
156
|
-
:datetime
|
|
157
|
-
when /\Atime(?: with(?:out)? time zone)?\z/io
|
|
158
|
-
:time
|
|
159
|
-
when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
|
|
160
|
-
:string
|
|
161
|
-
when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
|
|
162
|
-
:string
|
|
163
|
-
when /\A(?:small)?money\z/io
|
|
164
|
-
:big_decimal
|
|
165
|
-
when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/io
|
|
166
|
-
:big_decimal
|
|
167
|
-
when 'year'
|
|
168
|
-
:integer
|
|
169
|
-
else
|
|
170
|
-
:string
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def property_length_lookup(property)
|
|
175
|
-
case model.db_schema[property][:db_type]
|
|
176
|
-
when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
|
|
177
|
-
$1 ? $1.to_i : 255
|
|
178
|
-
when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
|
|
179
|
-
$1 ? $1.to_i : 255
|
|
180
|
-
else
|
|
181
|
-
nil
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
def association_name_lookup(association)
|
|
186
|
-
case association[:type]
|
|
187
|
-
when :one_to_many
|
|
188
|
-
if association[:one_to_one]
|
|
189
|
-
association[:name].to_s.singularize.to_sym
|
|
190
|
-
else
|
|
191
|
-
association[:name]
|
|
192
|
-
end
|
|
193
|
-
when :many_to_one
|
|
194
|
-
association[:name]
|
|
195
|
-
else
|
|
196
|
-
raise "Unknown association type"
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
def association_pretty_name_lookup(association)
|
|
201
|
-
case association[:type]
|
|
202
|
-
when :one_to_many
|
|
203
|
-
if association[:one_to_one]
|
|
204
|
-
association[:name].to_s.singularize.gsub('_', ' ').capitalize
|
|
205
|
-
else
|
|
206
|
-
association[:name].to_s.gsub('_', ' ').capitalize
|
|
207
|
-
end
|
|
208
|
-
when :many_to_one
|
|
209
|
-
association[:name].to_s.gsub('_', ' ').capitalize
|
|
210
|
-
else
|
|
211
|
-
raise "Unknown association type"
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def association_type_lookup(association)
|
|
216
|
-
case association[:type]
|
|
217
|
-
when :one_to_many
|
|
218
|
-
if association[:one_to_one]
|
|
219
|
-
:has_one
|
|
220
|
-
else
|
|
221
|
-
:has_many
|
|
222
|
-
end
|
|
223
|
-
when :many_to_one
|
|
224
|
-
:belongs_to
|
|
225
|
-
else
|
|
226
|
-
raise "Unknown association type"
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def association_parent_model_lookup(association)
|
|
231
|
-
case association[:type]
|
|
232
|
-
when :one_to_many
|
|
233
|
-
association[:model]
|
|
234
|
-
when :many_to_one
|
|
235
|
-
Object.const_get(association[:class_name])
|
|
236
|
-
else
|
|
237
|
-
raise "Unknown association type"
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def association_parent_key_lookup(association)
|
|
242
|
-
[:id]
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def association_child_model_lookup(association)
|
|
246
|
-
case association[:type]
|
|
247
|
-
when :one_to_many
|
|
248
|
-
Object.const_get(association[:class_name])
|
|
249
|
-
when :many_to_one
|
|
250
|
-
association[:model]
|
|
251
|
-
else
|
|
252
|
-
raise "Unknown association type"
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
def association_child_key_lookup(association)
|
|
257
|
-
case association[:type]
|
|
258
|
-
when :one_to_many
|
|
259
|
-
association[:keys]
|
|
260
|
-
when :many_to_one
|
|
261
|
-
["#{association[:class_name].snake_case}_id".to_sym]
|
|
262
|
-
else
|
|
263
|
-
raise "Unknown association type"
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
module InstanceMethods
|
|
268
|
-
def update_attributes(attributes)
|
|
269
|
-
update(attributes)
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
end
|
|
1
|
+
require 'sequel'
|
|
2
|
+
require 'sequel/extensions/pagination'
|
|
3
|
+
|
|
4
|
+
class Sequel::Model
|
|
5
|
+
=begin
|
|
6
|
+
# Intialize each column to the default value for new model objects
|
|
7
|
+
def after_initialize
|
|
8
|
+
super
|
|
9
|
+
model.columns.each do |x|
|
|
10
|
+
if !@values.include?(x) && db_schema[x][:allow_null]
|
|
11
|
+
send("#{x}=", db_schema[x][:ruby_default])
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
=end
|
|
16
|
+
|
|
17
|
+
# Return an empty array for *_to_many association methods for new model objects
|
|
18
|
+
def _load_associated_objects(opts)
|
|
19
|
+
opts.returns_array? && new? ? [] : super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module MerbAdmin
|
|
24
|
+
class AbstractModel
|
|
25
|
+
module SequelSupport
|
|
26
|
+
def get(id)
|
|
27
|
+
model.first(:id => id).extend(InstanceMethods)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def count(options = {})
|
|
31
|
+
if options[:conditions] && !options[:conditions].empty?
|
|
32
|
+
model.where(options[:conditions]).count
|
|
33
|
+
else
|
|
34
|
+
model.count
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def first(options = {})
|
|
39
|
+
sort = options.delete(:sort) || :id
|
|
40
|
+
sort_order = options.delete(:sort_reverse) ? :desc : :asc
|
|
41
|
+
|
|
42
|
+
if options[:conditions] && !options[:conditions].empty?
|
|
43
|
+
model.order(sort.to_sym.send(sort_order)).first(options[:conditions]).extend(InstanceMethods)
|
|
44
|
+
else
|
|
45
|
+
model.order(sort.to_sym.send(sort_order)).first.extend(InstanceMethods)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def all(options = {})
|
|
50
|
+
offset = options.delete(:offset)
|
|
51
|
+
limit = options.delete(:limit)
|
|
52
|
+
|
|
53
|
+
sort = options.delete(:sort) || :id
|
|
54
|
+
sort_order = options.delete(:sort_reverse) ? :desc : :asc
|
|
55
|
+
|
|
56
|
+
if options[:conditions] && !options[:conditions].empty?
|
|
57
|
+
model.where(options[:conditions]).order(sort.to_sym.send(sort_order))
|
|
58
|
+
else
|
|
59
|
+
model.order(sort.to_sym.send(sort_order))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def paginated(options = {})
|
|
64
|
+
page = options.delete(:page) || 1
|
|
65
|
+
per_page = options.delete(:per_page) || MerbAdmin[:per_page]
|
|
66
|
+
page_count = (count(options).to_f / per_page).ceil
|
|
67
|
+
|
|
68
|
+
sort = options.delete(:sort) || :id
|
|
69
|
+
sort_order = options.delete(:sort_reverse) ? :desc : :asc
|
|
70
|
+
|
|
71
|
+
if options[:conditions] && !options[:conditions].empty?
|
|
72
|
+
[page_count, model.paginate(page.to_i, per_page).where(options[:conditions]).order(sort.to_sym.send(sort_order))]
|
|
73
|
+
else
|
|
74
|
+
[page_count, model.paginate(page.to_i, per_page).order(sort.to_sym.send(sort_order))]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def create(params = {})
|
|
79
|
+
model.create(params).extend(InstanceMethods)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def new(params = {})
|
|
83
|
+
model.new(params).extend(InstanceMethods)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def destroy_all!
|
|
87
|
+
model.destroy
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def has_many_associations
|
|
91
|
+
associations.select do |association|
|
|
92
|
+
association[:type] == :has_many
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def has_one_associations
|
|
97
|
+
associations.select do |association|
|
|
98
|
+
association[:type] == :has_one
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def belongs_to_associations
|
|
103
|
+
associations.select do |association|
|
|
104
|
+
association[:type] == :belongs_to
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def associations
|
|
109
|
+
model.all_association_reflections.map do |association|
|
|
110
|
+
{
|
|
111
|
+
:name => association_name_lookup(association),
|
|
112
|
+
:pretty_name => association_pretty_name_lookup(association),
|
|
113
|
+
:type => association_type_lookup(association),
|
|
114
|
+
:parent_model => association_parent_model_lookup(association),
|
|
115
|
+
:parent_key => association_parent_key_lookup(association),
|
|
116
|
+
:child_model => association_child_model_lookup(association),
|
|
117
|
+
:child_key => association_child_key_lookup(association),
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def properties
|
|
123
|
+
model.columns.map do |property|
|
|
124
|
+
{
|
|
125
|
+
:name => property,
|
|
126
|
+
:pretty_name => property.to_s.gsub(/_id$/, "").gsub("_", " ").capitalize,
|
|
127
|
+
:type => property_type_lookup(property),
|
|
128
|
+
:length => property_length_lookup(property),
|
|
129
|
+
:nullable? => model.db_schema[property][:allow_null],
|
|
130
|
+
:serial? => model.db_schema[property][:primary_key],
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
def property_type_lookup(property)
|
|
138
|
+
case model.db_schema[property][:db_type]
|
|
139
|
+
when /\A(?:medium|small)?int(?:eger)?(?:\((?:\d+)\))?\z/io
|
|
140
|
+
:integer
|
|
141
|
+
when /\Atinyint(?:\((\d+)\))?\z/io
|
|
142
|
+
:boolean
|
|
143
|
+
when /\Abigint(?:\((?:\d+)\))?\z/io
|
|
144
|
+
:integer
|
|
145
|
+
when /\A(?:real|float|double(?: precision)?)\z/io
|
|
146
|
+
:float
|
|
147
|
+
when 'boolean'
|
|
148
|
+
:boolean
|
|
149
|
+
when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/io
|
|
150
|
+
:text
|
|
151
|
+
when 'date'
|
|
152
|
+
:date
|
|
153
|
+
when /\A(?:small)?datetime\z/io
|
|
154
|
+
:datetime
|
|
155
|
+
when /\Atimestamp(?: with(?:out)? time zone)?\z/io
|
|
156
|
+
:datetime
|
|
157
|
+
when /\Atime(?: with(?:out)? time zone)?\z/io
|
|
158
|
+
:time
|
|
159
|
+
when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
|
|
160
|
+
:string
|
|
161
|
+
when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
|
|
162
|
+
:string
|
|
163
|
+
when /\A(?:small)?money\z/io
|
|
164
|
+
:big_decimal
|
|
165
|
+
when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/io
|
|
166
|
+
:big_decimal
|
|
167
|
+
when 'year'
|
|
168
|
+
:integer
|
|
169
|
+
else
|
|
170
|
+
:string
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def property_length_lookup(property)
|
|
175
|
+
case model.db_schema[property][:db_type]
|
|
176
|
+
when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
|
|
177
|
+
$1 ? $1.to_i : 255
|
|
178
|
+
when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
|
|
179
|
+
$1 ? $1.to_i : 255
|
|
180
|
+
else
|
|
181
|
+
nil
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def association_name_lookup(association)
|
|
186
|
+
case association[:type]
|
|
187
|
+
when :one_to_many
|
|
188
|
+
if association[:one_to_one]
|
|
189
|
+
association[:name].to_s.singularize.to_sym
|
|
190
|
+
else
|
|
191
|
+
association[:name]
|
|
192
|
+
end
|
|
193
|
+
when :many_to_one
|
|
194
|
+
association[:name]
|
|
195
|
+
else
|
|
196
|
+
raise "Unknown association type"
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def association_pretty_name_lookup(association)
|
|
201
|
+
case association[:type]
|
|
202
|
+
when :one_to_many
|
|
203
|
+
if association[:one_to_one]
|
|
204
|
+
association[:name].to_s.singularize.gsub('_', ' ').capitalize
|
|
205
|
+
else
|
|
206
|
+
association[:name].to_s.gsub('_', ' ').capitalize
|
|
207
|
+
end
|
|
208
|
+
when :many_to_one
|
|
209
|
+
association[:name].to_s.gsub('_', ' ').capitalize
|
|
210
|
+
else
|
|
211
|
+
raise "Unknown association type"
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def association_type_lookup(association)
|
|
216
|
+
case association[:type]
|
|
217
|
+
when :one_to_many
|
|
218
|
+
if association[:one_to_one]
|
|
219
|
+
:has_one
|
|
220
|
+
else
|
|
221
|
+
:has_many
|
|
222
|
+
end
|
|
223
|
+
when :many_to_one
|
|
224
|
+
:belongs_to
|
|
225
|
+
else
|
|
226
|
+
raise "Unknown association type"
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def association_parent_model_lookup(association)
|
|
231
|
+
case association[:type]
|
|
232
|
+
when :one_to_many
|
|
233
|
+
association[:model]
|
|
234
|
+
when :many_to_one
|
|
235
|
+
Object.const_get(association[:class_name])
|
|
236
|
+
else
|
|
237
|
+
raise "Unknown association type"
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def association_parent_key_lookup(association)
|
|
242
|
+
[:id]
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def association_child_model_lookup(association)
|
|
246
|
+
case association[:type]
|
|
247
|
+
when :one_to_many
|
|
248
|
+
Object.const_get(association[:class_name])
|
|
249
|
+
when :many_to_one
|
|
250
|
+
association[:model]
|
|
251
|
+
else
|
|
252
|
+
raise "Unknown association type"
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def association_child_key_lookup(association)
|
|
257
|
+
case association[:type]
|
|
258
|
+
when :one_to_many
|
|
259
|
+
association[:keys]
|
|
260
|
+
when :many_to_one
|
|
261
|
+
["#{association[:class_name].snake_case}_id".to_sym]
|
|
262
|
+
else
|
|
263
|
+
raise "Unknown association type"
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
module InstanceMethods
|
|
268
|
+
def update_attributes(attributes)
|
|
269
|
+
update(attributes)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|