| Module | Sequel::Model::Associations::ClassMethods |
| In: |
lib/sequel/model/associations.rb
|
Each kind of association adds a number of instance methods to the model class which are specialized according to the association type and optional parameters given in the definition. Example:
class Project < Sequel::Model
many_to_one :portfolio
one_to_many :milestones
# or: many_to_many :milestones
end
The project class now has the following instance methods:
If you want to override the behavior of the add_/remove_/remove_all_ methods, there are private instance methods created that a prepended with an underscore (e.g. _add_milestone). The private instance methods can be easily overridden, but you shouldn‘t override the public instance methods without calling super, as they deal with callbacks and caching.
By default the classes for the associations are inferred from the association name, so for example the Project#portfolio will return an instance of Portfolio, and Project#milestones will return an array of Milestone instances.
Association definitions are also reflected by the class, e.g.:
Project.associations
=> [:portfolio, :milestones]
Project.association_reflection(:portfolio)
=> {:type => :many_to_one, :name => :portfolio, :class_name => "Portfolio"}
| association_reflections | [R] | All association reflections defined for this model (default: none). |
Associates a related model with the current model. The following types are supported:
A one to one relationship can be set up with a many_to_one association on the table with the foreign key, and a one_to_many association with the :one_to_one option specified on the table without the foreign key. The two associations will operate similarly, except that the many_to_one association setter doesn‘t update the database until you call save manually. Also, in most cases you need to specify the plural association name when using one_to_many with the :one_to_one option.
The following options can be supplied:
# File lib/sequel/model/associations.rb, line 585
585: def associate(type, name, opts = {}, &block)
586: raise(Error, 'invalid association type') unless assoc_class = ASSOCIATION_TYPES[type]
587: raise(Error, 'Model.associate name argument must be a symbol') unless Symbol === name
588:
589: # merge early so we don't modify opts
590: orig_opts = opts.dup
591: orig_opts = association_reflection(opts[:clone])[:orig_opts].merge(orig_opts) if opts[:clone]
592: opts = orig_opts.merge(:type => type, :name => name, :cache => true, :model => self)
593: opts[:block] = block if block
594: opts = assoc_class.new.merge!(opts)
595: opts[:eager_block] = block unless opts.include?(:eager_block)
596: opts[:graph_join_type] ||= :left_outer
597: opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
598: conds = opts[:conditions]
599: opts[:graph_conditions] = conds if !opts.include?(:graph_conditions) and Sequel.condition_specifier?(conds)
600: opts[:graph_conditions] = opts[:graph_conditions] ? opts[:graph_conditions].to_a : []
601: opts[:graph_select] = Array(opts[:graph_select]) if opts[:graph_select]
602: [:before_add, :before_remove, :after_add, :after_remove, :after_load, :extend].each do |cb_type|
603: opts[cb_type] = Array(opts[cb_type])
604: end
605:
606: # find class
607: case opts[:class]
608: when String, Symbol
609: # Delete :class to allow late binding
610: opts[:class_name] ||= opts.delete(:class).to_s
611: when Class
612: opts[:class_name] ||= opts[:class].name
613: end
614: opts[:class_name] ||= ((self.name || '').split("::")[0..-2] + [camelize(opts.returns_array? ? singularize(name) : name)]).join('::')
615:
616: send("def_#{type}""def_#{type}", opts)
617:
618: orig_opts.delete(:clone)
619: orig_opts.merge!(:class_name=>opts[:class_name], :class=>opts[:class], :block=>block)
620: opts[:orig_opts] = orig_opts
621: # don't add to association_reflections until we are sure there are no errors
622: association_reflections[name] = opts
623: end
The association reflection hash for the association of the given name.
# File lib/sequel/model/associations.rb, line 626
626: def association_reflection(name)
627: association_reflections[name]
628: end
Modify and return eager loading dataset based on association options. Options:
# File lib/sequel/model/associations.rb, line 636
636: def eager_loading_dataset(opts, ds, select, associations)
637: ds = ds.select(*select) if select
638: if c = opts[:conditions]
639: ds = (c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.filter(*c) : ds.filter(c)
640: end
641: ds = ds.order(*opts[:order]) if opts[:order]
642: ds = ds.eager(opts[:eager]) if opts[:eager]
643: ds = ds.distinct if opts[:distinct]
644: if opts[:eager_graph]
645: ds = ds.eager_graph(opts[:eager_graph])
646: ds = ds.add_graph_aliases(opts.associated_key_alias=>[opts.associated_class.table_name, opts.associated_key_alias, SQL::QualifiedIdentifier.new(opts.associated_key_table, opts.associated_key_column)]) if opts.eager_loading_use_associated_key?
647: elsif opts.eager_loading_use_associated_key?
648: ds = if opts[:uses_left_composite_keys]
649: t = opts.associated_key_table
650: ds.select_more(*opts.associated_key_alias.zip(opts.associated_key_column).map{|a, c| SQL::AliasedExpression.new(SQL::QualifiedIdentifier.new(t, c), a)})
651: else
652: ds.select_more(SQL::AliasedExpression.new(SQL::QualifiedIdentifier.new(opts.associated_key_table, opts.associated_key_column), opts.associated_key_alias))
653: end
654: end
655: ds = ds.eager(associations) unless Array(associations).empty?
656: ds = opts[:eager_block].call(ds) if opts[:eager_block]
657: ds
658: end
Copy the association reflections to the subclass
# File lib/sequel/model/associations.rb, line 661
661: def inherited(subclass)
662: super
663: subclass.instance_variable_set(:@association_reflections, @association_reflections.dup)
664: end
Shortcut for adding a many_to_many association, see associate
# File lib/sequel/model/associations.rb, line 667
667: def many_to_many(*args, &block)
668: associate(:many_to_many, *args, &block)
669: end
Shortcut for adding a many_to_one association, see associate
# File lib/sequel/model/associations.rb, line 672
672: def many_to_one(*args, &block)
673: associate(:many_to_one, *args, &block)
674: end
Shortcut for adding a one_to_many association, see associate
# File lib/sequel/model/associations.rb, line 677
677: def one_to_many(*args, &block)
678: associate(:one_to_many, *args, &block)
679: end