Class: Sequel::Model

Inherits:
Object show all
Extended by:
Enumerable, Associations
Defined in:
lib/sequel_model.rb,
lib/sequel_model/base.rb,
lib/sequel_model/hooks.rb,
lib/sequel_model/record.rb,
lib/sequel_model/schema.rb,
lib/sequel_model/caching.rb,
lib/sequel_model/plugins.rb,
lib/sequel_model/validations.rb,
lib/sequel_model/association_reflection.rb

Overview

Model has some methods that are added via metaprogramming:

  • All of the methods in DATASET_METHODS have class methods created that call the Model’s dataset with the method of the same name with the given arguments.

  • All of the methods in HOOKS have class methods created that accept either a method name symbol or an optional tag and a block. These methods run the code as a callback at the specified time. For example:

    Model.before_save :do_something
    Model.before_save(:do_something_else){ self.something_else = 42}
    object = Model.new
    object.save
    

    Would run the object’s :do_something method following by the code block related to :do_something_else. Note that if you specify a block, a tag is optional. If the tag is not nil, it will overwrite a previous block with the same tag. This allows hooks to work with systems that reload code.

  • All of the methods in HOOKS also create instance methods, but you should not override these instance methods.

  • The following instance_methods all call the class method of the same name: columns, dataset, db, primary_key, str_columns.

  • The following class level attr_readers are created: allowed_columns, cache_store, cache_ttl, dataset_methods, primary_key, restricted_columns, sti_dataset, and sti_key. You should not usually need to access these directly.

  • The following class level attr_accessors are created: raise_on_typecast_failure, raise_on_save_failure, strict_param_setting, typecast_empty_string_to_nil, and typecast_on_assignment:

    # Don't raise an error if a validation attempt fails in
    # save/create/save_changes/etc.
    Model.raise_on_save_failure = false
    Model.before_save{false}
    Model.new.save # => nil
    # Don't raise errors in new/set/update/etc. if an attempt to
    # access a missing/restricted method occurs (just silently
    # skip it)
    Model.strict_param_setting = false
    Model.new(:id=>1) # No Error
    # Don't typecast attribute values on assignment
    Model.typecast_on_assignment = false
    m = Model.new
    m.number = '10'
    m.number # => '10' instead of 10
    # Don't typecast empty string to nil for non-string, non-blob columns.
    Model.typecast_empty_string_to_nil = false
    m.number = ''
    m.number # => '' instead of nil
    # Don't raise if unable to typecast data for a column
    Model.typecast_empty_string_to_nil = true
    Model.raise_on_typecast_failure = false
    m.not_null_column = '' # => nil
    m.number = 'A' # => 'A'
    
  • The following class level method aliases are defined:

    • Model.dataset= => set_dataset

    • Model.is_a => is

Defined Under Namespace

Modules: Associations, DatasetMethods, Validation

Constant Summary collapse

DATASET_METHODS =

Dataset methods to proxy via metaprogramming

%w'<< all avg count delete distinct eager eager_graph each each_page 
empty? except exclude filter first from from_self full_outer_join get graph 
group group_and_count group_by having import inner_join insert 
insert_multiple intersect interval invert_order join join_table last 
left_outer_join limit map multi_insert naked order order_by order_more 
paginate print query range reverse_order right_outer_join select 
select_all select_more server set set_graph_aliases single_value size to_csv to_hash
transform union uniq unfiltered unordered update where'.map{|x| x.to_sym}
INHERITED_INSTANCE_VARIABLES =

Instance variables that are inherited in subclasses

{:@allowed_columns=>:dup, :@cache_store=>nil,
:@cache_ttl=>nil, :@dataset_methods=>:dup, :@primary_key=>nil, 
:@raise_on_save_failure=>nil, :@restricted_columns=>:dup, :@restrict_primary_key=>nil,
:@sti_dataset=>nil, :@sti_key=>nil, :@strict_param_setting=>nil,
:@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil,
:@raise_on_typecast_failure=>nil}
HOOKS =

Hooks that are safe for public use

[:after_initialize, :before_create, :after_create, :before_update,
:after_update, :before_save, :after_save, :before_destroy, :after_destroy,
:before_validation, :after_validation]
PRIVATE_HOOKS =

Hooks that are only for internal use

[:before_update_values, :before_delete]
RESTRICTED_SETTER_METHODS =

The setter methods (methods ending with =) that are never allowed to be called automatically via set.

%w"== === []= taguri= typecast_empty_string_to_nil= typecast_on_assignment= strict_param_setting= raise_on_save_failure= raise_on_typecast_failure="
DEFAULT_VALIDATION_IF_PROC =

Validations without an :if option are always run

proc{true}
@@lazy_load_schema =

Whether to lazily load the schema for future subclasses. Unless turned off, checks the database for the table schema whenever a subclass is created

false

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

send_each

Methods included from Associations

all_association_reflections, associate, association_reflection, many_to_many, many_to_one, one_to_many

Constructor Details

#initialize(values = nil, from_db = false) {|_self| ... } ⇒ Model

Creates new instance with values set to passed-in Hash. If a block is given, yield the instance to the block. This method runs the after_initialize hook after it has optionally yielded itself to the block.

Arguments:

  • values - should be a hash with symbol keys, though string keys will work if from_db is false.

  • from_db - should only be set by Model.load, forget it exists.

Yields:

  • (_self)

Yield Parameters:

  • _self (Sequel::Model)

    the object that the method was called on



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/sequel_model/record.rb', line 52

def initialize(values = nil, from_db = false, &block)
  values ||=  {}
  @associations = {}
  @db_schema = model.db_schema
  @changed_columns = []
  @raise_on_save_failure = model.raise_on_save_failure
  @strict_param_setting = model.strict_param_setting
  @typecast_on_assignment = model.typecast_on_assignment
  @typecast_empty_string_to_nil = model.typecast_empty_string_to_nil
  @raise_on_typecast_failure = model.raise_on_typecast_failure
  if from_db
    @new = false
    @values = values
  else
    @values = {}
    @new = true
    set(values)
  end
  @changed_columns.clear 
  
  yield self if block
  after_initialize
end

