Permalink
Browse files

added Sequel support

  • Loading branch information...
sferik committed Oct 26, 2009
1 parent ccb8ff0 commit 061fa28f652fc9214e9cf480d66870140181edef
View
@@ -24,6 +24,15 @@ def self.all
@models << new(model) if model
end
@models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
+ when :sequel
+ Dir.glob(Merb.dir_for(:model) / Merb.glob_for(:model)).each do |filename|
+ # FIXME: This heuristic for finding Sequel models could be too strict
+ File.read(filename).scan(/^class ([\w\d_\-:]+) < Sequel::Model$/).flatten.each do |m|
+ model = lookup(m.to_s.to_sym)
+ @models << new(model) if model
+ end
+ end
+ @models.sort!{|a, b| a.model.to_s <=> b.model.to_s}
else
raise "MerbAdmin does not support the #{Merb.orm} ORM"
end
@@ -42,6 +51,8 @@ def self.lookup(model_name)
return model if model.superclass == ActiveRecord::Base
when :datamapper
return model if model.include?(DataMapper::Resource)
+ when :sequel
+ return model if model.superclass == Sequel::Model
end
nil
end
@@ -59,6 +70,9 @@ def initialize(model)
when :datamapper
require 'datamapper_support'
self.extend(DatamapperSupport)
+ when :sequel
+ require 'sequel_support'
+ self.extend(SequelSupport)
else
raise "MerbAdmin does not support the #{Merb.orm} ORM"
end
@@ -51,6 +51,27 @@
end
end
+ desc "Copies sample models, copies and runs sample migrations, and loads sample data"
+ task :sequel => ["sequel:copy_sample_models", "sequel:copy_sample_migrations", "sequel:migrate", "load_sample_data"]
+ namespace :sequel do
+ desc "Copies sample models into your app"
+ task :copy_sample_models do
+ copy_models(:sequel)
+ end
+
+ desc "Copies sample migrations into your app"
+ task :copy_sample_migrations do
+ copy_migrations(:sequel)
+ end
+
+ desc "Perform migration using migrations in schema/migrations"
+ task :migrate do
+ require 'sequel/extensions/migration'
+ Rake::Task["sequel:db:migrate"].reenable
+ Rake::Task["sequel:db:migrate"].invoke
+ end
+ end
+
desc "Loads sample data into your app"
task :load_sample_data do
load_data
@@ -63,13 +84,13 @@
def load_data
begin
- require "mlb"
+ require "mlb"
rescue LoadError => e
puts "LoadError: #{e}"
puts "gem install mlb -s http://gemcutter.org"
return
end
-
+
puts "Loading current MLB leagues, divisions, teams, and players"
MLB.teams.each do |mlb_team|
unless league = MerbAdmin::AbstractModel.new("League").first(:conditions => ["name = ?", mlb_team.league])
View
@@ -0,0 +1,309 @@
+require 'sequel'
+require 'sequel/extensions/pagination'
+
+class Sequel::Model
+=begin
+ # Intialize each column to the default value for new model objects
+ def after_initialize
+ super
+ model.columns.each do |x|
+ if !@values.include?(x) && db_schema[x][:allow_null]
+ send("#{x}=", db_schema[x][:ruby_default])
+ end
+ end
+ end
+=end
+
+ # Return an empty array for *_to_many association methods for new model objects
+ def _load_associated_objects(opts)
+ opts.returns_array? && new? ? [] : super
+ end
+end
+
+module MerbAdmin
+ class AbstractModel
+ module SequelSupport
+ def get(id)
+ model.first(:id => id).extend(InstanceMethods)
+ end
+
+ def count(options = {})
+ if options[:conditions] && !options[:conditions].empty?
+ # If options[:conditions] isn't cloned, Sequel eats the first condition!
+ model.where(options[:conditions].clone).count
+ else
+ model.count
+ end
+ end
+
+ def first(options = {})
+ sort = options.delete(:sort) || :id
+ sort_order = options.delete(:sort_reverse) ? :desc : :asc
+
+ if options[:conditions] && !options[:conditions].empty?
+ # If options[:conditions] isn't cloned, Sequel eats the first condition!
+ model.order(sort.to_sym.send(sort_order)).first(options[:conditions].clone).extend(InstanceMethods)
+ else
+ model.order(sort.to_sym.send(sort_order)).first.extend(InstanceMethods)
+ end
+ end
+
+ def all(options = {})
+ offset = options.delete(:offset)
+ limit = options.delete(:limit)
+
+ sort = options.delete(:sort) || :id
+ sort_order = options.delete(:sort_reverse) ? :desc : :asc
+
+ if options[:conditions] && !options[:conditions].empty?
+ # If options[:conditions] isn't cloned, Sequel eats the first condition!
+ model.where(options[:conditions].clone).order(sort.to_sym.send(sort_order))
+ else
+ model.order(sort.to_sym.send(sort_order))
+ end
+ end
+
+ def paginated(options = {})
+ page = options.delete(:page) || 1
+ per_page = options.delete(:per_page) || MerbAdmin[:per_page]
+ page_count = (count(options).to_f / per_page).ceil
+
+ sort = options.delete(:sort) || :id
+ sort_order = options.delete(:sort_reverse) ? :desc : :asc
+
+ if options[:conditions] && !options[:conditions].empty?
+ # If options[:conditions] isn't cloned, Sequel eats the first condition!
+ [page_count, model.paginate(page.to_i, per_page).where(options[:conditions].clone).order(sort.to_sym.send(sort_order))]
+ else
+ [page_count, model.paginate(page.to_i, per_page).order(sort.to_sym.send(sort_order))]
+ end
+ end
+
+ def create(params = {})
+ model.create(params)
+ end
+
+ def new(params = {})
+ model.new(params).extend(InstanceMethods)
+ end
+
+ def destroy_all!
+ model.all.each do |object|
+ object.destroy
+ end
+ end
+
+ def has_many_associations
+ associations.select do |association|
+ association[:type] == :has_many
+ end
+ end
+
+ def has_one_associations
+ associations.select do |association|
+ association[:type] == :has_one
+ end
+ end
+
+ def belongs_to_associations
+ associations.select do |association|
+ association[:type] == :belongs_to
+ end
+ end
+
+ def associations
+ model.all_association_reflections.map do |association|
+ {
+ :name => association_name_lookup(association),
+ :pretty_name => association_pretty_name_lookup(association),
+ :type => association_type_lookup(association),
+ :parent_model => association_parent_model_lookup(association),
+ :parent_key => association_parent_key_lookup(association),
+ :child_model => association_child_model_lookup(association),
+ :child_key => association_child_key_lookup(association),
+ }
+ end
+ end
+
+ def properties
+ model.columns.map do |property|
+ {
+ :name => property,
+ :pretty_name => property.to_s.gsub(/_id$/, "").gsub("_", " ").capitalize,
+ :type => property_type_lookup(property),
+ :length => property_length_lookup(property),
+ :nullable? => model.db_schema[property][:allow_null],
+ :serial? => model.db_schema[property][:primary_key],
+ }
+ end
+ end
+
+ private
+
+ def property_type_lookup(property)
+ case model.db_schema[property][:db_type]
+ when /\A(?:medium|small)?int(?:eger)?(?:\((?:\d+)\))?\z/io
+ :integer
+ when /\Atinyint(?:\((\d+)\))?\z/io
+ :boolean
+ when /\Abigint(?:\((?:\d+)\))?\z/io
+ :integer
+ when /\A(?:real|float|double(?: precision)?)\z/io
+ :float
+ when 'boolean'
+ :boolean
+ when /\A(?:(?:tiny|medium|long|n)?text|clob)\z/io
+ :text
+ when 'date'
+ :date
+ when /\A(?:small)?datetime\z/io
+ :datetime
+ when /\Atimestamp(?: with(?:out)? time zone)?\z/io
+ :datetime
+ when /\Atime(?: with(?:out)? time zone)?\z/io
+ :time
+ when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
+ :string
+ when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
+ :string
+ when /\A(?:small)?money\z/io
+ :big_decimal
+ when /\A(?:decimal|numeric|number)(?:\((\d+)(?:,\s*(\d+))?\))?\z/io
+ :big_decimal
+ when 'year'
+ :integer
+ else
+ :string
+ end
+ end
+
+ def property_length_lookup(property)
+ case model.db_schema[property][:db_type]
+ when /\An?char(?:acter)?(?:\((\d+)\))?\z/io
+ $1 ? $1.to_i : 255
+ when /\A(?:n?varchar|character varying|bpchar|string)(?:\((\d+)\))?\z/io
+ $1 ? $1.to_i : 255
+ else
+ nil
+ end
+ end
+
+ def association_name_lookup(association)
+ case association[:type]
+ when :one_to_many
+ if association[:one_to_one]
+ association[:name].to_s.singularize.to_sym
+ else
+ association[:name]
+ end
+ when :many_to_one
+ association[:name]
+ else
+ raise "Unknown association type"
+ end
+ end
+
+ def association_pretty_name_lookup(association)
+ case association[:type]
+ when :one_to_many
+ if association[:one_to_one]
+ association[:name].to_s.singularize.gsub('_', ' ').capitalize
+ else
+ association[:name].to_s.gsub('_', ' ').capitalize
+ end
+ when :many_to_one
+ association[:name].to_s.gsub('_', ' ').capitalize
+ else
+ raise "Unknown association type"
+ end
+ end
+
+ def association_type_lookup(association)
+ case association[:type]
+ when :one_to_many
+ if association[:one_to_one]
+ :has_one
+ else
+ :has_many
+ end
+ when :many_to_one
+ :belongs_to
+ else
+ raise "Unknown association type"
+ end
+ end
+
+ def association_parent_model_lookup(association)
+ case association[:type]
+ when :one_to_many
+ association[:model]
+ when :many_to_one
+ Object.const_get(association[:class_name])
+ else
+ raise "Unknown association type"
+ end
+ end
+
+ def association_parent_key_lookup(association)
+ [:id]
+ end
+
+ def association_child_model_lookup(association)
+ case association[:type]
+ when :one_to_many
+ Object.const_get(association[:class_name])
+ when :many_to_one
+ association[:model]
+ else
+ raise "Unknown association type"
+ end
+ end
+
+ def association_child_key_lookup(association)
+ case association[:type]
+ when :one_to_many
+ association[:keys]
+ when :many_to_one
+ ["#{association[:class_name].snake_case}_id".to_sym]
+ else
+ raise "Unknown association type"
+ end
+ end
+
+ module InstanceMethods
+ def id
+ super
+ end
+
+ def save
+ super
+ end
+
+ def destroy
+ super
+ end
+
+ def update_attributes(attributes)
+ # NOTE: Not sure why calling update(attributes) raises
+ # Argument Error: wrong number of arguments (1 for 0)
+ # but this seems to work:
+ set(attributes)
+ save
+ end
+
+ def errors
+ super
+ end
+
+ def clear_association(association)
+ association.clear # FIXME!
+ end
+
+ def reset
+ super
+ end
+ end
+
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 061fa28

Please sign in to comment.