sequel 1.5.1 → 2.0.0
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/CHANGELOG +30 -0
 - data/README +12 -15
 - data/Rakefile +9 -20
 - data/lib/sequel_model.rb +47 -72
 - data/lib/sequel_model/association_reflection.rb +59 -0
 - data/lib/sequel_model/associations.rb +99 -94
 - data/lib/sequel_model/base.rb +308 -102
 - data/lib/sequel_model/caching.rb +72 -27
 - data/lib/sequel_model/eager_loading.rb +308 -300
 - data/lib/sequel_model/hooks.rb +51 -49
 - data/lib/sequel_model/inflector.rb +186 -182
 - data/lib/sequel_model/plugins.rb +54 -40
 - data/lib/sequel_model/record.rb +185 -220
 - data/lib/sequel_model/schema.rb +27 -34
 - data/lib/sequel_model/validations.rb +54 -73
 - data/spec/association_reflection_spec.rb +85 -0
 - data/spec/associations_spec.rb +160 -73
 - data/spec/base_spec.rb +3 -3
 - data/spec/eager_loading_spec.rb +132 -35
 - data/spec/hooks_spec.rb +120 -20
 - data/spec/inflector_spec.rb +2 -2
 - data/spec/model_spec.rb +110 -78
 - data/spec/plugins_spec.rb +4 -0
 - data/spec/rcov.opts +1 -1
 - data/spec/record_spec.rb +160 -59
 - data/spec/spec.opts +0 -5
 - data/spec/spec_helper.rb +12 -0
 - data/spec/validations_spec.rb +23 -0
 - metadata +60 -50
 - data/lib/sequel_model/deprecated.rb +0 -81
 - data/lib/sequel_model/inflections.rb +0 -112
 - data/spec/deprecated_relations_spec.rb +0 -113
 
    
        data/spec/base_spec.rb
    CHANGED
    
    | 
         @@ -240,10 +240,10 @@ end 
     | 
|
| 
       240 
240 
     | 
    
         | 
| 
       241 
241 
     | 
    
         
             
            describe "Model.db=" do
         
     | 
| 
       242 
242 
     | 
    
         
             
              setup do
         
     | 
| 
       243 
     | 
    
         
            -
                $db1 =  
     | 
| 
       244 
     | 
    
         
            -
                $db2 =  
     | 
| 
      
 243 
     | 
    
         
            +
                $db1 = MockDatabase.new
         
     | 
| 
      
 244 
     | 
    
         
            +
                $db2 = MockDatabase.new
         
     | 
| 
       245 
245 
     | 
    
         | 
| 
       246 
     | 
    
         
            -
                class BlueBlue < Sequel::Model
         
     | 
| 
      
 246 
     | 
    
         
            +
                class BlueBlue < Sequel::Model(:items)
         
     | 
| 
       247 
247 
     | 
    
         
             
                  set_dataset $db1[:blue]
         
     | 
| 
       248 
248 
     | 
    
         
             
                end
         
     | 
| 
       249 
249 
     | 
    
         
             
              end
         
     | 
    
        data/spec/eager_loading_spec.rb
    CHANGED
    
    | 
         @@ -9,12 +9,25 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       9 
9 
     | 
    
         
             
                  many_to_one :band, :class=>'EagerBand', :key=>:band_id
         
     | 
| 
       10 
10 
     | 
    
         
             
                  one_to_many :tracks, :class=>'EagerTrack', :key=>:album_id
         
     | 
| 
       11 
11 
     | 
    
         
             
                  many_to_many :genres, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag
         
     | 
| 
      
 12 
     | 
    
         
            +
                  one_to_many :good_tracks, :class=>'EagerTrack', :key=>:album_id do |ds|
         
     | 
| 
      
 13 
     | 
    
         
            +
                    ds.filter(:name=>'Good')
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
                  many_to_one :band_name, :class=>'EagerBand', :key=>:band_id, :select=>[:id, :name]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  one_to_many :track_names, :class=>'EagerTrack', :key=>:album_id, :select=>[:id, :name]
         
     | 
| 
      
 17 
     | 
    
         
            +
                  many_to_many :genre_names, :class=>'EagerGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :select=>[:id]
         
     | 
| 
       12 
18 
     | 
    
         
             
                end
         
     | 
| 
       13 
19 
     | 
    
         | 
| 
       14 
20 
     | 
    
         
             
                class EagerBand < Sequel::Model(:bands)
         
     | 
| 
       15 
21 
     | 
    
         
             
                  columns :id
         
     | 
| 
       16 
22 
     | 
    
         
             
                  one_to_many :albums, :class=>'EagerAlbum', :key=>:band_id, :eager=>:tracks
         
     | 
| 
       17 
23 
     | 
    
         
             
                  many_to_many :members, :class=>'EagerBandMember', :left_key=>:band_id, :right_key=>:member_id, :join_table=>:bm
         
     | 
| 
      
 24 
     | 
    
         
            +
                  one_to_many :good_albums, :class=>'EagerAlbum', :key=>:band_id, :eager_block=>proc{|ds| ds.filter(:name=>'good')} do |ds|
         
     | 
| 
      
 25 
     | 
    
         
            +
                    ds.filter(:name=>'Good')
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  one_to_many :self_titled_albums, :class=>'EagerAlbum', :key=>:band_id, :allow_eager=>false do |ds|
         
     | 
| 
      
 28 
     | 
    
         
            +
                    ds.filter(:name=>name)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  one_to_many :albums_by_name, :class=>'EagerAlbum', :key=>:band_id, :order=>:name, :allow_eager=>false
         
     | 
| 
       18 
31 
     | 
    
         
             
                end
         
     | 
| 
       19 
32 
     | 
    
         | 
| 
       20 
33 
     | 
    
         
             
                class EagerTrack < Sequel::Model(:tracks)
         
     | 
| 
         @@ -34,7 +47,11 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       34 
47 
     | 
    
         | 
| 
       35 