Instance Attribute Details

#associationsObject (readonly)

The current cached associations. A hash with the keys being the association name symbols and the values being the associated object or nil (many_to_one), or the array of associated objects (*_to_many).



10
11
12
# File 'lib/sequel_model/record.rb', line 10

def associations
  @associations
end

#changed_columnsObject (readonly)

The columns that have been updated. This isn’t completely accurate, see Model#[]=.



14
15
16
# File 'lib/sequel_model/record.rb', line 14

def changed_columns
  @changed_columns
end

#raise_on_save_failure=(value) ⇒ Object (writeonly)

Whether this model instance should raise an exception instead of returning nil on a failure to save/save_changes/etc.



18
19
20
# File 'lib/sequel_model/record.rb', line 18

def raise_on_save_failure=(value)
  @raise_on_save_failure = value
end

#raise_on_typecast_failure=(value) ⇒ Object (writeonly)

Whether this model instance should raise an error when it cannot typecast data for a column correctly.



22
23
24
# File 'lib/sequel_model/record.rb', line 22

def raise_on_typecast_failure=(value)
  @raise_on_typecast_failure = value
end

#strict_param_setting=(value) ⇒ Object (writeonly)

Whether this model instance should raise an error if attempting to call a method through set/update and their variants that either doesn’t exist or access to it is denied.



27
28
29
# File 'lib/sequel_model/record.rb', line 27

def strict_param_setting=(value)
  @strict_param_setting = value
end

#typecast_empty_string_to_nil=(value) ⇒ Object (writeonly)

Whether this model instance should typecast the empty string (”) to nil for columns that are non string or blob.



31
32
33
# File 'lib/sequel_model/record.rb', line 31

def typecast_empty_string_to_nil=(value)
  @typecast_empty_string_to_nil = value
end

#typecast_on_assignment=(value) ⇒ Object (writeonly)

Whether this model instance should typecast on attribute assignment



34
35
36
# File 'lib/sequel_model/record.rb', line 34

def typecast_on_assignment=(value)
  @typecast_on_assignment = value
end

#valuesObject (readonly)

The hash of attribute values. Keys are symbols with the names of the underlying database columns.



38
39
40
# File 'lib/sequel_model/record.rb', line 38

def values
  @values
end

Class Method Details

.[](*args) ⇒ Object

Returns the first record from the database matching the conditions. If a hash is given, it is used as the conditions. If another object is given, it finds the first record whose primary key(s) match the given argument(s). If caching is used, the cache is checked first before a dataset lookup is attempted unless a hash is supplied.



86
87
88
89
90
91
92
93
94
# File 'lib/sequel_model/base.rb', line 86

def self.[](*args)
  args = args.first if (args.size == 1)

  if Hash === args
    dataset[args]
  else
    @cache_store ? cache_lookup(args) : dataset[primary_key_hash(args)]
  end
end

.columnsObject

Returns the columns in the result set in their original order. Generally, this will used the columns determined via the database schema, but in certain cases (e.g. models that are based on a joined dataset) it will use Dataset#columns to find the columns, which may be empty if the Dataset has no records.



101
102
103
# File 'lib/sequel_model/base.rb', line 101

def self.columns
  @columns || set_columns(dataset.naked.columns)
end

.create(values = {}, &block) ⇒ Object

Creates new instance with values set to passed-in Hash, saves it (running any callbacks), and returns the instance if the object was saved correctly. If there was an error saving the object, returns false.



109
110
111
112
113
# File 'lib/sequel_model/base.rb', line 109

def self.create(values = {}, &block)
  obj = new(values, &block)
  return unless obj.save
  obj
end

.create_tableObject

Creates table, using the column information from set_schema.



4
5
6
7
8
# File 'lib/sequel_model/schema.rb', line 4

def self.create_table
  db.create_table(table_name, @schema)
  @db_schema = get_db_schema(true) unless @@lazy_load_schema
  columns
end

.create_table!Object

Drops the table if it exists and then runs create_table. Should probably not be used except in testing.



12
13
14
15
# File 'lib/sequel_model/schema.rb', line 12

def self.create_table!
  drop_table rescue nil
  create_table
end

.datasetObject

Returns the dataset associated with the Model class.



116
117
118
# File 'lib/sequel_model/base.rb', line 116

def self.dataset
  @dataset || raise(Error, "No dataset associated with #{self}")
end

.dbObject

Returns the database associated with the Model class.

Raises:



121
122
123
124
125
126
# File 'lib/sequel_model/base.rb', line 121

def self.db
  return @db if @db
  @db = self == Model ? DATABASES.first : superclass.db
  raise(Error, "No database associated with #{self}") unless @db
  @db
end

.db=(db) ⇒ Object

Sets the database associated with the Model class.



129
130
131
132
133
134
# File 'lib/sequel_model/base.rb', line 129

def self.db=(db)
  @db = db
  if @dataset
    set_dataset(db[table_name])
  end
end

.db_schemaObject

Returns the cached schema information if available or gets it from the database.



138
139
140
# File 'lib/sequel_model/base.rb', line 138

def self.db_schema
  @db_schema ||= get_db_schema
end

.def_dataset_method(*args, &block) ⇒ Object

If a block is given, define a method on the dataset with the given argument name using the given block as well as a method on the model that calls the dataset method.

If a block is not given, define a method on the model for each argument that calls the dataset method of the same argument name.

Raises:



148
149
150
151
152
153
154
155
156
157
# File 'lib/sequel_model/base.rb', line 148

def self.def_dataset_method(*args, &block)
  raise(Error, "No arguments given") if args.empty?
  if block_given?
    raise(Error, "Defining a dataset method using a block requires only one argument") if args.length > 1
    meth = args.first
    @dataset_methods[meth] = block
    dataset.meta_def(meth, &block)
  end
  args.each{|arg| instance_eval("def #{arg}(*args, &block); dataset.#{arg}(*args, &block) end", __FILE__, __LINE__)}
end

.delete_allObject

Deletes all records in the model’s table.



160
161
162
# File 'lib/sequel_model/base.rb', line 160

def self.delete_all
  dataset.delete
end

.destroy_allObject

