sequel 2.10.0 → 2.11.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 +51 -1
- data/README.rdoc +2 -2
- data/Rakefile +2 -2
- data/doc/advanced_associations.rdoc +6 -18
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/lib/sequel_core/adapters/ado.rb +3 -0
- data/lib/sequel_core/adapters/db2.rb +0 -11
- data/lib/sequel_core/adapters/dbi.rb +0 -11
- data/lib/sequel_core/adapters/do.rb +0 -12
- data/lib/sequel_core/adapters/firebird.rb +21 -16
- data/lib/sequel_core/adapters/informix.rb +1 -11
- data/lib/sequel_core/adapters/jdbc.rb +1 -13
- data/lib/sequel_core/adapters/jdbc/h2.rb +3 -11
- data/lib/sequel_core/adapters/jdbc/mysql.rb +0 -17
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +3 -15
- data/lib/sequel_core/adapters/mysql.rb +31 -27
- data/lib/sequel_core/adapters/odbc.rb +34 -28
- data/lib/sequel_core/adapters/openbase.rb +0 -11
- data/lib/sequel_core/adapters/oracle.rb +11 -9
- data/lib/sequel_core/adapters/postgres.rb +14 -17
- data/lib/sequel_core/adapters/shared/mssql.rb +6 -15
- data/lib/sequel_core/adapters/shared/mysql.rb +29 -14
- data/lib/sequel_core/adapters/shared/oracle.rb +4 -0
- data/lib/sequel_core/adapters/shared/postgres.rb +30 -35
- data/lib/sequel_core/adapters/shared/progress.rb +4 -0
- data/lib/sequel_core/adapters/shared/sqlite.rb +73 -13
- data/lib/sequel_core/adapters/sqlite.rb +8 -18
- data/lib/sequel_core/adapters/utils/date_format.rb +21 -0
- data/lib/sequel_core/{dataset → adapters/utils}/stored_procedures.rb +0 -0
- data/lib/sequel_core/{dataset → adapters/utils}/unsupported.rb +0 -0
- data/lib/sequel_core/core_ext.rb +1 -1
- data/lib/sequel_core/core_sql.rb +9 -4
- data/lib/sequel_core/database.rb +63 -62
- data/lib/sequel_core/dataset.rb +9 -4
- data/lib/sequel_core/dataset/convenience.rb +10 -9
- data/lib/sequel_core/dataset/prepared_statements.rb +1 -1
- data/lib/sequel_core/dataset/sql.rb +130 -36
- data/lib/sequel_core/schema/sql.rb +2 -2
- data/lib/sequel_core/sql.rb +44 -51
- data/lib/sequel_core/version.rb +1 -1
- data/lib/sequel_model/associations.rb +25 -17
- data/lib/sequel_model/base.rb +35 -7
- data/lib/sequel_model/caching.rb +1 -6
- data/lib/sequel_model/record.rb +23 -5
- data/lib/sequel_model/validations.rb +20 -5
- data/spec/adapters/firebird_spec.rb +6 -1
- data/spec/adapters/mysql_spec.rb +12 -0
- data/spec/adapters/postgres_spec.rb +2 -2
- data/spec/adapters/sqlite_spec.rb +81 -2
- data/spec/integration/dataset_test.rb +2 -2
- data/spec/integration/type_test.rb +12 -2
- data/spec/sequel_core/core_sql_spec.rb +46 -12
- data/spec/sequel_core/database_spec.rb +24 -12
- data/spec/sequel_core/dataset_spec.rb +82 -32
- data/spec/sequel_core/schema_spec.rb +16 -0
- data/spec/sequel_model/associations_spec.rb +89 -0
- data/spec/sequel_model/base_spec.rb +66 -0
- data/spec/sequel_model/eager_loading_spec.rb +32 -0
- data/spec/sequel_model/record_spec.rb +9 -9
- data/spec/sequel_model/spec_helper.rb +3 -0
- data/spec/sequel_model/validations_spec.rb +63 -3
- metadata +41 -4
@@ -12,7 +12,7 @@ module Sequel
|
|
12
12
|
SET_DEFAULT = 'SET DEFAULT'.freeze
|
13
13
|
SET_NULL = 'SET NULL'.freeze
|
14
14
|
TYPES = Hash.new {|h, k| k}
|
15
|
-
TYPES.merge!(:double=>'double precision', String=>'varchar',
|
15
|
+
TYPES.merge!(:double=>'double precision', String=>'varchar(255)',
|
16
16
|
Integer=>'integer', Fixnum=>'integer', Bignum=>'bigint',
|
17
17
|
Float=>'double precision', BigDecimal=>'numeric', Numeric=>'numeric',
|
18
18
|
Date=>'date', DateTime=>'timestamp', Time=>'timestamp', File=>'blob',
|
@@ -124,7 +124,7 @@ module Sequel
|
|
124
124
|
# for certain databases.
|
125
125
|
def default_index_name(table_name, columns)
|
126
126
|
schema, table = schema_and_table(table_name)
|
127
|
-
"#{"#{schema}_" if schema and schema != default_schema}#{table}_#{columns.join(UNDERSCORE)}_index"
|
127
|
+
"#{"#{schema}_" if schema and schema != default_schema}#{table}_#{columns.map{|c| c.is_one_of?(String, Symbol) ? c : literal(c).gsub(/\W/, '_')}.join(UNDERSCORE)}_index"
|
128
128
|
end
|
129
129
|
|
130
130
|
# The SQL to drop an index for the table.
|
data/lib/sequel_core/sql.rb
CHANGED
@@ -181,21 +181,21 @@ module Sequel
|
|
181
181
|
module CastMethods
|
182
182
|
# Cast the reciever to the given SQL type
|
183
183
|
def cast(sql_type)
|
184
|
-
|
184
|
+
Cast.new(self, sql_type)
|
185
185
|
end
|
186
186
|
alias_method :cast_as, :cast
|
187
187
|
|
188
188
|
# Cast the reciever to the given SQL type (or integer if none given),
|
189
189
|
# and return the result as a NumericExpression.
|
190
190
|
def cast_numeric(sql_type = nil)
|
191
|
-
cast(sql_type ||
|
191
|
+
cast(sql_type || Integer).sql_number
|
192
192
|
end
|
193
193
|
|
194
194
|
# Cast the reciever to the given SQL type (or text if none given),
|
195
195
|
# and return the result as a StringExpression, so you can use +
|
196
196
|
# directly on the result for SQL string concatenation.
|
197
197
|
def cast_string(sql_type = nil)
|
198
|
-
cast(sql_type ||
|
198
|
+
cast(sql_type || String).sql_string
|
199
199
|
end
|
200
200
|
end
|
201
201
|
|
@@ -336,12 +336,12 @@ module Sequel
|
|
336
336
|
module ComplexExpressionMethods
|
337
337
|
# Extract a datetime_part (e.g. year, month) from self:
|
338
338
|
#
|
339
|
-
# :date.extract(:year) # SQL: extract(year FROM date)
|
339
|
+
# :date.extract(:year) # SQL: extract(year FROM "date")
|
340
340
|
#
|
341
341
|
# Also has the benefit of returning the result as a
|
342
342
|
# NumericExpression instead of a generic ComplexExpression.
|
343
343
|
def extract(datetime_part)
|
344
|
-
|
344
|
+
Function.new(:extract, PlaceholderLiteralString.new("#{datetime_part} FROM ?", [self])).sql_number
|
345
345
|
end
|
346
346
|
|
347
347
|
# Return a BooleanExpression representation of self.
|
@@ -400,22 +400,6 @@ module Sequel
|
|
400
400
|
end
|
401
401
|
end
|
402
402
|
|
403
|
-
# Represents an SQL array. Added so it is possible to deal with a
|
404
|
-
# ruby array of all two pairs as an SQL array instead of an ordered
|
405
|
-
# hash-like conditions specifier.
|
406
|
-
class SQLArray < Expression
|
407
|
-
# Create an object with the given array.
|
408
|
-
def initialize(array)
|
409
|
-
@array = array
|
410
|
-
end
|
411
|
-
|
412
|
-
# Delegate the creation of the resulting SQL to the given dataset,
|
413
|
-
# since it may be database dependent.
|
414
|
-
def to_s(ds)
|
415
|
-
ds.array_sql(@array)
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
403
|
# Blob is used to represent binary data in the Ruby environment that is
|
420
404
|
# stored as a blob type in the database. In PostgreSQL, the blob type is
|
421
405
|
# called bytea. Sequel represents binary data as a Blob object because
|
@@ -423,9 +407,10 @@ module Sequel
|
|
423
407
|
# escaped.
|
424
408
|
class Blob < ::String
|
425
409
|
# return self.
|
426
|
-
def
|
410
|
+
def to_sequel_blob
|
427
411
|
self
|
428
412
|
end
|
413
|
+
alias to_blob to_sequel_blob
|
429
414
|
end
|
430
415
|
|
431
416
|
# Subclass of ComplexExpression where the expression results
|
@@ -516,6 +501,27 @@ module Sequel
|
|
516
501
|
end
|
517
502
|
end
|
518
503
|
|
504
|
+
# Represents a cast of an SQL expression to a specific type.
|
505
|
+
class Cast < GenericExpression
|
506
|
+
# The expression to cast
|
507
|
+
attr_reader :expr
|
508
|
+
|
509
|
+
# The type to which to cast the expression
|
510
|
+
attr_reader :type
|
511
|
+
|
512
|
+
# Set the attributes to the given arguments
|
513
|
+
def initialize(expr, type)
|
514
|
+
@expr = expr
|
515
|
+
@type = type
|
516
|
+
end
|
517
|
+
|
518
|
+
# Delegate the creation of the resulting SQL to the given dataset,
|
519
|
+
# since it may be database dependent.
|
520
|
+
def to_s(ds)
|
521
|
+
ds.cast_sql(expr, type)
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
519
525
|
# Represents all columns in a given table, table.* in SQL
|
520
526
|
class ColumnAll < SpecificExpression
|
521
527
|
# The table containing the columns being selected
|
@@ -586,35 +592,6 @@ module Sequel
|
|
586
592
|
end
|
587
593
|
end
|
588
594
|
|
589
|
-
# IrregularFunction is used for the SQL EXTRACT and CAST functions,
|
590
|
-
# which don't use regular function calling syntax. The IrregularFunction
|
591
|
-
# replaces the commas the regular function uses with a custom
|
592
|
-
# join string.
|
593
|
-
#
|
594
|
-
# This shouldn't be used directly, see CastMethods#cast and
|
595
|
-
# ComplexExpressionMethods#extract.
|
596
|
-
class IrregularFunction < Function
|
597
|
-
# The arguments to pass to the function (may be blank)
|
598
|
-
attr_reader :arg1, :arg2
|
599
|
-
|
600
|
-
# The SQL function to call
|
601
|
-
attr_reader :f
|
602
|
-
|
603
|
-
# The literal string to use in place of a comma to join arguments
|
604
|
-
attr_reader :joiner
|
605
|
-
|
606
|
-
# Set the attributes to the given arguments
|
607
|
-
def initialize(f, arg1, joiner, arg2)
|
608
|
-
@f, @arg1, @joiner, @arg2 = f, arg1, joiner, arg2
|
609
|
-
end
|
610
|
-
|
611
|
-
# Delegate the creation of the resulting SQL to the given dataset,
|
612
|
-
# since it may be database dependent.
|
613
|
-
def to_s(ds)
|
614
|
-
ds.irregular_function_sql(self)
|
615
|
-
end
|
616
|
-
end
|
617
|
-
|
618
595
|
# Represents an SQL JOIN clause, used for joining tables.
|
619
596
|
class JoinClause < SpecificExpression
|
620
597
|
# The type of join to do
|
@@ -785,6 +762,22 @@ module Sequel
|
|
785
762
|
end
|
786
763
|
end
|
787
764
|
|
765
|
+
# Represents an SQL array. Added so it is possible to deal with a
|
766
|
+
# ruby array of all two pairs as an SQL array instead of an ordered
|
767
|
+
# hash-like conditions specifier.
|
768
|
+
class SQLArray < Expression
|
769
|
+
# Create an object with the given array.
|
770
|
+
def initialize(array)
|
771
|
+
@array = array
|
772
|
+
end
|
773
|
+
|
774
|
+
# Delegate the creation of the resulting SQL to the given dataset,
|
775
|
+
# since it may be database dependent.
|
776
|
+
def to_s(ds)
|
777
|
+
ds.array_sql(@array)
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
788
781
|
# Represents an SQL array access, with multiple possible arguments.
|
789
782
|
class Subscript < GenericExpression
|
790
783
|
# The SQL array column
|
data/lib/sequel_core/version.rb
CHANGED
@@ -51,6 +51,15 @@
|
|
51
51
|
# one_to_many :attributes
|
52
52
|
# has_many :attributes
|
53
53
|
module Sequel::Model::Associations
|
54
|
+
# This module contains methods added to all association datasets
|
55
|
+
module DatasetMethods
|
56
|
+
# The model object that created the association dataset
|
57
|
+
attr_accessor :model_object
|
58
|
+
|
59
|
+
# The association reflection related to the association dataset
|
60
|
+
attr_accessor :association_reflection
|
61
|
+
end
|
62
|
+
|
54
63
|
# Array of all association reflections for this model class
|
55
64
|
def all_association_reflections
|
56
65
|
association_reflections.values
|
@@ -100,6 +109,10 @@ module Sequel::Model::Associations
|
|
100
109
|
# - :class - The associated class or its name. If not
|
101
110
|
# given, uses the association's name, which is camelized (and
|
102
111
|
# singularized unless the type is :many_to_one)
|
112
|
+
# - :clone - Merge the current options and block into the options and block used in defining
|
113
|
+
# the given association. Can be used to DRY up a bunch of similar associations that
|
114
|
+
# all share the same options such as :class and :key, while changing the order and block used.
|
115
|
+
# - :conditions - The conditions to use to filter the association, can be any argument passed to filter.
|
103
116
|
# - :dataset - A proc that is instance_evaled to get the base dataset
|
104
117
|
# to use for the _dataset method (before the other options are applied).
|
105
118
|
# - :eager - The associations to eagerly load via EagerLoading#eager when loading the associated object(s).
|
@@ -126,7 +139,8 @@ module Sequel::Model::Associations
|
|
126
139
|
# - :graph_block - The block to pass to join_table when eagerly loading
|
127
140
|
# the association via eager_graph.
|
128
141
|
# - :graph_conditions - The additional conditions to use on the SQL join when eagerly loading
|
129
|
-
# the association via eager_graph. Should be a hash or an array of all two pairs.
|
142
|
+
# the association via eager_graph. Should be a hash or an array of all two pairs. If not
|
143
|
+
# specified, the :conditions option is used if it is a hash or array of all two pairs.
|
130
144
|
# - :graph_join_type - The type of SQL join to use when eagerly loading the association via
|
131
145
|
# eager_graph. Defaults to :left_outer.
|
132
146
|
# - :graph_only_conditions - The conditions to use on the SQL join when eagerly loading
|
@@ -203,11 +217,16 @@ module Sequel::Model::Associations
|
|
203
217
|
raise(Error, 'Model.associate name argument must be a symbol') unless Symbol === name
|
204
218
|
|
205
219
|
# merge early so we don't modify opts
|
206
|
-
|
220
|
+
orig_opts = opts.dup
|
221
|
+
orig_opts = association_reflection(opts[:clone])[:orig_opts].merge(orig_opts) if opts[:clone]
|
222
|
+
opts = orig_opts.merge(:type => type, :name => name, :cache => true, :model => self)
|
223
|
+
opts[:block] = block if block
|
207
224
|
opts = assoc_class.new.merge!(opts)
|
208
225
|
opts[:eager_block] = block unless opts.include?(:eager_block)
|
209
226
|
opts[:graph_join_type] ||= :left_outer
|
210
227
|
opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
|
228
|
+
conds = opts[:conditions]
|
229
|
+
opts[:graph_conditions] = conds if !opts.include?(:graph_conditions) and (conds.is_a?(Hash) or (conds.is_a?(Array) and conds.all_two_pairs?))
|
211
230
|
opts[:graph_conditions] = opts[:graph_conditions] ? opts[:graph_conditions].to_a : []
|
212
231
|
opts[:graph_select] = Array(opts[:graph_select]) if opts[:graph_select]
|
213
232
|
[:before_add, :before_remove, :after_add, :after_remove, :after_load, :extend].each do |cb_type|
|
@@ -225,6 +244,9 @@ module Sequel::Model::Associations
|
|
225
244
|
|
226
245
|
send(:"def_#{type}", opts)
|
227
246
|
|
247
|
+
orig_opts.delete(:clone)
|
248
|
+
orig_opts.merge!(:class_name=>opts[:class_name], :class=>opts[:class], :block=>block)
|
249
|
+
opts[:orig_opts] = orig_opts
|
228
250
|
# don't add to association_reflections until we are sure there are no errors
|
229
251
|
association_reflections[name] = opts
|
230
252
|
end
|
@@ -386,21 +408,7 @@ module Sequel::Model::Associations
|
|
386
408
|
return if opts[:read_only]
|
387
409
|
|
388
410
|
association_module_private_def(opts._setter_method){|o| send(:"#{key}=", (o.send(opts.primary_key) if o))}
|
389
|
-
|
390
|
-
association_module_def(opts.setter_method) do |o|
|
391
|
-
raise(Sequel::Error, "model object #{model} does not have a primary key") if o && !o.pk
|
392
|
-
old_val = send(opts.association_method)
|
393
|
-
return o if old_val == o
|
394
|
-
return if old_val and run_association_callbacks(opts, :before_remove, old_val) == false
|
395
|
-
return if o and run_association_callbacks(opts, :before_add, o) == false
|
396
|
-
send(opts._setter_method, o)
|
397
|
-
associations[name] = o
|
398
|
-
remove_reciprocal_object(opts, old_val) if old_val
|
399
|
-
add_reciprocal_object(opts, o) if o
|
400
|
-
run_association_callbacks(opts, :after_add, o) if o
|
401
|
-
run_association_callbacks(opts, :after_remove, old_val) if old_val
|
402
|
-
o
|
403
|
-
end
|
411
|
+
association_module_def(opts.setter_method){|o| set_associated_object(opts, o)}
|
404
412
|
end
|
405
413
|
|
406
414
|
# Adds one_to_many association instance methods
|
data/lib/sequel_model/base.rb
CHANGED
@@ -2,16 +2,25 @@ module Sequel
|
|
2
2
|
class Model
|
3
3
|
@allowed_columns = nil
|
4
4
|
@association_reflections = {}
|
5
|
+
@cache_store = nil
|
6
|
+
@cache_ttl = nil
|
7
|
+
@db = nil
|
8
|
+
@db_schema = nil
|
5
9
|
@dataset_methods = {}
|
6
10
|
@hooks = {}
|
11
|
+
@overridable_methods_module = nil
|
7
12
|
@primary_key = :id
|
8
13
|
@raise_on_save_failure = true
|
9
14
|
@raise_on_typecast_failure = true
|
10
15
|
@restrict_primary_key = true
|
11
16
|
@restricted_columns = nil
|
17
|
+
@simple_pk = nil
|
18
|
+
@simple_table = nil
|
19
|
+
@skip_superclass_validations = nil
|
12
20
|
@sti_dataset = nil
|
13
21
|
@sti_key = nil
|
14
22
|
@strict_param_setting = true
|
23
|
+
@transform = nil
|
15
24
|
@typecast_empty_string_to_nil = true
|
16
25
|
@typecast_on_assignment = true
|
17
26
|
|
@@ -41,6 +50,14 @@ module Sequel
|
|
41
50
|
# (default: no columns).
|
42
51
|
metaattr_reader :restricted_columns
|
43
52
|
|
53
|
+
# Should be the literal primary key column name if this Model's table has a simple primary key, or
|
54
|
+
# nil if the model has a compound primary key or no primary key.
|
55
|
+
metaattr_reader :simple_pk
|
56
|
+
|
57
|
+
# Should be the literal table name if this Model's dataset is a simple table (no select, order, join, etc.),
|
58
|
+
# or nil otherwise.
|
59
|
+
metaattr_reader :simple_table
|
60
|
+
|
44
61
|
# The base dataset for STI, to which filters are added to get
|
45
62
|
# only the models for the specific STI subclass.
|
46
63
|
metaattr_reader :sti_dataset
|
@@ -68,15 +85,19 @@ module Sequel
|
|
68
85
|
left_outer_join limit map multi_insert naked order order_by order_more
|
69
86
|
paginate print query range reverse_order right_outer_join select
|
70
87
|
select_all select_more server set set_graph_aliases single_value size to_csv to_hash
|
71
|
-
transform union uniq unfiltered unordered update where'.map{|x| x.to_sym}
|
88
|
+
transform union uniq unfiltered unordered update where with_sql'.map{|x| x.to_sym}
|
72
89
|
|
73
90
|
# Instance variables that are inherited in subclasses
|
74
91
|
INHERITED_INSTANCE_VARIABLES = {:@allowed_columns=>:dup, :@cache_store=>nil,
|
75
92
|
:@cache_ttl=>nil, :@dataset_methods=>:dup, :@primary_key=>nil,
|
76
93
|
:@raise_on_save_failure=>nil, :@restricted_columns=>:dup, :@restrict_primary_key=>nil,
|
94
|
+
:@simple_pk=>nil, :@simple_table=>nil,
|
77
95
|
:@sti_dataset=>nil, :@sti_key=>nil, :@strict_param_setting=>nil,
|
78
96
|
:@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil,
|
79
97
|
:@raise_on_typecast_failure=>nil, :@association_reflections=>:dup}
|
98
|
+
|
99
|
+
# Empty instance variables, for -w compliance
|
100
|
+
EMPTY_INSTANCE_VARIABLES = [:@overridable_methods_module, :@transform, :@db, :@skip_superclass_validations]
|
80
101
|
|
81
102
|
# Returns the first record from the database matching the conditions.
|
82
103
|
# If a hash is given, it is used as the conditions. If another
|
@@ -85,11 +106,12 @@ module Sequel
|
|
85
106
|
# first before a dataset lookup is attempted unless a hash is supplied.
|
86
107
|
def self.[](*args)
|
87
108
|
args = args.first if (args.size == 1)
|
88
|
-
|
89
|
-
|
90
|
-
|
109
|
+
return dataset[args] if args.is_a?(Hash)
|
110
|
+
return cache_lookup(args) if @cache_store
|
111
|
+
if t = simple_table and p = simple_pk
|
112
|
+
with_sql("SELECT * FROM #{t} WHERE #{p} = #{dataset.literal(args)} LIMIT 1").first
|
91
113
|
else
|
92
|
-
|
114
|
+
dataset[primary_key_hash(args)]
|
93
115
|
end
|
94
116
|
end
|
95
117
|
|
@@ -174,6 +196,7 @@ module Sequel
|
|
174
196
|
# Modify and return eager loading dataset based on association options
|
175
197
|
def self.eager_loading_dataset(opts, ds, select, associations)
|
176
198
|
ds = ds.select(*select) if select
|
199
|
+
ds = ds.filter(opts[:conditions]) if opts[:conditions]
|
177
200
|
ds = ds.order(*opts[:order]) if opts[:order]
|
178
201
|
ds = ds.eager(opts[:eager]) if opts[:eager]
|
179
202
|
ds = ds.eager_graph(opts[:eager_graph]) if opts[:eager_graph]
|
@@ -201,6 +224,7 @@ module Sequel
|
|
201
224
|
def self.inherited(subclass)
|
202
225
|
sup_class = subclass.superclass
|
203
226
|
ivs = subclass.instance_variables.collect{|x| x.to_s}
|
227
|
+
EMPTY_INSTANCE_VARIABLES.each{|iv| subclass.instance_variable_set(iv, nil) unless ivs.include?(iv.to_s)}
|
204
228
|
INHERITED_INSTANCE_VARIABLES.each do |iv, dup|
|
205
229
|
next if ivs.include?(iv.to_s)
|
206
230
|
sup_class_value = sup_class.instance_variable_get(iv)
|
@@ -211,7 +235,7 @@ module Sequel
|
|
211
235
|
db
|
212
236
|
begin
|
213
237
|
if sup_class == Model
|
214
|
-
subclass.set_dataset(
|
238
|
+
subclass.set_dataset(subclass.implicit_table_name) unless subclass.name.blank?
|
215
239
|
elsif ds = sup_class.instance_variable_get(:@dataset)
|
216
240
|
subclass.set_dataset(sup_class.sti_key ? sup_class.sti_dataset.filter(sup_class.sti_key=>subclass.name.to_s) : ds.clone, :inherited=>true)
|
217
241
|
end
|
@@ -239,7 +263,7 @@ module Sequel
|
|
239
263
|
# Mark the model as not having a primary key. Not having a primary key
|
240
264
|
# can cause issues, among which is that you won't be able to update records.
|
241
265
|
def self.no_primary_key
|
242
|
-
@primary_key = nil
|
266
|
+
@simple_pk = @primary_key = nil
|
243
267
|
end
|
244
268
|
|
245
269
|
# Returns primary key attribute hash. If using a composite primary key
|
@@ -317,8 +341,10 @@ module Sequel
|
|
317
341
|
inherited = opts[:inherited]
|
318
342
|
@dataset = case ds
|
319
343
|
when Symbol
|
344
|
+
@simple_table = db.literal(ds)
|
320
345
|
db[ds]
|
321
346
|
when Dataset
|
347
|
+
@simple_table = nil
|
322
348
|
@db = ds.db
|
323
349
|
ds
|
324
350
|
else
|
@@ -327,6 +353,7 @@ module Sequel
|
|
327
353
|
@dataset.set_model(self)
|
328
354
|
@dataset.transform(@transform) if @transform
|
329
355
|
if inherited
|
356
|
+
@simple_table = sti_key ? nil : superclass.simple_table
|
330
357
|
@columns = @dataset.columns rescue nil
|
331
358
|
else
|
332
359
|
@dataset.extend(DatasetMethods)
|
@@ -354,6 +381,7 @@ module Sequel
|
|
354
381
|
# You can set it to nil to not have a primary key, but that
|
355
382
|
# cause certain things not to work, see #no_primary_key.
|
356
383
|
def self.set_primary_key(*key)
|
384
|
+
@simple_pk = key.length == 1 ? db.literal(key.first) : nil
|
357
385
|
@primary_key = (key.length == 1) ? key[0] : key.flatten
|
358
386
|
end
|
359
387
|
|
data/lib/sequel_model/caching.rb
CHANGED
@@ -17,7 +17,7 @@ module Sequel
|
|
17
17
|
def self.set_cache(store, opts = {})
|
18
18
|
@cache_store = store
|
19
19
|
@cache_ttl = opts[:ttl] || 3600
|
20
|
-
|
20
|
+
before_update :cache_delete
|
21
21
|
before_update_values :cache_delete
|
22
22
|
before_delete :cache_delete
|
23
23
|
end
|
@@ -78,10 +78,5 @@ module Sequel
|
|
78
78
|
def cache_delete
|
79
79
|
model.send(:cache_delete, cache_key)
|
80
80
|
end
|
81
|
-
|
82
|
-
# Delete this object from the cache unless it is a new record
|
83
|
-
def cache_delete_unless_new
|
84
|
-
cache_delete unless new?
|
85
|
-
end
|
86
81
|
end
|
87
82
|
end
|
data/lib/sequel_model/record.rb
CHANGED
@@ -345,8 +345,12 @@ module Sequel
|
|
345
345
|
def _dataset(opts)
|
346
346
|
raise(Sequel::Error, "model object #{model} does not have a primary key") if opts.dataset_need_primary_key? && !pk
|
347
347
|
ds = send(opts._dataset_method)
|
348
|
+
ds.extend(Associations::DatasetMethods)
|
349
|
+
ds.model_object = self
|
350
|
+
ds.association_reflection = opts
|
348
351
|
opts[:extend].each{|m| ds.extend(m)}
|
349
352
|
ds = ds.select(*opts.select) if opts.select
|
353
|
+
ds = ds.filter(opts[:conditions]) if opts[:conditions]
|
350
354
|
ds = ds.order(*opts[:order]) if opts[:order]
|
351
355
|
ds = ds.limit(*opts[:limit]) if opts[:limit]
|
352
356
|
ds = ds.eager(*opts[:eager]) if opts[:eager]
|
@@ -470,6 +474,24 @@ module Sequel
|
|
470
474
|
end
|
471
475
|
end
|
472
476
|
|
477
|
+
# Set the given object as the associated object for the given association
|
478
|
+
def set_associated_object(opts, o)
|
479
|
+
raise(Sequel::Error, "model object #{model} does not have a primary key") if o && !o.pk
|
480
|
+
old_val = send(opts.association_method)
|
481
|
+
return o if old_val == o
|
482
|
+
return if old_val and run_association_callbacks(opts, :before_remove, old_val) == false
|
483
|
+
return if o and run_association_callbacks(opts, :before_add, o) == false
|
484
|
+
send(opts._setter_method, o)
|
485
|
+
associations[opts[:name]] = o
|
486
|
+
remove_reciprocal_object(opts, old_val) if old_val
|
487
|
+
if o
|
488
|
+
add_reciprocal_object(opts, o)
|
489
|
+
run_association_callbacks(opts, :after_add, o)
|
490
|
+
end
|
491
|
+
run_association_callbacks(opts, :after_remove, old_val) if old_val
|
492
|
+
o
|
493
|
+
end
|
494
|
+
|
473
495
|
# Set the columns, filtered by the only and except arrays.
|
474
496
|
def set_restricted(hash, only, except)
|
475
497
|
columns_not_set = model.instance_variable_get(:@columns).blank?
|
@@ -527,11 +549,7 @@ module Sequel
|
|
527
549
|
begin
|
528
550
|
model.db.typecast_value(col_schema[:type], value)
|
529
551
|
rescue Error::InvalidValue
|
530
|
-
|
531
|
-
raise
|
532
|
-
else
|
533
|
-
value
|
534
|
-
end
|
552
|
+
raise_on_typecast_failure ? raise : value
|
535
553
|
end
|
536
554
|
end
|
537
555
|
|