48 
     | 
    
         
             
                EagerAlbum.dataset.extend(Module.new {
         
     | 
| 
       36 
49 
     | 
    
         
             
                  def fetch_rows(sql)
         
     | 
| 
       37 
     | 
    
         
            -
                    h =  
     | 
| 
      
 50 
     | 
    
         
            +
                    h = if sql =~ /101/
         
     | 
| 
      
 51 
     | 
    
         
            +
                      {:id => 101, :band_id=> 101}
         
     | 
| 
      
 52 
     | 
    
         
            +
                    else
         
     | 
| 
      
 53 
     | 
    
         
            +
                      {:id => 1, :band_id=> 2}
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
       38 
55 
     | 
    
         
             
                    h.merge!(:x_foreign_key_x=>4) if sql =~ /ag\.genre_id/
         
     | 
| 
       39 
56 
     | 
    
         
             
                    @db << sql
         
     | 
| 
       40 
57 
     | 
    
         
             
                    yield h
         
     | 
| 
         @@ -46,7 +63,14 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       46 
63 
     | 
    
         
             
                    h = {:id => 2}
         
     | 
| 
       47 
64 
     | 
    
         
             
                    h.merge!(:x_foreign_key_x=>5) if sql =~ /bm\.member_id/
         
     | 
| 
       48 
65 
     | 
    
         
             
                    @db << sql
         
     | 
| 
       49 
     | 
    
         
            -
                     
     | 
| 
      
 66 
     | 
    
         
            +
                    case sql
         
     | 
| 
      
 67 
     | 
    
         
            +
                    when /id IN (101)/
         
     | 
| 
      
 68 
     | 
    
         
            +
                    when /id > 100/
         
     | 
| 
      
 69 
     | 
    
         
            +
                      yield({:id => 101})
         
     | 
| 
      
 70 
     | 
    
         
            +
                      yield({:id => 102})
         
     | 
| 
      
 71 
     | 
    
         
            +
                    else
         
     | 
| 
      
 72 
     | 
    
         
            +
                      yield h
         
     | 
| 
      
 73 
     | 
    
         
            +
                    end
         
     | 
| 
       50 
74 
     | 
    
         
             
                  end
         
     | 
| 
       51 
75 
     | 
    
         
             
                })
         
     | 
| 
       52 
76 
     | 
    
         | 
| 
         @@ -82,7 +106,7 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       82 
106 
     | 
    
         
             
                a.size.should == 1
         
     | 
| 
       83 
107 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
       84 
108 
     | 
    
         
             
                a.first.values.should == {:id => 1, :band_id => 2}
         
     | 
| 
       85 
     | 
    
         
            -
                MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT  
     | 
| 
      
 109 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT bands.* FROM bands WHERE (id IN (2))']
         
     | 
| 
       86 
110 
     | 
    
         
             
                a = a.first
         
     | 
| 
       87 
111 
     | 
    
         
             
                a.band.should be_a_kind_of(EagerBand)
         
     | 
| 
       88 
112 
     | 
    
         
             
                a.band.values.should == {:id => 2}
         
     | 
| 
         @@ -95,7 +119,7 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       95 
119 
     | 
    
         
             
                a.size.should == 1
         
     | 
| 
       96 
120 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
       97 
121 
     | 
    
         
             
                a.first.values.should == {:id => 1, :band_id => 2}
         
     | 
| 
       98 
     | 
    
         
            -
                MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT  
     | 
| 
      
 122 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT tracks.* FROM tracks WHERE (album_id IN (1))']
         
     | 
| 
       99 
123 
     | 
    
         
             
                a = a.first
         
     | 
| 
       100 
124 
     | 
    
         
             
                a.tracks.should be_a_kind_of(Array)
         
     | 
| 
       101 
125 
     | 
    
         
             
                a.tracks.size.should == 1
         
     | 
| 
         @@ -110,11 +134,7 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       110 
134 
     | 
    
         
             
                a.size.should == 1
         
     | 
| 
       111 
135 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
       112 
136 
     | 
    
         
             
                a.first.values.should == {:id => 1, :band_id => 2}
         
     | 
| 
       113 
     | 
    
         
            -
                MODEL_DB.sqls. 
     | 
| 
       114 
     | 
    
         
            -
                MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
         
     | 
| 
       115 
     | 
    
         
            -
                ["SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) AND (ag.album_id IN (1))",
         
     | 
| 
       116 
     | 
    
         
            -
                 "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.album_id IN (1)) AND (ag.genre_id = genres.id)"
         
     | 
| 
       117 
     | 
    
         
            -
                ].should(include(MODEL_DB.sqls[1]))
         
     | 
| 
      
 137 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
         
     | 
| 
       118 
138 
     | 
    
         
             
                a = a.first
         
     | 
| 
       119 
139 
     | 
    
         
             
                a.genres.should be_a_kind_of(Array)
         
     | 
| 
       120 
140 
     | 
    
         
             
                a.genres.size.should == 1
         
     | 
| 
         @@ -131,12 +151,9 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       131 
151 
     | 
    
         
             
                a.first.values.should == {:id => 1, :band_id => 2}
         
     | 
| 
       132 
152 
     | 
    
         
             
                MODEL_DB.sqls.length.should == 4
         
     | 
| 
       133 
153 
     | 
    
         
             
                MODEL_DB.sqls[0].should == 'SELECT * FROM albums'
         
     | 
