Skip to content

Commit 061fa28

Browse files
committed
added Sequel support
1 parent ccb8ff0 commit 061fa28

15 files changed

+540
-2
lines changed

lib/abstract_model.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ def self.all
2424
@models << new(model) if model
2525
end
2626
@models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
27+
when :sequel
28+
Dir.glob(Merb.dir_for(:model) / Merb.glob_for(:model)).each do |filename|
29+
# FIXME: This heuristic for finding Sequel models could be too strict
30+
File.read(filename).scan(/^class ([\w\d_\-:]+) < Sequel::Model$/).flatten.each do |m|
31+
model = lookup(m.to_s.to_sym)
32+
@models << new(model) if model
33+
end
34+
end
35+
@models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
2736
else
2837
raise "MerbAdmin does not support the #{Merb.orm} ORM"
2938
end
@@ -42,6 +51,8 @@ def self.lookup(model_name)
4251
return model if model.superclass == ActiveRecord::Base
4352
when :datamapper
4453
return model if model.include?(DataMapper::Resource)
54+
when :sequel
55+
return model if model.superclass == Sequel::Model
4556
end
4657
nil
4758
end
@@ -59,6 +70,9 @@ def initialize(model)
5970
when :datamapper
6071
require 'datamapper_support'
6172
self.extend(DatamapperSupport)
73+
when :sequel
74+
require 'sequel_support'
75+
self.extend(SequelSupport)
6276
else
6377
raise "MerbAdmin does not support the #{Merb.orm} ORM"
6478
end

lib/merb-admin/slicetasks.rb

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@
5151
end
5252
end
5353

54+
desc "Copies sample models, copies and runs sample migrations, and loads sample data"
55+
task :sequel => ["sequel:copy_sample_models", "sequel:copy_sample_migrations", "sequel:migrate", "load_sample_data"]
56+
namespace :sequel do
57+
desc "Copies sample models into your app"
58+
task :copy_sample_models do
59+
copy_models(:sequel)
60+
end
61+
62+
desc "Copies sample migrations into your app"
63+
task :copy_sample_migrations do
64+
copy_migrations(:sequel)
65+
end
66+
67+
desc "Perform migration using migrations in schema/migrations"
68+
task :migrate do
69+
require 'sequel/extensions/migration'
70+
Rake::Task["sequel:db:migrate"].reenable
71+
Rake::Task["sequel:db:migrate"].invoke
72+
end
73+
end
74+
5475
desc "Loads sample data into your app"
5576
task :load_sample_data do
5677
load_data
@@ -63,13 +84,13 @@
6384

6485
def load_data
6586
begin
66-
require "mlb"
87+
require "mlb"
6788
rescue LoadError => e
6889
puts "LoadError: #{e}"
6990
puts "gem install mlb -s http://gemcutter.org"
7091
return
7192
end
72-
93+
7394
puts "Loading current MLB leagues, divisions, teams, and players"
7495
MLB.teams.each do |mlb_team|
7596
unless league = MerbAdmin::AbstractModel.new("League").first(:conditions => ["name = ?", mlb_team.league])