Like delete_all, but invokes before_destroy and after_destroy hooks if used.



165
166
167
# File 'lib/sequel_model/base.rb', line 165

def self.destroy_all
  dataset.destroy
end

.drop_tableObject

Drops table.



18
19
20
# File 'lib/sequel_model/schema.rb', line 18

def self.drop_table
  db.drop_table(table_name)
end

.eager_loading_dataset(opts, ds, select, associations) ⇒ Object

Modify and return eager loading dataset based on association options



175
176
177
178
179
180
181
182
183
# File 'lib/sequel_model/base.rb', line 175

def self.eager_loading_dataset(opts, ds, select, associations)
  ds = ds.select(*select) if select
  ds = ds.order(*opts[:order]) if opts[:order]
  ds = ds.eager(opts[:eager]) if opts[:eager]
  ds = ds.eager_graph(opts[:eager_graph]) if opts[:eager_graph]
  ds = ds.eager(associations) unless associations.blank?
  ds = opts[:eager_block].call(ds) if opts[:eager_block]
  ds
end

.fetch(*args) ⇒ Object

Returns a dataset with custom SQL that yields model objects.



170
171
172
# File 'lib/sequel_model/base.rb', line 170

def self.fetch(*args)
  db.fetch(*args).set_model(self)
end

.find(*args, &block) ⇒ Object

Finds a single record according to the supplied filter, e.g.:

Ticket.find :author => 'Sharon' # => record


188
189
190
# File 'lib/sequel_model/base.rb', line 188

def self.find(*args, &block)
  dataset.filter(*args, &block).first
end

.find_or_create(cond) ⇒ Object

Like find but invokes create with given conditions when record does not exists.



194
195
196
# File 'lib/sequel_model/base.rb', line 194

def self.find_or_create(cond)
  find(cond) || create(cond)
end

.has_hooks?(key) ⇒ Boolean

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.

Returns:

  • (Boolean)


14
15
16
17
# File 'lib/sequel_model/hooks.rb', line 14

def self.has_hooks?(key)
  has = hooks[key] && !hooks[key].empty?
  has || ((self != Model) && superclass.has_hooks?(key))
end

.has_validations?Boolean

Returns true if validations are defined.

Returns:

  • (Boolean)


54
55
56
# File 'lib/sequel_model/validations.rb', line 54

def self.has_validations?
  !validations.empty?
end

.implicit_table_nameObject

Returns the implicit table name for the model class.



224
225
226
# File 'lib/sequel_model/base.rb', line 224

def self.implicit_table_name
  name.demodulize.underscore.pluralize.to_sym
end

.inherited(subclass) ⇒ Object

If possible, set the dataset for the model subclass as soon as it is created. Also, inherit the INHERITED_INSTANCE_VARIABLES from the parent class.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/sequel_model/base.rb', line 201

def self.inherited(subclass)
  sup_class = subclass.superclass
  ivs = subclass.instance_variables.collect{|x| x.to_s}
  INHERITED_INSTANCE_VARIABLES.each do |iv, dup|
    next if ivs.include?(iv.to_s)
    sup_class_value = sup_class.instance_variable_get(iv)
    sup_class_value = sup_class_value.dup if dup == :dup && sup_class_value
    subclass.instance_variable_set(iv, sup_class_value)
  end
  unless ivs.include?("@dataset")
    begin
      if sup_class == Model
        subclass.set_dataset(Model.db[subclass.implicit_table_name]) unless subclass.name.blank?
      elsif ds = sup_class.instance_variable_get(:@dataset)
        subclass.set_dataset(sup_class.sti_key ? sup_class.sti_dataset.filter(sup_class.sti_key=>subclass.name.to_s) : ds.clone, :inherited=>true)
      end
    rescue
      nil
    end
  end
end

.is(plugin, *args) ⇒ Object

Loads a plugin for use with the model class, passing optional arguments to the plugin. If the plugin has a DatasetMethods module and the model doesn’t have a dataset, raise an Error.

Raises:



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/sequel_model/plugins.rb', line 21

def self.is(plugin, *args)
  m = plugin_module(plugin)
  raise(Error, "Plugin cannot be applied because the model class has no dataset") if m.const_defined?("DatasetMethods") && !@dataset
  if m.respond_to?(:apply)
    m.apply(self, *args)
  end
  if m.const_defined?("InstanceMethods")
    class_def(:"#{plugin}_opts") {args.first}
    include(m::InstanceMethods)
  end
  if m.const_defined?("ClassMethods")
    meta_def(:"#{plugin}_opts") {args.first}
    extend(m::ClassMethods)
  end
  if m.const_defined?("DatasetMethods")
    dataset.meta_def(:"#{plugin}_opts") {args.first}
    dataset.extend(m::DatasetMethods)
    def_dataset_method(*m::DatasetMethods.public_instance_methods)
  end
end

.lazy_load_schema=(value) ⇒ Object

Set whether to lazily load the schema for future model classes. When the schema is lazy loaded, the schema information is grabbed during the first instantiation of the class instead of when the class is created.



232
233
234
# File 'lib/sequel_model/base.rb', line 232

def self.lazy_load_schema=(value)
  @@lazy_load_schema = value
end

.load(values) ⇒ Object

Initializes a model instance as an existing record. This constructor is used by Sequel to initialize model instances when fetching records. #load requires that values be a hash where all keys are symbols. It probably should not be used by external code.



240
241
242
# File 'lib/sequel_model/base.rb', line 240

def self.load(values)
  new(values, true)
end

.no_primary_keyObject

Mark the model as not having a primary key. Not having a primary key can cause issues, among which is that you won’t be able to update records.



246
247
248
# File 'lib/sequel_model/base.rb', line 246

def self.no_primary_key
  @primary_key = nil
end

.primary_key_hash(value) ⇒ Object

Returns primary key attribute hash. If using a composite primary key value such be an array with values for each primary key in the correct order. For a standard primary key, value should be an object with a compatible type for the key. If the model does not have a primary key, raises an Error.

Raises:



255
256
257
258
259
260
261
262
263
264
265
# File 'lib/sequel_model/base.rb', line 255