| 
       134 
     | 
    
         
            -
                MODEL_DB.sqls[1..-1].should(include('SELECT  
     | 
| 
       135 
     | 
    
         
            -
                MODEL_DB.sqls[1..-1].should(include('SELECT  
     | 
| 
       136 
     | 
    
         
            -
                 
     | 
| 
       137 
     | 
    
         
            -
                ["SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.genre_id = genres.id) AND (ag.album_id IN (1))",
         
     | 
| 
       138 
     | 
    
         
            -
                 "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.album_id IN (1)) AND (ag.genre_id = genres.id)"
         
     | 
| 
       139 
     | 
    
         
            -
                ].should(include(sqls[0]))
         
     | 
| 
      
 154 
     | 
    
         
            +
                MODEL_DB.sqls[1..-1].should(include('SELECT bands.* FROM bands WHERE (id IN (2))'))
         
     | 
| 
      
 155 
     | 
    
         
            +
                MODEL_DB.sqls[1..-1].should(include('SELECT tracks.* FROM tracks WHERE (album_id IN (1))'))
         
     | 
| 
      
 156 
     | 
    
         
            +
                MODEL_DB.sqls[1..-1].should(include('SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))'))
         
     | 
| 
       140 
157 
     | 
    
         
             
                a = a.first
         
     | 
| 
       141 
158 
     | 
    
         
             
                a.band.should be_a_kind_of(EagerBand)
         
     | 
| 
       142 
159 
     | 
    
         
             
                a.band.values.should == {:id => 2}
         
     | 
| 
         @@ -158,12 +175,10 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       158 
175 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerTrack)
         
     | 
| 
       159 
176 
     | 
    
         
             
                a.first.values.should == {:id => 3, :album_id => 1}
         
     | 
| 
       160 
177 
     | 
    
         
             
                MODEL_DB.sqls.length.should == 4
         
     | 
| 
       161 
     | 
    
         
            -
                MODEL_DB.sqls 
     | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
                 "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON (bm.band_id IN (2)) AND (bm.member_id = members.id)"
         
     | 
| 
       166 
     | 
    
         
            -
                ].should(include(MODEL_DB.sqls[-1]))
         
     | 
| 
      
 178 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM tracks', 
         
     | 
| 
      
 179 
     | 
    
         
            +
                  'SELECT albums.* FROM albums WHERE (id IN (1))',
         
     | 
| 
      
 180 
     | 
    
         
            +
                  'SELECT bands.* FROM bands WHERE (id IN (2))',
         
     | 
| 
      
 181 
     | 
    
         
            +
                  "SELECT members.*, bm.band_id AS x_foreign_key_x FROM members INNER JOIN bm ON ((bm.member_id = members.id) AND (bm.band_id IN (2)))"]
         
     | 
| 
       167 
182 
     | 
    
         
             
                a = a.first
         
     | 
| 
       168 
183 
     | 
    
         
             
                a.album.should be_a_kind_of(EagerAlbum)
         
     | 
| 
       169 
184 
     | 
    
         
             
                a.album.values.should == {:id => 1, :band_id => 2}
         
     | 
| 
         @@ -183,8 +198,8 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       183 
198 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerBand)
         
     | 
| 
       184 
199 
     | 
    
         
             
                a.first.values.should == {:id => 2}
         
     | 
| 
       185 
200 
     | 
    
         
             
                MODEL_DB.sqls.should == ['SELECT * FROM bands', 
         
     | 
| 
       186 
     | 
    
         
            -
                                         'SELECT  
     | 
| 
       187 
     | 
    
         
            -
                                         'SELECT  
     | 
| 
      
 201 
     | 
    
         
            +
                                         'SELECT albums.* FROM albums WHERE (band_id IN (2))',
         
     | 
| 
      
 202 
     | 
    
         
            +
                                         'SELECT tracks.* FROM tracks WHERE (album_id IN (1))']
         
     | 
| 
       188 
203 
     | 
    
         
             
                a = a.first
         
     | 
| 
       189 
204 
     | 
    
         
             
                a.albums.should be_a_kind_of(Array)
         
     | 
| 
       190 
205 
     | 
    
         
             
                a.albums.size.should == 1
         
     | 
| 
         @@ -208,8 +223,8 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       208 
223 
     | 
    
         
             
                a = a.first
         
     | 
| 
       209 
224 
     | 
    
         
             
                a.albums
         
     | 
| 
       210 
225 
     | 
    
         
             
                MODEL_DB.sqls.should == ['SELECT * FROM bands', 
         
     | 
| 
       211 
     | 
    
         
            -
                                         'SELECT  
     | 
| 
       212 
     | 
    
         
            -
                                         'SELECT  
     | 
| 
      
 226 
     | 
    
         
            +
                                         'SELECT albums.* FROM albums WHERE (band_id = 2)',
         
     | 
| 
      
 227 
     | 
    
         
            +
                                         'SELECT tracks.* FROM tracks WHERE (album_id IN (1))']
         
     | 
| 
       213 
228 
     | 
    
         
             
                a.albums.should be_a_kind_of(Array)
         
     | 
| 
       214 
229 
     | 
    
         
             
                a.albums.size.should == 1
         
     | 
| 
       215 
230 
     | 
    
         
             
                a.albums.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
         @@ -228,11 +243,7 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       228 
243 
     | 
    
         
             
                a.size.should == 1
         
     | 
| 
       229 
244 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerBandMember)
         
     | 
| 
       230 
245 
     | 
    
         
             
                a.first.values.should == {:id => 5}
         
     | 
| 
       231 
     | 
    
         
            -
                MODEL_DB.sqls. 
     | 
| 
       232 
     | 
    
         
            -
                MODEL_DB.sqls[0].should == 'SELECT * FROM members'
         
     | 
| 
       233 
     | 
    
         
            -
                ['SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.band_id = bands.id) AND (bm.member_id IN (5)) ORDER BY id',
         
     | 
| 
       234 
     | 
    
         
            -
                 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON (bm.member_id IN (5)) AND (bm.band_id = bands.id) ORDER BY id'
         
     | 
| 
       235 
     | 
    
         
            -
                ].should(include(MODEL_DB.sqls[1]))
         
     | 
| 
      
 246 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM members', 'SELECT bands.*, bm.member_id AS x_foreign_key_x FROM bands INNER JOIN bm ON ((bm.band_id = bands.id) AND (bm.member_id IN (5))) ORDER BY id']
         
     | 
| 
       236 
247 
     | 
    
         
             
                a = a.first
         
     | 
| 
       237 
248 
     | 
    
         
             
                a.bands.should be_a_kind_of(Array)
         
     | 
| 
       238 
249 
     | 
    
         
             
                a.bands.size.should == 1
         
     | 
| 
         @@ -247,7 +258,7 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       247 
258 
     | 
    
         
             
                a.size.should == 1
         
     | 
| 
       248 
259 
     | 
    
         
             
                a.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
       249 
260 
     | 
    
         
             
                a.first.values.should == {:id => 1, :band_id => 2}
         
     | 
| 
       250 
     | 
    
         
            -
                MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT  
     | 
| 
      
 261 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', 'SELECT tracks.* FROM tracks WHERE (album_id IN (1))']
         
     | 
| 
       251 
262 
     | 
    
         
             
                a = a.first
         
     | 
| 
       252 
263 
     | 
    
         
             
                a.tracks.should be_a_kind_of(Array)
         
     | 
| 
       253 
264 
     | 
    
         
             
                a.tracks.size.should == 1
         
     | 
| 
         @@ -257,6 +268,64 @@ describe Sequel::Model, "#eager" do 
     | 