lib/sequel_support.rb

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
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+
# If options[:conditions] isn't cloned, Sequel eats the first condition!
33+
model.where(options[:conditions].clone).count
34+
else
35+
model.count
36+
end
37+
end
38+
39+
def first(options = {})
40+
sort = options.delete(:sort) || :id
41+
sort_order = options.delete(:sort_reverse) ? :desc : :asc
42+
43+
if options[:conditions] && !options[:conditions].empty?
44+
# If options[:conditions] isn't cloned, Sequel eats the first condition!
45+
model.order(sort.to_sym.send(sort_order)).first(options[:conditions].clone).extend(InstanceMethods)
46+
else
47+
model.order(sort.to_sym.send(sort_order)).first.extend(InstanceMethods)
48+
end
49+
end
50+
51+
def all(options = {})
52+
offset = options.delete(:offset)
53+
limit = options.delete(:limit)
54+
55+
sort = options.delete(:sort) || :id
56+
sort_order = options.delete(:sort_reverse) ? :desc : :asc
57+
58+
if options[:conditions] && !options[:conditions].empty?
59+
# If options[:conditions] isn't cloned, Sequel eats the first condition!
60+
model.where(options[:conditions].clone).order(sort.to_sym.send(sort_order))
61+
else
62+
model.order(sort.to_sym.send(sort_order))
63+
end
64+
end
65+
66+
def paginated(options = {})
67+
page = options.delete(:page) || 1
68+
per_page = options.delete(:per_page) || MerbAdmin[:per_page]
69+
page_count = (count(options).to_f / per_page).ceil
70+
71+
sort = options.delete(:sort) || :id
72+
sort_order = options.delete(:sort_reverse) ? :desc : :asc
73+
74+
if options[:conditions] && !options[:conditions].empty?
75+
# If options[:conditions] isn't cloned, Sequel eats the first condition!
76+
[page_count, model.paginate(page.to_i, per_page).where(options[:conditions].clone).order(sort.to_sym.send(sort_order))]
77+
else
78+
[page_count, model.paginate(page.to_i, per_page).order(sort.to_sym.send(sort_order))]
79+
end
80+
end
81+
82+
def create(params = {})
83+
model.create(params)
84+
end
85+
86+
def new(params = {})
87+
model.new(params).extend(InstanceMethods)
88+
end
89+
90+
def destroy_all!
91+
model.all.each do |object|
92+
object.destroy
93+
end
94+
end
95+
96+
def has_many_associations
97+
associations.select do |association|
98+
association[:type] == :has_many
99+
end
100+
end
101+
102+
def has_one_associations
103+
associations.select do |association|
104+
association[:type] == :has_one
105+
end
106+
end
107+
108+
def belongs_to_associations
109+
associations.select do |association|
110+
association[:type] == :belongs_to
111+
end
112+
end
113+
114+
def associations
115+
model.all_association_reflections.map do |association|
116+
{
117+
:name => association_name_lookup(association),
118+
:pretty_name => association_pretty_name_lookup(association),
119+
:type => association_type_lookup(association),
120+
:parent_model => association_parent_model_lookup(association),
121+
:parent_key => association_parent_key_lookup(association),
122+
:child_model => association_child_model_lookup(association),
123+
:child_key => association_child_key_lookup(association),
124+
}
125+
end
126+
end
127+
128+
def properties
129+
model.columns.map do |property|
130+
{
131+
:name => property,
132+
:pretty_name => property.to_s.gsub(/_id$/, "").gsub("_", " ").capitalize,
133+
:type => property_type_lookup(property),
134+
:length => property_length_lookup(property),
135+
:nullable? => model.db_schema[property][:allow_null],
136+
:serial? => model.db_schema[property][:primary_key],
137+
}
138+
end
139+
end
140+
141+
private
142+
143+
def property_type_lookup(property)
144+
case model.db_schema[property][:db_type]
145+
when /\A(?:medium|small)?int(?:eger)?(?:\((?:\d+)\))?\z/io
146+
:integer
147+
when /\Atinyint(?:\((\d+)\))?\z/io
148+
:boolean
149+
when /\Abigint(?:\((?:\d+)\))?\z/io
150+
:integer
151+
when /\A(?:real|float|double(?: precision)?)\z/io
152+
:float
153+
when 'boolean'
154+
:boolean
155+
when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/io
156+
:text
157+
when 'date'
158+
:date
159+
when /\A(?:small)?datetime\z/io
160+
:datetime
161+
when /\Atimestamp(?: with(?:out)? time zone)?\z/io
162+
:datetime
163+
when /\Atime(?: with(?:out)? time zone)?\z/io
164+
:time
165+
when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
166+
:string
167+
when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
168+
:string
169+
when /\A(?:small)?money\z/io
170+
:big_decimal
171+
when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/io
172+
:big_decimal
173+
when 'year'
174+
:integer
175+
else
176+
:string
177+
end
178+
end
179+
180+
def property_length_lookup(property)
181+
case model.db_schema[property][:db_type]
182+
when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
183+
$1 ? $1.to_i : 255
184+
when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
185+
$1 ? $1.to_i : 255
186+
else
187+
nil
188+
end
189+
end
190+
191+
def association_name_lookup(association)
192+
case association[:type]
193+
when :one_to_many
194+
if association[:one_to_one]
195+
association[:name].to_s.singularize.to_sym
196+
else
197+
association[:name]
198+
end
199+
when :many_to_one
200+
association[:name]
201+
else
202+
raise "Unknown association type"
203+
end
204+
end
205+
206+
def association_pretty_name_lookup(association)
207+
case association[:type]
208+
when :one_to_many
209+
if association[:one_to_one]
210+
association[:name].to_s.singularize.gsub('_', ' ').capitalize
211+
else
212+
association[:name].to_s.gsub('_', ' ').capitalize
213+
end
214+
when :many_to_one
215+
association[:name].to_s.gsub('_', ' ').capitalize
216+
else
217+
raise "Unknown association type"
218+
end
219+
end
220+
221+
def association_type_lookup(association)
222+
case association[:type]
223+
when :one_to_many
224+
if association[:one_to_one]
225+
:has_one
226+
else
227+
:has_many
228+
end
229+
when :many_to_one
230+
:belongs_to
231+
else
232+
raise "Unknown association type"
233+
end
234+
end
235+
236+
def association_parent_model_lookup(association)
237+
case association[:type]
238+
when :one_to_many
239+
association[:model]
240+
when :many_to_one
241+
Object.const_get(association[:class_name])
242+
else
243+
raise "Unknown association type"
244+
end
245+
end
246+
247+
def association_parent_key_lookup(association)
248+
[:id]
249+
end
250+
251+
def association_child_model_lookup(association)
252+
case association[:type]
253+
when :one_to_many
254+
Object.const_get(association[:class_name])
255+
when :many_to_one
256+
association[:model]
257+
else
258+
raise "Unknown association type"
259+
end
260+
end
261+
262+
def association_child_key_lookup(association)
263+
case association[:type]
264+
when :one_to_many
265+
association[:keys]
266+
when :many_to_one
267+
["#{association[:class_name].snake_case}_id".to_sym]
268+
else
269+
raise "Unknown association type"
270+
end
271+
end
272+
273+
module InstanceMethods
274+
def id
275+
super
276+
end
277+
278+
def save
279+
super
280+
end
281+
282+
def destroy
283+
super
284+
end
285+
286+
def update_attributes(attributes)
287+
# NOTE: Not sure why calling update(attributes) raises
288+
# Argument Error: wrong number of arguments (1 for 0)
289+
# but this seems to work:
290+
set(attributes)
291+
save
292+
end
293+
294+
def errors
295+
super
296+
end
297+
298+
def clear_association(association)
299+
association.clear # FIXME!
300+
end
301+
302+
def reset
303+
super
304+
end
305+
end
306+
307+
end
308+
end
309+
end

0 commit comments

Comments
 (0)