def self.primary_key_hash(value)
  raise(Error, "#{self} does not have a primary key") unless key = @primary_key
  case key
  when Array
    hash = {}
    key.each_with_index{|k,i| hash[k] = value[i]}
    hash
  else
    {key => value}
  end
end

.restrict_primary_keyObject

Restrict the setting of the primary key(s) inside new/set/update. Because this is the default, this only make sense to use in a subclass where the parent class has used unrestrict_primary_key.



270
271
272
# File 'lib/sequel_model/base.rb', line 270

def self.restrict_primary_key
  @restrict_primary_key = true
end

.restrict_primary_key?Boolean

Whether or not setting the primary key inside new/set/update is restricted, true by default.

Returns:

  • (Boolean)


276
277
278
# File 'lib/sequel_model/base.rb', line 276

def self.restrict_primary_key?
  @restrict_primary_key
end

.schemaObject

Returns table schema created with set_schema for direct descendant of Model. Does not retreive schema information from the database, see db_schema if you want that.



25
26
27
# File 'lib/sequel_model/schema.rb', line 25

def self.schema
  @schema || (superclass.schema unless superclass == Model)
end

.serialize(*columns) ⇒ Object

Serializes column with YAML or through marshalling. Arguments should be column symbols, with an optional trailing hash with a :format key set to :yaml or :marshal (:yaml is the default). Setting this adds a transform to the model and dataset so that columns values will be serialized when saved and deserialized when returned from the database.



285
286
287
288
289
290
291
292
# File 'lib/sequel_model/base.rb', line 285

def self.serialize(*columns)
  format = columns.extract_options![:format] || :yaml
  @transform = columns.inject({}) do |m, c|
    m[c] = format
    m
  end
  @dataset.transform(@transform) if @dataset
end

.set_allowed_columns(*cols) ⇒ Object

Set the columns to allow in new/set/update. Using this means that any columns not listed here will not be modified. If you have any virtual setter methods (methods that end in =) that you want to be used in new/set/update, they need to be listed here as well (without the =).

It may be better to use (set|update)_only instead of this in places where only certain columns may be allowed.



301
302
303
# File 'lib/sequel_model/base.rb', line 301

def self.set_allowed_columns(*cols)
  @allowed_columns = cols
end

.set_cache(store, opts = {}) ⇒ Object

Set the cache store for the model, as well as the caching before_* hooks.

The cache store should implement the following API:

cache_store.set(key, obj, time) # Associate the obj with the given key
                                # in the cache for the time (specified
                                # in seconds)
cache_store.get(key) => obj # Returns object set with same key
cache_store.get(key2) => nil # nil returned if there isn't an object
                             # currently in the cache with that key


17
18
19
20
21
22
23
# File 'lib/sequel_model/caching.rb', line 17

def self.set_cache(store, opts = {})
  @cache_store = store
  @cache_ttl = opts[:ttl] || 3600
  before_save :cache_delete_unless_new
  before_update_values :cache_delete
  before_delete :cache_delete
end

.set_cache_ttl(ttl) ⇒ Object

Set the time to live for the cache store, in seconds (default is 3600, so 1 hour).



27
28
29
# File 'lib/sequel_model/caching.rb', line 27

def self.set_cache_ttl(ttl)
  @cache_ttl = ttl
end

.set_dataset(ds, opts = {}) ⇒ Object

Sets the dataset associated with the Model class. ds can be a Symbol (specifying a table name in the current database), or a Dataset. If a dataset is used, the model’s database is changed to the given dataset. If a symbol is used, a dataset is created from the current database with the table name given. Other arguments raise an Error.

This sets the model of the the given/created dataset to the current model and adds a destroy method to it. It also extends the dataset with the Associations::EagerLoading methods, and assigns a transform to it if there is one associated with the model. Finally, it attempts to determine the database schema based on the given/created dataset unless lazy_load_schema is set.



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# File 'lib/sequel_model/base.rb', line 317

def self.set_dataset(ds, opts={})
  inherited = opts[:inherited]
  @dataset = case ds
  when Symbol
    db[ds]
  when Dataset
    @db = ds.db
    ds
  else
    raise(Error, "Model.set_dataset takes a Symbol or a Sequel::Dataset")
  end
  @dataset.set_model(self)
  @dataset.transform(@transform) if @transform
  if inherited
    ((@columns = @dataset.columns) rescue nil) unless @@lazy_load_schema
  else
    @dataset.extend(DatasetMethods)
    @dataset.extend(Associations::EagerLoading)
    @dataset_methods.each{|meth, block| @dataset.meta_def(meth, &block)} if @dataset_methods
  end
  ((@db_schema = inherited ? superclass.db_schema : get_db_schema) rescue nil) unless @@lazy_load_schema
  self
end

.set_primary_key(*key) ⇒ Object

Sets primary key, regular and composite are possible.

Example:

class Tagging < Sequel::Model
  # composite key
  set_primary_key :taggable_id, :tag_id
end

class Person < Sequel::Model
  # regular key
  set_primary_key :person_id
end

You can set it to nil to not have a primary key, but that cause certain things not to work, see #no_primary_key.



357
358
359
# File 'lib/sequel_model/base.rb', line 357

def self.set_primary_key(*key)
  @primary_key = (key.length == 1) ? key[0] : key.flatten
end

.set_restricted_columns(*cols) ⇒ Object

Set the columns to restrict in new/set/update. Using this means that any columns listed here will not be modified. If you have any virtual setter methods (methods that end in =) that you want not to be used in new/set/update, they need to be listed here as well (without the =).

It may be better to use (set|update)_except instead of this in places where only certain columns may be allowed.



368
369
370
# File 'lib/sequel_model/base.rb', line 368

def self.set_restricted_columns(*cols)
  @restricted_columns = cols
end

.set_schema(name = nil, &block) ⇒ Object

Defines a table schema (see Schema::Generator for more information).

This is only needed if you want to use the create_table/create_table! methods. Will also set the dataset if you provide a name, as well as setting the primary key if you defined one in the passed block.

In general, it is a better idea to use migrations for production code, as migrations allow changes to existing schema. set_schema is mostly useful for test code or simple examples.