|
| 
       257 
268 
     | 
    
         
             
                a.tracks.first.album.should == a
         
     | 
| 
       258 
269 
     | 
    
         
             
                MODEL_DB.sqls.length.should == 2
         
     | 
| 
       259 
270 
     | 
    
         
             
              end
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
              it "should cache the negative lookup when eagerly loading a many_to_one association" do
         
     | 
| 
      
 273 
     | 
    
         
            +
                a = EagerAlbum.eager(:band).filter(:id=>101).all
         
     | 
| 
      
 274 
     | 
    
         
            +
                a.should be_a_kind_of(Array)
         
     | 
| 
      
 275 
     | 
    
         
            +
                a.size.should == 1
         
     | 
| 
      
 276 
     | 
    
         
            +
                a.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
      
 277 
     | 
    
         
            +
                a.first.values.should == {:id => 101, :band_id => 101}
         
     | 
| 
      
 278 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums WHERE (id = 101)', 'SELECT bands.* FROM bands WHERE (id IN (101))']
         
     | 
| 
      
 279 
     | 
    
         
            +
                a = a.first
         
     | 
| 
      
 280 
     | 
    
         
            +
                a.instance_variable_get(:@band).should == :null
         
     | 
| 
      
 281 
     | 
    
         
            +
                a.band.should == nil
         
     | 
| 
      
 282 
     | 
    
         
            +
                MODEL_DB.sqls.length.should == 2
         
     | 
| 
      
 283 
     | 
    
         
            +
              end
         
     | 
| 
      
 284 
     | 
    
         
            +
              
         
     | 
| 
      
 285 
     | 
    
         
            +
              it "should cache the negative lookup when eagerly loading a *_to_many associations" do
         
     | 
| 
      
 286 
     | 
    
         
            +
                a = EagerBand.eager(:albums).filter('id > 100').all
         
     | 
| 
      
 287 
     | 
    
         
            +
                a.should be_a_kind_of(Array)
         
     | 
| 
      
 288 
     | 
    
         
            +
                a.size.should == 2
         
     | 
| 
      
 289 
     | 
    
         
            +
                a.first.should be_a_kind_of(EagerBand)
         
     | 
| 
      
 290 
     | 
    
         
            +
                a.first.values.should == {:id => 101}
         
     | 
| 
      
 291 
     | 
    
         
            +
                a.last.values.should == {:id => 102}
         
     | 
| 
      
 292 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM bands WHERE (id > 100)', 'SELECT albums.* FROM albums WHERE (band_id IN (101, 102))', "SELECT tracks.* FROM tracks WHERE (album_id IN (101))"]
         
     | 
| 
      
 293 
     | 
    
         
            +
                a.first.instance_variable_get(:@albums).should be_a_kind_of(Array)
         
     | 
| 
      
 294 
     | 
    
         
            +
                a.first.albums.length.should == 1
         
     | 
| 
      
 295 
     | 
    
         
            +
                a.first.albums.first.should be_a_kind_of(EagerAlbum)
         
     | 
| 
      
 296 
     | 
    
         
            +
                a.last.instance_variable_get(:@albums).should == []
         
     | 
| 
      
 297 
     | 
    
         
            +
                a.last.albums.should == []
         
     | 
| 
      
 298 
     | 
    
         
            +
                MODEL_DB.sqls.length.should == 3
         
     | 
| 
      
 299 
     | 
    
         
            +
              end
         
     | 
| 
      
 300 
     | 
    
         
            +
              
         
     | 
| 
      
 301 
     | 
    
         
            +
              it "should use the association's block when eager loading by default" do
         
     | 
| 
      
 302 
     | 
    
         
            +
                EagerAlbum.eager(:good_tracks).all
         
     | 
| 
      
 303 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT tracks.* FROM tracks WHERE ((album_id IN (1)) AND (name = 'Good'))"]
         
     | 
| 
      
 304 
     | 
    
         
            +
              end
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
              it "should use the eager_block option when eager loading if given" do
         
     | 
| 
      
 307 
     | 
    
         
            +
                EagerBand.eager(:good_albums).all
         
     | 
| 
      
 308 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT albums.* FROM albums WHERE ((band_id IN (2)) AND (name = 'good'))"]
         
     | 
| 
      
 309 
     | 
    
         
            +
                MODEL_DB.sqls.clear
         
     | 
| 
      
 310 
     | 
    
         
            +
                EagerBand.eager(:good_albums=>:good_tracks).all
         
     | 
| 
      
 311 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM bands', "SELECT albums.* FROM albums WHERE ((band_id IN (2)) AND (name = 'good'))", "SELECT tracks.* FROM tracks WHERE ((album_id IN (1)) AND (name = 'Good'))"]
         
     | 
| 
      
 312 
     | 
    
         
            +
              end
         
     | 
| 
      
 313 
     | 
    
         
            +
             
     | 
| 
      
 314 
     | 
    
         
            +
              it "should raise an error when attempting to eagerly load an association with the :allow_eager option set to false" do
         
     | 
| 
      
 315 
     | 
    
         
            +
                proc{EagerBand.eager(:self_titled_albums).all}.should raise_error(Sequel::Error)
         
     | 
| 
      
 316 
     | 
    
         
            +
                proc{EagerBand.eager(:albums_by_name).all}.should raise_error(Sequel::Error)
         
     | 
| 
      
 317 
     | 
    
         
            +
              end
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
              it "should respect the association's :select option" do
         
     | 
| 
      
 320 
     | 
    
         
            +
                EagerAlbum.eager(:band_name).all
         
     | 
| 
      
 321 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM bands WHERE (id IN (2))"]
         
     | 
| 
      
 322 
     | 
    
         
            +
                MODEL_DB.sqls.clear
         
     | 
| 
      
 323 
     | 
    
         
            +
                EagerAlbum.eager(:track_names).all
         
     | 
| 
      
 324 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, name FROM tracks WHERE (album_id IN (1))"]
         
     | 
| 
      
 325 
     | 
    
         
            +
                MODEL_DB.sqls.clear
         
     | 
| 
      
 326 
     | 
    
         
            +
                EagerAlbum.eager(:genre_names).all
         
     | 
| 
      
 327 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT * FROM albums', "SELECT id, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
         
     | 
