Permalink
Browse files

Additional specs. We're now at 100% coverage. Removed examples from s…

…equel core.
  • Loading branch information...
1 parent 18a6a5e commit 65a863f884f7060cf8f5e3aa80bf8f3a52eb6bf7 @ciconia ciconia committed Jan 1, 2008
View
@@ -1,5 +1,9 @@
=== SVN
+* Removed examples from sequel core.
+
+* Additional specs. We're now at 100% coverage.
+
* Refactored hooks code. Hooks are now inheritable, and can be defined by supplying a block or a method name, or by overriding the hook instance method. Hook chains can now be broken by returning false (#111, #112).
=== 0.1 (2007-12-30)
View
@@ -1,30 +0,0 @@
-require 'rubygems'
-require 'sequel/sqlite'
-
-# Let's open an in-memory database
-DB = Sequel.open 'sqlite:/'
-
-# Create a new table
-DB.create_table :items do
- primary_key :id, :integer, :auto_increment => true
- column :name, :text
- column :price, :float
-end
-
-# Create a dataset
-items = DB[:items]
-
-# Populate the table
-items << {:name => 'abc', :price => rand * 100}
-items << {:name => 'def', :price => rand * 100}
-items << {:name => 'ghi', :price => rand * 100}
-
-# Print out the number of records
-puts "Item count: #{items.count}"
-
-# Print out the records
-items.print(:name, :price)
-
-# Print out the average price
-puts "The average price is: #{items.avg(:price)}"
-
@@ -1,23 +0,0 @@
-require 'sequel/sqlite'
-
-DB = Sequel.open 'sqlite:///countries.db'
-countries = DB[:countries]
-
-# select name, region and popuplation
-countries.select(:name, :region, :population).all
-
-# show the name for the countries that have a population of
-# at least 200 million.
-large_populations = countries.filter {population >= 200_000_000}
-large_populations.map(:name)
-
-# Give the name and the per capita GDP for those countries
-# with a population of at least 200 million.
-large_populations.hash_map(:name, :gdp)
-
-# Show the name and population in millions for the countries of Asia
-countries.filter(:region => 'Asia').select(:name, 'population/1000000').all
-
-# Show the name and population for France, Germany, Italy
-countries.filter(:name => ['France', 'Germany', 'Italy']).hash_map(:name, :population)
-
View
@@ -1,16 +0,0 @@
-require 'rubygems'
-require 'faster_csv'
-require File.join(File.dirname(__FILE__), '../lib/sequel/sqlite')
-
-DB = Sequel.open 'sqlite:///test.db'
-DB.create_table :countries do
- column :name, :text
- column :population, :integer
-end unless DB.table_exists?(:countries)
-
-FCSV.foreach('/home/sharon/reality/server/trunk/test.csv',
- :headers => true, :header_converters => :symbol) do |l|
- DB[:countries] << l.to_hash
-end
-
-DB[:countries].print(:name, :population)
View
@@ -1,30 +0,0 @@
-require 'rubygems'
-require 'sequel/sqlite' # gem install sequel (and sqlite3 as well)
-
-DB = Sequel.open 'sqlite:/' # memory DB
-
-DB.create_table :items do
- text :name
- decimal :price
-end
-
-items = DB[:items]
-
-1000.times {|i| items << {:name => "item#{i}", :price => rand * 100}}
-
-puts "#{items.count} total items"
-
-puts "Average price: #{items.avg(:price)}"
-
-puts "3 most expensive items:"
-items.order(:price.DESC).limit(3).print(:name, :price)
-
-puts "#{items.filter {price < items.avg(:price)}.count} below the average"
-#{}
-
-puts "Changing price for expensive items"
-items.filter {price > items.avg(:price)}.update(:price => 'price + 10'.expr)
-
-puts "Highest price: #{items.max(:price)}"
-
-puts "Updated average price: #{items.avg(:price)}"
View
@@ -1,40 +0,0 @@
-require 'rubygems'
-require File.join(File.dirname(__FILE__), '../lib/sequel/sqlite')
-
-db = Sequel.open("sqlite:/:memory:")
-db << "create table k1 (id integer primary key autoincrement, f1 text)"
-db << "create table k2 (id integer primary key autoincrement, f2 text)"
-db << "create table k3 (id integer primary key autoincrement, f3 text)"
-db << "create table records (id integer primary key autoincrement,
- k1_id integer, k2_id integer, k3_id integer, value text)"
-db << "create unique index records_key_unique on records(k1_id,k2_id,k3_id)"
-db << "create view data as select records.id as id, k1.f1 as f1, k2.f2 as f2,
- k3.f3 as f3, records.value as value
- from records inner join k1 on records.k1_id = k1.id
- inner join k2 on records.k2_id = k2.id
- inner join k3 on records.k3_id = k3.id
- order by k1.f1, k2.f2, k3.f3"
-k1 = db[:k1]
-k1 << [1, 'Alfred']
-k1 << [2,'Barry']
-k1 << [3, 'Charles']
-k1 << [4,'Dave']
-k1 << [5,'Douglas']
-k2 = db[:k2]
-k2 << [1,'USA']
-k2 << [2,'Japan']
-k2 << [3,'Brazil']
-k3 = db[:k3]
-k3 << [1,'APL']
-k3 << [2,'BASIC']
-k3 << [3,'COBOL']
-k3 << [4,'Ruby']
-records = db[:records]
-records << [1,1,1,1,'Red']
-records << [2,2,2,2,'Yellow']
-records << [3,3,3,3,'Green']
-records << [4,4,1,4,'Magenta']
-records << [5,5,2,4,'Blue']
-data = db[:data].filter(:f1 => ['Dave','Douglas'])
-puts data.sql
-data.print(:id, :f1, :f2, :f3, :value)
@@ -19,8 +19,8 @@ def self.database_opened(db)
# Returns the dataset associated with the Model class.
def self.dataset
- @dataset || super_dataset or
- raise Error, "No dataset associated with #{self}"
+ (@dataset ||= super_dataset) ||
+ (raise Error, "No dataset associated with #{self}")
end
def self.super_dataset # :nodoc:
@@ -12,37 +12,29 @@ class Model
:after_destroy
]
- def self.def_hook_method(m) #:nodoc:
- # write hook def
- hook_def = "
- def self.#{m}(method = nil, &block)
- unless block
- (raise SequelError, 'No hook method specified') unless method
- block = proc {send method}
- end
- add_hook(#{m.inspect}, &block)
+ # Some fancy code generation here in order to define the hook class methods...
+ HOOK_METHOD_STR = %Q{
+ def self.%s(method = nil, &block)
+ unless block
+ (raise SequelError, 'No hook method specified') unless method
+ block = proc {send method}
end
- "
-
- instance_eval(hook_def)
+ add_hook(%s, &block)
+ end
+ }
+
+ def self.def_hook_method(m) #:nodoc:
+ instance_eval(HOOK_METHOD_STR % [m.to_s, m.inspect])
end
HOOKS.each {|h| define_method(h) {}}
HOOKS.each {|h| def_hook_method(h)}
# Returns the hooks hash for the model class.
- def self.hooks
+ def self.hooks #:nodoc:
@hooks ||= Hash.new {|h, k| h[k] = []}
end
- # Returns true if the model class or any of its ancestors have defined
- # hooks for the given hook key. Notice that this method cannot detect
- # hooks defined using overridden methods.
- def self.has_hooks?(key)
- has = hooks[key] && !hooks[key].empty?
- has || ((self != Model) && superclass.has_hooks?(key))
- end
-
def self.add_hook(hook, &block) #:nodoc:
chain = hooks[hook]
chain << block
@@ -51,5 +43,13 @@ def self.add_hook(hook, &block) #:nodoc:
chain.each {|h| break false if instance_eval(&h) == false}
end
end
+
+ # Returns true if the model class or any of its ancestors have defined
+ # hooks for the given hook key. Notice that this method cannot detect
+ # hooks defined using overridden methods.
+ def self.has_hooks?(key)
+ has = hooks[key] && !hooks[key].empty?
+ has || ((self != Model) && superclass.has_hooks?(key))
+ end
end
end
@@ -19,6 +19,9 @@ def is(plugin, *args)
metaclass.send(:include, m::ClassMethods)
end
if m.const_defined?("DatasetMethods")
+ unless @dataset
+ raise Sequel::Error, "Plugin cannot be applied because the model class has no dataset"
+ end
dataset.meta_def(:"#{plugin}_opts") {args.first}
dataset.metaclass.send(:include, m::DatasetMethods)
end
@@ -5,7 +5,9 @@ class Model
# This is only needed if you want to use the create_table or drop_table
# methods.
def self.set_schema(name = nil, &block)
- name ? set_dataset(db[name]) : name = table_name
+ if name
+ set_dataset(db[name])
+ end
@schema = Schema::Generator.new(db, &block)
if @schema.primary_key_name
set_primary_key @schema.primary_key_name
View
@@ -244,3 +244,26 @@ def delete
]
end
end
+
+describe "Model#has_hooks?" do
+ setup do
+ @c = Class.new(Sequel::Model)
+ end
+
+ specify "should return false if no hooks are defined" do
+ @c.has_hooks?(:before_save).should be_false
+ end
+
+ specify "should return true if hooks are defined" do
+ @c.before_save {'blah'}
+ @c.has_hooks?(:before_save).should be_true
+ end
+
+ specify "should return true if hooks are inherited" do
+ @d = Class.new(@c)
+ @d.has_hooks?(:before_save).should be_false
+
+ @c.before_save :blah
+ @d.has_hooks?(:before_save).should be_true
+ end
+end
View
@@ -6,6 +6,8 @@ module Timestamped
def self.apply(m, opts)
m.class_def(:get_stamp) {@values[:stamp]}
m.meta_def(:stamp_opts) {opts}
+ puts "opts: #{opts.inspect}"
+ puts "stamp_opts: #{m.stamp_opts.inspect}"
m.before_save {@values[:stamp] = Time.now}
end
@@ -17,10 +19,9 @@ module ClassMethods
def deff; timestamped_opts; end
end
- # ??
- # module DatasetMethods
- # def ghi; timestamped_opts; end
- # end
+ module DatasetMethods
+ def ghi; timestamped_opts; end
+ end
end
end
@@ -39,13 +40,15 @@ def deff; timestamped_opts; end
c = nil
proc do
c = Class.new(Sequel::Model) do
+ set_dataset MODEL_DB[:items]
is :timestamped, :a => 1, :b => 2
end
end.should_not raise_error(LoadError)
c.should respond_to(:stamp_opts)
c.stamp_opts.should == {:a => 1, :b => 2}
+ # instance methods
m = c.new
m.should respond_to(:get_stamp)
m.should respond_to(:abc)
@@ -54,8 +57,20 @@ def deff; timestamped_opts; end
m[:stamp] = t
m.get_stamp.should == t
+ # class methods
c.should respond_to(:deff)
c.deff.should == {:a => 1, :b => 2}
+
+ # dataset methods
+ c.dataset.should respond_to(:ghi)
+ c.dataset.ghi.should == {:a => 1, :b => 2}
end
+ it "should fail to apply if the plugin has DatasetMethod and the model has no datset" do
+ proc do
+ Class.new(Sequel::Model) do
+ is :timestamped, :a => 1, :b => 2
+ end
+ end.should raise_error(Sequel::Error)
+ end
end
Oops, something went wrong.

0 comments on commit 65a863f

Please sign in to comment.