38
39
40
41
42
# File 'lib/sequel_model/schema.rb', line 38

def self.set_schema(name = nil, &block)
  set_dataset(db[name]) if name
  @schema = Schema::Generator.new(db, &block)
  set_primary_key(@schema.primary_key_name) if @schema.primary_key_name
end

.set_sti_key(key) ⇒ Object

Makes this model a polymorphic model with the given key being a string field in the database holding the name of the class to use. If the key given has a NULL value or there are any problems looking up the class, uses the current class.

This should be used to set up single table inheritance for the model, and it only makes sense to use this in the parent class.

You should call sti_key after any calls to set_dataset in the model, otherwise subclasses might not have the filters set up correctly.

The filters that sti_key sets up in subclasses will not work if those subclasses have further subclasses. For those middle subclasses, you will need to call set_dataset manually with the correct filter set.



386
387
388
389
390
391
392
# File 'lib/sequel_model/base.rb', line 386

def self.set_sti_key(key)
  m = self
  @sti_key = key
  @sti_dataset = dataset
  dataset.set_model(key, Hash.new{|h,k| h[k] = (k.constantize rescue m)})
  before_create(:set_sti_key){send("#{key}=", model.name.to_s)}
end

.skip_superclass_validationsObject

Instructs the model to skip validations defined in superclasses



59
60
61
# File 'lib/sequel_model/validations.rb', line 59

def self.skip_superclass_validations
  @skip_superclass_validations = true
end

.str_columnsObject

Returns the columns as a list of frozen strings instead of a list of symbols. This makes it possible to check whether a column exists without creating a symbol, which would be a memory leak if called with user input.



398
399
400
# File 'lib/sequel_model/base.rb', line 398

def self.str_columns
  @str_columns ||= columns.map{|c| c.to_s.freeze}
end

.subset(name, *args, &block) ⇒ Object

Defines a method that returns a filtered dataset. Subsets create dataset methods, so they can be chained for scoping. For example:

Topic.subset(:popular, :num_posts > 100)
Topic.subset(:recent, :created_on > Date.today - 7)

Allows you to do:

Topic.filter(:username.like('%joe%')).popular.recent

to get topics with a username that includes joe that have more than 100 posts and were created less than 7 days ago.



416
417
418
# File 'lib/sequel_model/base.rb', line 416

def self.subset(name, *args, &block)
  def_dataset_method(name){filter(*args, &block)}
end

.table_exists?Boolean

Returns true if table exists, false otherwise.

Returns:

  • (Boolean)


45
46
47
# File 'lib/sequel_model/schema.rb', line 45

def self.table_exists?
  db.table_exists?(table_name)
end

.table_nameObject

Returns name of primary table for the dataset.



421
422
423
# File 'lib/sequel_model/base.rb', line 421

def self.table_name
  dataset.opts[:from].first
end

.unrestrict_primary_keyObject

Allow the setting of the primary key(s) inside new/set/update.



426
427
428
# File 'lib/sequel_model/base.rb', line 426

def self.unrestrict_primary_key
  @restrict_primary_key = false
end

.validate(o) ⇒ Object

Validates the given instance.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/sequel_model/validations.rb', line 85

def self.validate(o)
  if superclass.respond_to?(:validate) && !@skip_superclass_validations
    superclass.validate(o)
  end
  validations.each do |att, procs|
    v = case att
    when Array
      att.collect{|a| o.send(a)}
    else
      o.send(att)
    end
    procs.each {|tag, p| p.call(o, att, v)}
  end
end

.validates(&block) ⇒ Object

Defines validations by converting a longhand block into a series of shorthand definitions. For example:

class MyClass
  include Validation
  validates do
    length_of :name, :minimum => 6
    length_of :password, :minimum => 8
  end
end

is equivalent to:

class MyClass
  include Validation
  validates_length_of :name, :minimum => 6
  validates_length_of :password, :minimum => 8
end


80
81
82
# File 'lib/sequel_model/validations.rb', line 80

def self.validates(&block)
  Validation::Generator.new(self, &block)
end

.validates_acceptance_of(*atts) ⇒ Object

Validates acceptance of an attribute. Just checks that the value is equal to the :accept option.

Possible Options:

  • :accept - The value required for the object to be valid (default: ‘1’)

  • :allow_blank - Whether to skip the validation if the value is blank (default: false)

  • :allow_nil - Whether to skip the validation if the value is nil (default: true)

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :message - The message to use (default: ‘is not accepted’)

  • :tag - The tag to use for this validation (default: :acceptance)



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/sequel_model/validations.rb', line 111

def self.validates_acceptance_of(*atts)
  opts = {
    :message => 'is not accepted',
    :allow_nil => true,
    :accept => '1'
  }.merge!(atts.extract_options!)
  
  atts << {:if=>opts[:if], :tag=>opts[:tag]||:acceptance}
  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
    o.errors[a] << opts[:message] unless v == opts[:accept]
  end
end

.validates_confirmation_of(*atts) ⇒ Object

Validates confirmation of an attribute. Checks that the object has a _confirmation value matching the current value. For example:

validates_confirmation_of :blah

Just makes sure that object.blah = object.blah_confirmation. Often used for passwords or email addresses on web forms.

Possible Options:

  • :allow_false - Whether to skip the validation if the value is blank (default: false)

  • :allow_nil - Whether to skip the validation if the value is nil (default: false)

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :message - The message to use (default: ‘is not confirmed’)

  • :tag - The tag to use for this validation (default: :confirmation)



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/sequel_model/validations.rb', line 140

def self.validates_confirmation_of(*atts)
  opts = {
    :message => 'is not confirmed',
  }.merge!(atts.extract_options!)
 
  atts << {:if=>opts[:if], :tag=>opts[:tag]||:confirmation}
  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
    c = o.send(:"#{a}_confirmation")
    o.errors[a] << opts[:message] unless v == c
  end
end

.validates_each(*atts, &block) ⇒ Object

Adds a validation for each of the given attributes using the supplied block. The block must accept three arguments: instance, attribute and value, e.g.:

validates_each :name, :password do |object, attribute, value|
  object.errors[attribute] << 'is not nice' unless value.nice?
end