| 
      
 328 
     | 
    
         
            +
              end
         
     | 
| 
       260 
329 
     | 
    
         
             
            end
         
     | 
| 
       261 
330 
     | 
    
         | 
| 
       262 
331 
     | 
    
         
             
            describe Sequel::Model, "#eager_graph" do
         
     | 
| 
         @@ -540,10 +609,8 @@ describe Sequel::Model, "#eager_graph" do 
     | 
|
| 
       540 
609 
     | 
    
         
             
                a.genres.size.should == 1
         
     | 
| 
       541 
610 
     | 
    
         
             
                a.genres.first.should be_a_kind_of(GraphGenre)
         
     | 
| 
       542 
611 
     | 
    
         
             
                a.genres.first.values.should == {:id=>6}
         
     | 
| 
       543 
     | 
    
         
            -
                MODEL_DB.sqls 
     | 
| 
       544 
     | 
    
         
            -
                 
     | 
| 
       545 
     | 
    
         
            -
                 "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON (ag.album_id IN (1)) AND (ag.genre_id = genres.id)"
         
     | 
| 
       546 
     | 
    
         
            -
                ].should(include(MODEL_DB.sqls[1]))
         
     | 
| 
      
 612 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['SELECT albums.id, albums.band_id, tracks.id AS tracks_id, tracks.album_id FROM albums LEFT OUTER JOIN tracks ON (tracks.album_id = albums.id)',
         
     | 
| 
      
 613 
     | 
    
         
            +
                "SELECT genres.*, ag.album_id AS x_foreign_key_x FROM genres INNER JOIN ag ON ((ag.genre_id = genres.id) AND (ag.album_id IN (1)))"]
         
     | 
| 
       547 
614 
     | 
    
         
             
              end
         
     | 
| 
       548 
615 
     | 
    
         | 
| 
       549 
616 
     | 
    
         
             
              it "should handle no associated records for a single many_to_one association" do
         
     | 
| 
         @@ -645,4 +712,34 @@ describe Sequel::Model, "#eager_graph" do 
     | 
|
| 
       645 
712 
     | 
    
         
             
                a[3].album.band.members.last.should be_a_kind_of(GraphBandMember)
         
     | 
| 
       646 
713 
     | 
    
         
             
                a[3].album.band.members.last.values.should == {:id => 6}
         
     | 
| 
       647 
714 
     | 
    
         
             
              end
         
     | 
| 
      
 715 
     | 
    
         
            +
             
     | 
| 
      
 716 
     | 
    
         
            +
              it "should respect the association's :graph_join_type option" do 
         
     | 
| 
      
 717 
     | 
    
         
            +
                GraphAlbum.many_to_one :inner_band, :class=>'GraphBand', :key=>:band_id, :graph_join_type=>:inner
         
     | 
| 
      
 718 
     | 
    
         
            +
                GraphAlbum.eager_graph(:inner_band).sql.should == 'SELECT albums.id, albums.band_id, inner_band.id AS inner_band_id, inner_band.vocalist_id FROM albums INNER JOIN bands inner_band ON (inner_band.id = albums.band_id)'
         
     | 
| 
      
 719 
     | 
    
         
            +
             
     | 
| 
      
 720 
     | 
    
         
            +
                GraphAlbum.one_to_many :right_tracks, :class=>'GraphTrack', :key=>:album_id, :graph_join_type=>:right_outer
         
     | 
| 
      
 721 
     | 
    
         
            +
                GraphAlbum.eager_graph(:right_tracks).sql.should == 'SELECT albums.id, albums.band_id, right_tracks.id AS right_tracks_id, right_tracks.album_id FROM albums RIGHT OUTER JOIN tracks right_tracks ON (right_tracks.album_id = albums.id)'
         
     | 
| 
      
 722 
     | 
    
         
            +
             
     | 
| 
      
 723 
     | 
    
         
            +
                GraphAlbum.many_to_many :inner_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_join_type=>:inner
         
     | 
| 
      
 724 
     | 
    
         
            +
                GraphAlbum.eager_graph(:inner_genres).sql.should == 'SELECT albums.id, albums.band_id, inner_genres.id AS inner_genres_id FROM albums INNER JOIN ag ON (ag.album_id = albums.id) INNER JOIN genres inner_genres ON (inner_genres.id = ag.genre_id)'
         
     | 
| 
      
 725 
     | 
    
         
            +
              end
         
     | 
| 
      
 726 
     | 
    
         
            +
             
     | 
| 
      
 727 
     | 
    
         
            +
              it "should respect the association's :graph_conditions option" do 
         
     | 
| 
      
 728 
     | 
    
         
            +
                GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_conditions=>{:active=>true}
         
     | 
| 
      
 729 
     | 
    
         
            +
                GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands active_band ON ((active_band.id = albums.band_id) AND (active_band.active = 't'))"
         
     | 
| 
      
 730 
     | 
    
         
            +
             
     | 
| 
      
 731 
     | 
    
         
            +
                GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_conditions=>{true=>:active}
         
     | 
| 
      
 732 
     | 
    
         
            +
                GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON (ag.album_id = albums.id) LEFT OUTER JOIN genres active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
         
     | 
| 
      
 733 
     | 
    
         
            +
             
     | 
| 
      
 734 
     | 
    
         
            +
                GraphAlbum.many_to_one :active_band, :class=>'GraphBand', :key=>:band_id, :graph_conditions=>{:id=>(0..100)}
         
     | 
| 
      
 735 
     | 
    
         
            +
                GraphAlbum.eager_graph(:active_band).sql.should == "SELECT albums.id, albums.band_id, active_band.id AS active_band_id, active_band.vocalist_id FROM albums LEFT OUTER JOIN bands active_band ON ((active_band.id = albums.band_id) AND ((active_band.id >= 0) AND (active_band.id <= 100)))"
         
     | 
| 
      
 736 
     | 
    
         
            +
              end
         
     | 
| 
      
 737 
     | 
    
         
            +
             
     | 
| 
      
 738 
     | 
    
         
            +
              it "should respect the association's :graph_join_table_conditions option" do 
         
     | 
| 
      
 739 
     | 
    
         
            +
                GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_join_table_conditions=>{:active=>true}
         
     | 
| 
      
 740 
     | 
    
         
            +
                GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON ((ag.album_id = albums.id) AND (ag.active = 't')) LEFT OUTER JOIN genres active_genres ON (active_genres.id = ag.genre_id)"
         
     | 
| 
      
 741 
     | 
    
         
            +
             
     | 
| 
      
 742 
     | 
    
         
            +
                GraphAlbum.many_to_many :active_genres, :class=>'GraphGenre', :left_key=>:album_id, :right_key=>:genre_id, :join_table=>:ag, :graph_conditions=>{true=>:active}, :graph_join_table_conditions=>{true=>:active}
         
     | 
| 
      
 743 
     | 
    
         
            +
                GraphAlbum.eager_graph(:active_genres).sql.should == "SELECT albums.id, albums.band_id, active_genres.id AS active_genres_id FROM albums LEFT OUTER JOIN ag ON ((ag.album_id = albums.id) AND ('t' = albums.active)) LEFT OUTER JOIN genres active_genres ON ((active_genres.id = ag.genre_id) AND ('t' = ag.active))"
         
     | 
| 
      
 744 
     | 
    
         
            +
              end
         
     | 
| 
       648 
745 
     | 
    
         
             
            end
         
     | 
    
        data/spec/hooks_spec.rb
    CHANGED
    
    | 
         @@ -3,20 +3,6 @@ require File.join(File.dirname(__FILE__), "spec_helper") 
     | 
|
| 
       3 
3 
     | 
    
         
             
            describe "Model hooks" do
         
     | 
| 
       4 
4 
     | 
    
         
             
              before do
         
     | 
| 
       5 
5 
     | 
    
         
             
                MODEL_DB.reset
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                @hooks = [
         
     | 
| 
       8 
     | 
    
         
            -
                  :after_initialize,
         
     | 
| 
       9 
     | 
    
         
            -
                  :before_create,
         
     | 
| 
       10 
     | 
    
         
            -
                  :after_create,
         
     | 
| 
       11 
     | 
    
         
            -
                  :before_update,
         
     | 
| 
       12 
     | 
    
         
            -
                  :after_update,
         
     | 
| 
       13 
     | 
    
         
            -
                  :before_save,
         
     | 
| 
       14 
     | 
    
         
            -
                  :after_save,
         
     | 
| 
       15 
     | 
    
         
            -
                  :before_destroy,
         
     | 
| 
       16 
     | 
    
         
            -
                  :after_destroy
         
     | 
| 
       17 
     | 
    
         
            -
                ]
         
     | 
| 
       18 
     | 
    
         
            -
                
         
     | 
| 
       19 
     | 
    
         
            -
                # @hooks.each {|h| Sequel::Model.class_def(h) {}}
         
     | 
| 
       20 
6 
     | 
    
         
             
              end
         
     | 
| 
       21 
7 
     | 
    
         | 
| 
       22 
8 
     | 
    
         
             
              specify "should be definable using def <hook name>" do
         
     | 
| 
         @@ -60,6 +46,47 @@ describe "Model hooks" do 
     | 
|
| 
       60 
46 
     | 
    
         
             
                c.new.before_save
         
     | 
| 
       61 
47 
     | 
    
         
             
                $adds.should == ['hyiyie', 'byiyie']
         
     | 
| 
       62 
48 
     | 
    
         
             
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              specify "should not be additive if the method or tag already exists" do
         
     | 
| 
      
 51 
     | 
    
         
            +
                $adds = []
         
     | 
| 
      
 52 
     | 
    
         
            +
                c = Class.new(Sequel::Model) do
         
     | 
| 
      
 53 
     | 
    
         
            +
                  def bye; $adds << 'bye'; end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  before_save :bye
         
     | 
| 
      
 55 
     | 
    
         
            +
                  before_save :bye
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
                
         
     | 
| 
      
 58 
     | 
    
         
            +
                c.new.before_save
         
     | 
| 
      
 59 
     | 
    
         
            +
                $adds.should == ['bye']
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                $adds = []
         
     | 
| 
      
 62 
     | 
    
         
            +
                d = Class.new(Sequel::Model) do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  before_save(:bye){$adds << 'hyiyie'}
         
     | 
| 
      
 64 
     | 
    
         
            +
                  before_save(:bye){$adds << 'byiyie'}
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
                
         
     | 
| 
      
 67 
     | 
    
         
            +
                d.new.before_save
         
     | 
| 
      
 68 
     | 
    
         
            +
                $adds.should == ['byiyie']
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                $adds = []
         
     | 
| 
      
 71 
     | 
    
         
            +
                e = Class.new(Sequel::Model) do
         
     | 
| 
      
 72 
     | 
    
         
            +
                  def bye; $adds << 'bye'; end
         
     | 
| 
      
 73 
     | 
    
         
            +
                  before_save :bye
         
     | 
| 
      
 74 
     | 
    
         
            +
                  before_save(:bye){$adds << 'byiyie'}
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
                
         
     | 
| 
      
 77 
     | 
    
         
            +
                e.new.before_save
         
     | 
| 
      
 78 
     | 
    
         
            +
                $adds.should == ['byiyie']
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                $adds = []
         
     | 
| 
      
 81 
     | 
    
         
            +
                e = Class.new(Sequel::Model) do
         
     | 
| 
      
 82 
     | 
    
         
            +
                  def bye; $adds << 'bye'; end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  before_save(:bye){$adds << 'byiyie'}
         
     | 
| 
      
 84 
     | 
    
         
            +
                  before_save :bye
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
                
         
     | 
| 
      
 87 
     | 
    
         
            +
                e.new.before_save
         
     | 
| 
      
 88 
     | 
    
         
            +
                $adds.should == ['bye']
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
       63 
90 
     | 
    
         | 
| 
       64 
91 
     | 
    
         
             
              specify "should be inheritable" do
         
     | 
| 
       65 
92 
     | 
    
         
             
                # pending
         
     | 
| 
         @@ -155,12 +182,12 @@ describe "Model#before_create && Model#after_create" do 
     | 
|
| 
       155 
182 
     | 
    
         
             
                  columns :x
         
     | 
| 
       156 
183 
     | 
    
         
             
                  no_primary_key
         
     | 
| 
       157 
184 
     | 
    
         | 
| 
       158 
     | 
    
         
            -
                  before_create {MODEL_DB << "BLAH before"}
         
     | 
| 
       159 