Possible Options:

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :tag - The tag to use for this validation (default: nil)



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/sequel_model/validations.rb', line 165

def self.validates_each(*atts, &block)
  opts = atts.extract_options!
  blk = if opts[:if]
    proc{|o,a,v| block.call(o,a,v) if o.instance_eval(&if_proc(opts))}
  else
    block
  end
  tag = opts[:tag]
  atts.each do |a| 
    a_vals = validations[a]
    if tag && (old = a_vals.find{|x| x[0] == tag})
      old[1] = blk
    else
      a_vals << [tag, blk]
    end
  end
end

.validates_format_of(*atts) ⇒ Object

Validates the format of an attribute, checking the string representation of the value against the regular expression provided by the :with option.

Possible Options:

  • :allow_blank - Whether to skip the validation if the value is blank (default: false)

  • :allow_nil - Whether to skip the validation if the value is nil (default: false)

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :message - The message to use (default: ‘is invalid’)

  • :tag - The tag to use for this validation (default: :format)

  • :with - The regular expression to validate the value with (required).



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/sequel_model/validations.rb', line 194

def self.validates_format_of(*atts)
  opts = {
    :message => 'is invalid',
  }.merge!(atts.extract_options!)
  
  unless opts[:with].is_a?(Regexp)
    raise ArgumentError, "A regular expression must be supplied as the :with option of the options hash"
  end
  
  atts << {:if=>opts[:if], :tag=>opts[:tag]||:format}
  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
    o.errors[a] << opts[:message] unless v.to_s =~ opts[:with]
  end
end

.validates_length_of(*atts) ⇒ Object

Validates the length of an attribute.

Possible Options:

  • :allow_blank - Whether to skip the validation if the value is blank (default: false)

  • :allow_nil - Whether to skip the validation if the value is nil (default: false)

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :is - The exact size required for the value to be valid (no default)

  • :maximum - The maximum size allowed for the value (no default)

  • :message - The message to use (no default, overrides :too_long, :too_short, and :wrong_length options if present)

  • :minimum - The minimum size allowed for the value (no default)

  • :tag - The tag to use for this validation (default: :length)

  • :too_long - The message to use use if it the value is too long (default: ‘is too long’)

  • :too_short - The message to use use if it the value is too short (default: ‘is too short’)

  • :with - The array/range that must include the size of the value for it to be valid (no default)

  • :wrong_length - The message to use use if it the value is not valid (default: ‘is the wrong length’)



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/sequel_model/validations.rb', line 227

def self.validates_length_of(*atts)
  opts = {
    :too_long     => 'is too long',
    :too_short    => 'is too short',
    :wrong_length => 'is the wrong length'
  }.merge!(atts.extract_options!)
  
  tag = if opts[:tag]
    opts[:tag]
  else
   ([:length] + [:maximum, :minimum, :is, :within].reject{|x| !opts.include?(x)}).join('-').to_sym
  end
  atts << {:if=>opts[:if], :tag=>tag}
  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
    if m = opts[:maximum]
      o.errors[a] << (opts[:message] || opts[:too_long]) unless v && v.size <= m
    end
    if m = opts[:minimum]
      o.errors[a] << (opts[:message] || opts[:too_short]) unless v && v.size >= m
    end
    if i = opts[:is]
      o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && v.size == i
    end
    if w = opts[:within]
      o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && w.include?(v.size)
    end
  end
end

.validates_numericality_of(*atts) ⇒ Object

Validates whether an attribute is a number.

Possible Options:

  • :allow_blank - Whether to skip the validation if the value is blank (default: false)

  • :allow_nil - Whether to skip the validation if the value is nil (default: false)

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :message - The message to use (default: ‘is not a number’)

  • :tag - The tag to use for this validation (default: :numericality)

  • :only_integer - Whether only integers are valid values (default: false)



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/sequel_model/validations.rb', line 267

def self.validates_numericality_of(*atts)
  opts = {
    :message => 'is not a number',
  }.merge!(atts.extract_options!)
  
  atts << {:if=>opts[:if], :tag=>opts[:tag]||:numericality}
  validates_each(*atts) do |o, a, v|
    next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
    begin
      if opts[:only_integer]
        Kernel.Integer(v.to_s)
      else
        Kernel.Float(v.to_s)
      end
    rescue
      o.errors[a] << opts[:message]
    end
  end
end

.validates_presence_of(*atts) ⇒ Object

Validates the presence of an attribute. Requires the value not be blank, with false considered present instead of absent.

Possible Options:

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :message - The message to use (default: ‘is not present’)

  • :tag - The tag to use for this validation (default: :presence)



295
296
297
298
299
300
301
302
303
304
# File 'lib/sequel_model/validations.rb', line 295

def self.validates_presence_of(*atts)
  opts = {
    :message => 'is not present',
  }.merge!(atts.extract_options!)
  
  atts << {:if=>opts[:if], :tag=>opts[:tag]||:presence}
  validates_each(*atts) do |o, a, v|
    o.errors[a] << opts[:message] if v.blank? && v != false
  end
end

.validates_uniqueness_of(*atts) ⇒ Object

Validates only if the fields in the model (specified by atts) are unique in the database. You should also add a unique index in the database, as this suffers from a fairly obvious race condition.

Possible Options:

  • :allow_nil - Whether to skip the validation if the value(s) is/are nil (default: false)

  • :if - A symbol (indicating an instance_method) or proc (which is instance_evaled) skipping this validation if it returns nil or false.

  • :message - The message to use (default: ‘is already taken’)

  • :tag - The tag to use for this validation (default: :uniqueness)



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/sequel_model/validations.rb', line 316

def self.validates_uniqueness_of(*atts)
  opts = {
    :message => 'is already taken',
  }.merge!(atts.extract_options!)

  atts << {:if=>opts[:if], :tag=>opts[:tag]||:uniqueness}
  validates_each(*atts) do |o, a, v|
    error_field = a
    a = Array(a)
    v = Array(v)
    next unless v.any? or opts[:allow_nil] == false
    ds = o.class.filter(a.zip(v))
    num_dups = ds.count
    allow = if num_dups == 0
      # No unique value in the database
      true
    elsif num_dups > 1
      # Multiple "unique" values in the database!!
      # Someone didn't add a unique index
      false
    elsif o.new?
      # New record, but unique value already exists in the database
      false
    elsif ds.first === o
      # Unique value exists in database, but for the same record, so the update won't cause a duplicate record
      true
    else
      false
    end
    o.errors[error_field] << opts[:message] unless allow
  end