185 
     | 
    
         
             
                  after_create {MODEL_DB << "BLAH after"}
         
     | 
| 
       160 
186 
     | 
    
         
             
                end
         
     | 
| 
       161 
187 
     | 
    
         
             
              end
         
     | 
| 
       162 
188 
     | 
    
         | 
| 
       163 
189 
     | 
    
         
             
              specify "should be called around new record creation" do
         
     | 
| 
      
 190 
     | 
    
         
            +
                @c.before_create {MODEL_DB << "BLAH before"}
         
     | 
| 
       164 
191 
     | 
    
         
             
                @c.create(:x => 2)
         
     | 
| 
       165 
192 
     | 
    
         
             
                MODEL_DB.sqls.should == [
         
     | 
| 
       166 
193 
     | 
    
         
             
                  'BLAH before',
         
     | 
| 
         @@ -168,6 +195,12 @@ describe "Model#before_create && Model#after_create" do 
     | 
|
| 
       168 
195 
     | 
    
         
             
                  'BLAH after'
         
     | 
| 
       169 
196 
     | 
    
         
             
                ]
         
     | 
| 
       170 
197 
     | 
    
         
             
              end
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
              specify "should cancel the save if before_create returns false" do
         
     | 
| 
      
 200 
     | 
    
         
            +
                @c.before_create{false}
         
     | 
| 
      
 201 
     | 
    
         
            +
                @c.create(:x => 2).should == false
         
     | 
| 
      
 202 
     | 
    
         
            +
                MODEL_DB.sqls.should == []
         
     | 
| 
      
 203 
     | 
    
         
            +
              end
         
     | 
| 
       171 
204 
     | 
    
         
             
            end
         
     | 
| 
       172 
205 
     | 
    
         | 
| 
       173 
206 
     | 
    
         
             
            describe "Model#before_update && Model#after_update" do
         
     | 
| 
         @@ -175,12 +208,12 @@ describe "Model#before_update && Model#after_update" do 
     | 
|
| 
       175 
208 
     | 
    
         
             
                MODEL_DB.reset
         
     | 
| 
       176 
209 
     | 
    
         | 
| 
       177 
210 
     | 
    
         
             
                @c = Class.new(Sequel::Model(:items)) do
         
     | 
| 
       178 
     | 
    
         
            -
                  before_update {MODEL_DB << "BLAH before"}
         
     | 
| 
       179 
211 
     | 
    
         
             
                  after_update {MODEL_DB << "BLAH after"}
         
     | 
| 
       180 
212 
     | 
    
         
             
                end
         
     | 
| 
       181 
213 
     | 
    
         
             
              end
         
     | 
| 
       182 
214 
     | 
    
         | 
| 
       183 
215 
     | 
    
         
             
              specify "should be called around record update" do
         
     | 
| 
      
 216 
     | 
    
         
            +
                @c.before_update {MODEL_DB << "BLAH before"}
         
     | 
| 
       184 
217 
     | 
    
         
             
                m = @c.load(:id => 2233)
         
     | 
| 
       185 
218 
     | 
    
         
             
                m.save
         
     | 
| 
       186 
219 
     | 
    
         
             
                MODEL_DB.sqls.should == [
         
     | 
| 
         @@ -189,6 +222,12 @@ describe "Model#before_update && Model#after_update" do 
     | 
|
| 
       189 
222 
     | 
    
         
             
                  'BLAH after'
         
     | 
| 
       190 
223 
     | 
    
         
             
                ]
         
     | 
| 
       191 
224 
     | 
    
         
             
              end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
      
 226 
     | 
    
         
            +
              specify "should cancel the save if before_update returns false" do
         
     | 
| 
      
 227 
     | 
    
         
            +
                @c.before_update{false}
         
     | 
| 
      
 228 
     | 
    
         
            +
                @c.load(:id => 2233).save.should == false
         
     | 
| 
      
 229 
     | 
    
         
            +
                MODEL_DB.sqls.should == []
         
     | 
| 
      
 230 
     | 
    
         
            +
              end
         
     | 
| 
       192 
231 
     | 
    
         
             
            end
         
     | 
| 
       193 
232 
     | 
    
         | 
| 
       194 
233 
     | 
    
         
             
            describe "Model#before_save && Model#after_save" do
         
     | 
| 
         @@ -221,6 +260,12 @@ describe "Model#before_save && Model#after_save" do 
     | 
|
| 
       221 
260 
     | 
    
         
             
                  'BLAH after'
         
     | 
| 
       222 
261 
     | 
    
         
             
                ]
         
     | 
| 
       223 
262 
     | 
    
         
             
              end
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
              specify "should cancel the save if before_save returns false" do
         
     | 
| 
      
 265 
     | 
    
         
            +
                @c.before_save{false}
         
     | 
| 
      
 266 
     | 
    
         
            +
                @c.load(:id => 2233).save.should == false
         
     | 
| 
      
 267 
     | 
    
         
            +
                MODEL_DB.sqls.should == ["BLAH before"]
         
     | 
| 
      
 268 
     | 
    
         
            +
              end
         
     | 
| 
       224 
269 
     | 
    
         
             
            end
         
     | 
| 
       225 
270 
     | 
    
         | 
| 
       226 
271 
     | 
    
         
             
            describe "Model#before_destroy && Model#after_destroy" do
         
     | 
| 
         @@ -228,7 +273,6 @@ describe "Model#before_destroy && Model#after_destroy" do 
     | 
|
| 
       228 
273 
     | 
    
         
             
                MODEL_DB.reset
         
     | 
| 
       229 
274 
     | 
    
         | 
| 
       230 
275 
     | 
    
         
             
                @c = Class.new(Sequel::Model(:items)) do
         
     | 
| 
       231 
     | 
    
         
            -
                  before_destroy {MODEL_DB << "BLAH before"}
         
     | 
| 
       232 
276 
     | 
    
         
             
                  after_destroy {MODEL_DB << "BLAH after"}
         
     | 
| 
       233 
277 
     | 
    
         | 
| 
       234 
278 
     | 
    
         
             
                  def delete
         
     | 
| 
         @@ -237,7 +281,8 @@ describe "Model#before_destroy && Model#after_destroy" do 
     | 
|
| 
       237 
281 
     | 
    
         
             
                end
         
     | 
| 
       238 
282 
     | 
    
         
             
              end
         
     | 
| 
       239 
283 
     | 
    
         | 
| 
       240 
     | 
    
         
            -
              specify "should be called around record  
     | 
| 
      
 284 
     | 
    
         
            +
              specify "should be called around record destruction" do
         
     | 
| 
      
 285 
     | 
    
         
            +
                @c.before_destroy {MODEL_DB << "BLAH before"}
         
     | 
| 
       241 
286 
     | 
    
         
             
                m = @c.new(:id => 2233)
         
     | 
| 
       242 
287 
     | 
    
         
             
                m.destroy
         
     | 
| 
       243 
288 
     | 
    
         
             
                MODEL_DB.sqls.should == [
         
     | 
| 
         @@ -246,11 +291,66 @@ describe "Model#before_destroy && Model#after_destroy" do 
     | 
|
| 
       246 
291 
     | 
    
         
             
                  'BLAH after'
         
     | 
| 
       247 
292 
     | 
    
         
             
                ]
         
     | 
| 
       248 
293 
     | 
    
         
             
              end
         
     | 
| 
      
 294 
     | 
    
         
            +
             
     | 
| 
      
 295 
     | 
    
         
            +
              specify "should cancel the destroy if before_destroy returns false" do
         
     | 
| 
      
 296 
     | 
    
         
            +
                @c.before_destroy{false}
         
     | 
| 
      
 297 
     | 
    
         
            +
                @c.load(:id => 2233).destroy.should == false
         
     | 
| 
      
 298 
     | 
    
         
            +
                MODEL_DB.sqls.should == []
         
     | 
| 
      
 299 
     | 
    
         
            +
              end
         
     | 
| 
      
 300 
     | 
    
         
            +
            end
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
            describe "Model#before_validation && Model#after_validation" do
         
     | 
| 
      
 303 
     | 
    
         
            +
              setup do
         
     | 
| 
      
 304 
     | 
    
         
            +
                MODEL_DB.reset
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                @c = Class.new(Sequel::Model(:items)) do
         
     | 
| 
      
 307 
     | 
    
         
            +
                  before_validation{MODEL_DB << "BLAH before"}
         
     | 
| 
      
 308 
     | 
    
         
            +
                  after_validation{MODEL_DB << "BLAH after"}
         
     | 
| 
      
 309 
     | 
    
         
            +
             
     | 
| 
      
 310 
     | 
    
         
            +
                  def self.validate(o)
         
     | 
| 
      
 311 
     | 
    
         
            +
                    o.errors[:id] << 'not valid' unless o[:id] == 2233
         
     | 
| 
      
 312 
     | 
    
         
            +
                  end
         
     | 
| 
      
 313 
     | 
    
         
            +
                  
         
     | 
| 
      
 314 
     | 
    
         
            +
                  def save!(*columns)
         
     | 
| 
      
 315 
     | 
    
         
            +
                    MODEL_DB << "CREATE BLAH"
         
     | 
| 
      
 316 
     | 
    
         
            +
                    self
         
     | 
| 
      
 317 
     | 
    
         
            +
                  end
         
     | 
| 
      
 318 
     | 
    
         
            +
                  columns :id
         
     | 
| 
      
 319 
     | 
    
         
            +
                end
         
     | 
| 
      
 320 
     | 
    
         
            +
              end
         
     | 
| 
      
 321 
     | 
    
         
            +
              
         
     | 
| 
      
 322 
     | 
    
         
            +
              specify "should be called around validation" do
         
     | 
| 
      
 323 
     | 
    
         
            +
                m = @c.new(:id => 2233)
         
     | 
| 
      
 324 
     | 
    
         
            +
                m.should be_valid
         
     | 
| 
      
 325 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
         
     | 
| 
      
 326 
     | 
    
         
            +
             
     | 
| 
      
 327 
     | 
    
         
            +
                MODEL_DB.sqls.clear
         
     | 
| 
      
 328 
     | 
    
         
            +
                m = @c.new(:id => 22)
         
     | 
| 
      
 329 
     | 
    
         
            +
                m.should_not be_valid
         
     | 
| 
      
 330 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
         
     | 
| 
      
 331 
     | 
    
         
            +
              end
         
     | 
| 
      
 332 
     | 
    
         
            +
             
     | 
| 
      
 333 
     | 
    
         
            +
              specify "should be called when calling save" do
         
     | 
| 
      
 334 
     | 
    
         
            +
                m = @c.new(:id => 2233)
         
     | 
| 
      
 335 
     | 
    
         
            +
                m.save.should == m
         
     | 
| 
      
 336 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['BLAH before', 'BLAH after', 'CREATE BLAH']
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
                MODEL_DB.sqls.clear
         
     | 
| 
      
 339 
     | 
    
         
            +
                m = @c.new(:id => 22)
         
     | 
| 
      
 340 
     | 
    
         
            +
                m.save.should == false
         
     | 
| 
      
 341 
     | 
    
         
            +
                MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
         
     | 
| 
      
 342 
     | 
    
         
            +
              end
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
              specify "should cancel the save if before_validation returns false" do
         
     | 
| 
      
 345 
     | 
    
         
            +
                @c.before_validation{false}
         
     | 
| 
      
 346 
     | 
    
         
            +
                @c.load(:id => 2233).save.should == false
         
     | 
| 
      
 347 
     | 
    
         
            +
                MODEL_DB.sqls.should == ["BLAH before"]
         
     | 
| 
      
 348 
     | 
    
         
            +
              end
         
     | 
| 
       249 
349 
     | 
    
         
             
            end
         
     | 
| 
       250 
350 
     | 
    
         | 
| 
       251 
     | 
    
         
            -
            describe "Model 
     | 
| 
      
 351 
     | 
    
         
            +
            describe "Model.has_hooks?" do
         
     | 
| 
       252 
352 
     | 
    
         
             
              setup do
         
     | 
| 
       253 
     | 
    
         
            -
                @c = Class.new(Sequel::Model)
         
     | 
| 
      
 353 
     | 
    
         
            +
                @c = Class.new(Sequel::Model(:items))
         
     | 
| 
       254 
354 
     | 
    
         
             
              end
         
     | 
| 
       255 
355 
     | 
    
         | 
| 
       256 
356 
     | 
    
         
             
              specify "should return false if no hooks are defined" do
         
     |