end

.validationsObject

Returns the validations hash for the class.



350
351
352
# File 'lib/sequel_model/validations.rb', line 350

def self.validations
  @validations ||= Hash.new {|h, k| h[k] = []}
end

Instance Method Details

#==(obj) ⇒ Object Also known as: eql?

Compares model instances by values.



95
96
97
# File 'lib/sequel_model/record.rb', line 95

def ==(obj)
  (obj.class == model) && (obj.values == @values)
end

#===(obj) ⇒ Object

If pk is not nil, true only if the objects have the same class and pk. If pk is nil, false.



102
103
104
# File 'lib/sequel_model/record.rb', line 102

def ===(obj)
  pk.nil? ? false : (obj.class == model) && (obj.pk == pk)
end

#[](column) ⇒ Object

Returns value of the column’s attribute.



77
78
79
# File 'lib/sequel_model/record.rb', line 77

def [](column)
  @values[column]
end

#[]=(column, value) ⇒ Object

Sets value of the column’s attribute and marks the column as changed. If the column already has the same value, this is a no-op.



83
84
85
86
87
88
89
90
91
92
# File 'lib/sequel_model/record.rb', line 83

def []=(column, value)
  # If it is new, it doesn't have a value yet, so we should
  # definitely set the new value.
  # If the column isn't in @values, we can't assume it is
  # NULL in the database, so assume it has changed.
  if new? || !@values.include?(column) || value != @values[column]
    @changed_columns << column unless @changed_columns.include?(column)
    @values[column] = typecast_value(column, value)
  end
end

#cache_keyObject

Return a key unique to the underlying record for caching, based on the primary key value(s) for the object. If the model does not have a primary key, raise an Error.

Raises:



64
65
66
67
68
69
70
71
72
73
# File 'lib/sequel_model/caching.rb', line 64

def cache_key
  raise(Error, "No primary key is associated with this model") unless key = primary_key
  pk = case key
  when Array
    key.collect{|k| @values[k]}
  else
    @values[key] || (raise Error, 'no primary key for this record')
  end
  model.send(:cache_key, pk)
end

#deleteObject

Deletes and returns self. Does not run destroy hooks. Look into using destroy instead.



114
115
116
117
118
# File 'lib/sequel_model/record.rb', line 114

def delete
  before_delete
  this.delete
  self
end

#destroyObject

Like delete but runs hooks before and after delete. If before_destroy returns false, returns false without deleting the object the the database. Otherwise, deletes the item from the database and returns self.



124
125
126
127
128
129
130
131
# File 'lib/sequel_model/record.rb', line 124

def destroy
  db.transaction do
    return save_failure(:destroy) if before_destroy == false
    delete
    after_destroy
  end
  self
end

#each(&block) ⇒ Object

Enumerates through all attributes.

Example:

Ticket.find(7).each { |k, v| puts "#{k} => #{v}" }


137
138
139
# File 'lib/sequel_model/record.rb', line 137

def each(&block)
  @values.each(&block)
end

#errorsObject

Returns the validation errors associated with the object.



370
371
372
# File 'lib/sequel_model/validations.rb', line 370

def errors
  @errors ||= Validation::Errors.new
end

#exists?Boolean

Returns true when current instance exists, false otherwise.

Returns:

  • (Boolean)


142
143
144
# File 'lib/sequel_model/record.rb', line 142

def exists?
  this.count > 0
end

#hashObject

Unique for objects with the same class and pk (if pk is not nil), or the same class and values (if pk is nil).



148
149
150
# File 'lib/sequel_model/record.rb', line 148

def hash
  [model, pk.nil? ? @values.sort_by{|k,v| k.to_s} : pk].hash
end

#idObject

Returns value for the :id attribute, even if the primary key is not id. To get the primary key value, use #pk.



154
155
156
# File 'lib/sequel_model/record.rb', line 154

def id
  @values[:id]
end

#inspectObject

Returns a string representation of the model instance including the class name and values.



160
161
162
# File 'lib/sequel_model/record.rb', line 160

def inspect
  "#<#{model.name} @values=#{@values.inspect}>"
end

#keysObject

Returns attribute names as an array of symbols.



165
166
167
# File 'lib/sequel_model/record.rb', line 165

def keys
  @values.keys
end

#new?Boolean

Returns true if the current instance represents a new record.

Returns:

  • (Boolean)


170
171
172
# File 'lib/sequel_model/record.rb', line 170

def new?
  @new
end

#pkObject

Returns the primary key value identifying the model instance. Raises an error if this model does not have a primary key. If the model has a composite primary key, returns an array of values.

Raises:



177
178
179
180
181
182
183
184
185
# File 'lib/sequel_model/record.rb', line 177

def pk
  raise(Error, "No primary key is associated with this model") unless key = primary_key
  case key
  when Array
    key.collect{|k| @values[k]}
  else
    @values[key]
  end
end

#pk_hashObject

Returns a hash identifying the model instance. It should be true that:

Model[model_instance.pk_hash] === model_instance


190
191
192
# File 'lib/sequel_model/record.rb', line 190

def pk_hash
  model.primary_key_hash(pk)
end

#refreshObject Also known as: reload

Reloads attributes from database and returns self. Also clears all cached association information. Raises an Error if the record no longer exists in the database.



197
198
199
200
201
# File 'lib/sequel_model/record.rb', line 197

def refresh
  @values = this.first || raise(Error, "Record not found")
  @associations.clear
  self
end

#save(*columns) ⇒ Object

Creates or updates the record, after making sure the record is valid. If the record is not valid, or before_save, before_create (if new?), or before_update (if !new?) return false, returns nil unless raise_on_save_failure is true (if it is true, it raises an error). Otherwise, returns self. You can provide an optional list of columns to update, in which case it only updates those columns.



211
212
213
214
# File 'lib/sequel_model/record.rb', line 211

def save(*columns)
  return save_failure(:save) unless valid?
  save!(*columns)
end

#save!(*columns) ⇒ Object

Creates or updates the record, without attempting to validate it first. You can provide an optional list of columns to update, in which case it only updates those columns. If before_save, before_create (if new?), or before_update (if !new?) return false, returns nil unless raise_on_save_failure is true (if it is true, it raises an error). Otherwise, returns self.



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/sequel_model/record.rb', line 222

def save!(*columns)
  opts = columns.extract_options!
  return save_failure(:save) if before_save == false
  if @new
    return save_failure(:create) if before_create == false
    ds = model.dataset
    if ds.respond_to?(:insert_select) and h = ds.insert_select(@values)
      @values = h
      @this = nil
    else
      iid = ds.insert(@values)
      # if we have a regular primary key and it's not set in @values,
      # we assume it's the last inserted id
      if (pk = primary_key) && !(Array === pk) && !@values[pk]
        @values[pk] = iid
      end
      if pk
        @this = nil # remove memoized this dataset
        refresh
      end
    end
    @new = false
    after_create
  else
    return save_failure(:update) if before_update == false
    if columns.empty?
      vals = opts[:changed] ? @values.reject{|k,v| !@changed_columns.include?(k)} : @values
      this.update(vals)
      @changed_columns = []
    else # update only the specified columns
      this.update(@values.reject {|k, v| !columns.include?(k)})
      @changed_columns.reject! {|c| columns.include?(c)}
    end
    after_update
  end
  after_save
  self
end

#save_changesObject

Saves only changed columns or does nothing if no columns are marked as chanaged. If no columns have been changed, returns nil. If unable to save, returns false unless raise_on_save_failure is true.



264
265
266
# File 'lib/sequel_model/record.rb', line 264

def save_changes
  save(:changed=>true) || false unless @changed_columns.empty?
end

#set(hash) ⇒ Object Also known as: set_with_params

Updates the instance with the supplied values with support for virtual attributes, raising an exception if a value is used that doesn’t have a setter method (or ignoring it if strict_param_setting = false). Does not save the record.

If no columns have been set for this model (very unlikely), assume symbol keys are valid column names, and assign the column value based on that.



275
276
277
# File 'lib/sequel_model/record.rb', line 275

def set(hash)
  set_restricted(hash, nil, nil)
end

#set_all(hash) ⇒ Object

Set all values using the entries in the hash, ignoring any setting of allowed_columns or restricted columns in the model.



282
283
284
# File 'lib/sequel_model/record.rb', line 282

def set_all(hash)
  set_restricted(hash, false, false)
end

#set_except(hash, *except) ⇒ Object

Set all values using the entries in the hash, except for the keys given in except.



288
289
290
# File 'lib/sequel_model/record.rb', line 288

def set_except(hash, *except)
  set_restricted(hash, false, except.flatten)
end

#set_only(hash, *only) ⇒ Object

Set the values using the entries in the hash, only if the key is included in only.



294
295
296
# File 'lib/sequel_model/record.rb', line 294

def set_only(hash, *only)
  set_restricted(hash, only.flatten, false)
end

#set_values(values) ⇒ Object

Sets the value attributes without saving the record. Returns the values changed. Raises an error if the keys are not symbols or strings or a string key was passed that was not a valid column. This is a low level method that does not respect virtual attributes. It should probably be avoided. Look into using set instead.



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
# File 'lib/sequel_model/record.rb', line 303

def set_values(values)
  s = str_columns
  vals = values.inject({}) do |m, kv| 
    k, v = kv
    k = case k
    when Symbol
      k
    when String
      # Prevent denial of service via memory exhaustion by only 
      # calling to_sym if the symbol already exists.
      raise(Error, "all string keys must be a valid columns") unless s.include?(k)
      k.to_sym
    else
      raise(Error, "Only symbols and strings allows as keys")
    end
    m[k] = v
    m
  end
  vals.each {|k, v| @values[k] = v}
  vals
end

#thisObject

Returns (naked) dataset that should return only this instance.



326
327
328
# File 'lib/sequel_model/record.rb', line 326

def this
  @this ||= dataset.filter(pk_hash).limit(1).naked
end

#update(hash) ⇒ Object Also known as: update_with_params

Runs set with the passed hash and runs save_changes (which runs any callback methods).



331
332
333
# File 'lib/sequel_model/record.rb', line 331

def update(hash)
  update_restricted(hash, nil, nil)
end

#update_all(hash) ⇒ Object

Update all values using the entries in the hash, ignoring any setting of allowed_columns or restricted columns in the model.



338
339
340
# File 'lib/sequel_model/record.rb', line 338

def update_all(hash)
  update_restricted(hash, false, false)
end

#update_except(hash, *except) ⇒ Object

Update all values using the entries in the hash, except for the keys given in except.



344
345
346
# File 'lib/sequel_model/record.rb', line 344

def update_except(hash, *except)
  update_restricted(hash, false, except.flatten)
end

#update_only(hash, *only) ⇒ Object

Update the values using the entries in the hash, only if the key is included in only.



350
351
352
# File 'lib/sequel_model/record.rb', line 350

def update_only(hash, *only)
  update_restricted(hash, only.flatten, false)
end

#update_values(values) ⇒ Object

Sets the values attributes with set_values and then updates the record in the database using those values. This is a low level method that does not run the usual save callbacks. It should probably be avoided. Look into using update_with_params instead.



358
359
360
361
# File 'lib/sequel_model/record.rb', line 358

def update_values(values)
  before_update_values
  this.update(set_values(values))
end

#valid?Boolean

Validates the object and returns true if no errors are reported.

Returns:

  • (Boolean)


384
385
386
387
# File 'lib/sequel_model/validations.rb', line 384

def valid?
  return false if validate == false
  errors.empty?
end

#validateObject

Validates the object.



375
376
377
378
379
380
381
# File 'lib/sequel_model/validations.rb', line 375

def validate
  errors.clear
  return false if before_validation == false
  self.class.validate(self)
  after_validation
  nil
end