Instance methods used to implement the associations support.
The currently 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).
# File lib/sequel/model/associations.rb, line 1398 1398: def associations 1399: @associations ||= {} 1400: end
Freeze the associations cache when freezing the object. Note that retrieving associations after freezing will still work in most cases, but the associations will not be cached in the association cache.
# File lib/sequel/model/associations.rb, line 1405 1405: def freeze 1406: associations.freeze 1407: super 1408: end
Formally used internally by the associations code, like pk but doesn’t raise an Error if the model has no primary key. Not used any longer, deprecated.
# File lib/sequel/model/associations.rb, line 1412 1412: def pk_or_nil 1413: key = primary_key 1414: key.is_a?(Array) ? key.map{|k| @values[k]} : @values[key] 1415: end
Apply the association options such as :order and :limit to the given dataset, returning a modified dataset.
# File lib/sequel/model/associations.rb, line 1420 1420: def _apply_association_options(opts, ds) 1421: ds.extend(AssociationDatasetMethods) 1422: ds.model_object = self 1423: ds.association_reflection = opts 1424: opts[:extend].each{|m| ds.extend(m)} 1425: ds = ds.select(*opts.select) if opts.select 1426: if c = opts[:conditions] 1427: ds = (c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.filter(*c) : ds.filter(c) 1428: end 1429: ds = ds.order(*opts[:order]) if opts[:order] 1430: ds = ds.limit(*opts[:limit]) if opts[:limit] 1431: ds = ds.limit(1) if !opts.returns_array? && opts[:key] 1432: ds = ds.eager(*opts[:eager]) if opts[:eager] 1433: ds = ds.distinct if opts[:distinct] 1434: ds = ds.eager_graph(opts[:eager_graph]) if opts[:eager_graph] && opts.eager_graph_lazy_dataset? 1435: ds = send(opts.dataset_helper_method, ds) if opts[:block] 1436: ds 1437: end
Return a dataset for the association after applying any dynamic callback.
# File lib/sequel/model/associations.rb, line 1440 1440: def _associated_dataset(opts, dynamic_opts) 1441: ds = send(opts.dataset_method) 1442: if callback = dynamic_opts[:callback] 1443: ds = callback.call(ds) 1444: end 1445: ds 1446: end
Return an association dataset for the given association reflection
# File lib/sequel/model/associations.rb, line 1449 1449: def _dataset(opts) 1450: raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk 1451: _apply_association_options(opts, send(opts._dataset_method)) 1452: end
Dataset for the join table of the given many to many association reflection
# File lib/sequel/model/associations.rb, line 1455 1455: def _join_table_dataset(opts) 1456: ds = model.db.from(opts.join_table_source) 1457: opts[:join_table_block] ? opts[:join_table_block].call(ds) : ds 1458: end
Return the associated single object for the given association reflection and dynamic options (or nil if no associated object).
# File lib/sequel/model/associations.rb, line 1462 1462: def _load_associated_object(opts, dynamic_opts) 1463: _load_associated_object_array(opts, dynamic_opts).first 1464: end
Load the associated objects for the given association reflection and dynamic options as an array.
# File lib/sequel/model/associations.rb, line 1468 1468: def _load_associated_object_array(opts, dynamic_opts) 1469: _associated_dataset(opts, dynamic_opts).all 1470: end
Return the associated objects from the dataset, without association callbacks, reciprocals, and caching. Still apply the dynamic callback if present.
# File lib/sequel/model/associations.rb, line 1474 1474: def _load_associated_objects(opts, dynamic_opts={}) 1475: if opts.can_have_associated_objects?(self) 1476: if opts.returns_array? 1477: _load_associated_object_array(opts, dynamic_opts) 1478: else 1479: _load_associated_object(opts, dynamic_opts) 1480: end 1481: else 1482: [] if opts.returns_array? 1483: end 1484: end
Clear the associations cache when refreshing
# File lib/sequel/model/associations.rb, line 1487 1487: def _refresh(dataset) 1488: associations.clear 1489: super 1490: end
Set the given object as the associated object for the given *_to_one association reflection
# File lib/sequel/model/associations.rb, line 1648 1648: def _set_associated_object(opts, o) 1649: a = associations[opts[:name]] 1650: return if a && a == o && !set_associated_object_if_same? 1651: run_association_callbacks(opts, :before_set, o) 1652: remove_reciprocal_object(opts, a) if a 1653: send(opts._setter_method, o) 1654: associations[opts[:name]] = o 1655: add_reciprocal_object(opts, o) if o 1656: run_association_callbacks(opts, :after_set, o) 1657: o 1658: end
Add the given associated object to the given association
# File lib/sequel/model/associations.rb, line 1493 1493: def add_associated_object(opts, o, *args) 1494: klass = opts.associated_class 1495: if o.is_a?(Hash) 1496: o = klass.new(o) 1497: elsif o.is_a?(Integer) || o.is_a?(String) || o.is_a?(Array) 1498: o = klass[o] 1499: elsif !o.is_a?(klass) 1500: raise(Sequel::Error, "associated object #{o.inspect} not of correct type #{klass}") 1501: end 1502: raise(Sequel::Error, "model object #{inspect} does not have a primary key") unless pk 1503: ensure_associated_primary_key(opts, o, *args) 1504: return if run_association_callbacks(opts, :before_add, o) == false 1505: send(opts._add_method, o, *args) 1506: if array = associations[opts[:name]] and !array.include?(o) 1507: array.push(o) 1508: end 1509: add_reciprocal_object(opts, o) 1510: run_association_callbacks(opts, :after_add, o) 1511: o 1512: end
Add/Set the current object to/as the given object’s reciprocal association.
# File lib/sequel/model/associations.rb, line 1515 1515: def add_reciprocal_object(opts, o) 1516: return if o.frozen? 1517: return unless reciprocal = opts.reciprocal 1518: if opts.reciprocal_array? 1519: if array = o.associations[reciprocal] and !array.include?(self) 1520: array.push(self) 1521: end 1522: else 1523: o.associations[reciprocal] = self 1524: end 1525: end
Call uniq! on the given array. This is used by the :uniq option, and is an actual method for memory reasons.
# File lib/sequel/model/associations.rb, line 1529 1529: def array_uniq!(a) 1530: a.uniq! 1531: end
Save the associated object if the associated object needs a primary key and the associated object is new and does not have one. Raise an error if the object still does not have a primary key
# File lib/sequel/model/associations.rb, line 1536 1536: def ensure_associated_primary_key(opts, o, *args) 1537: if opts.need_associated_primary_key? 1538: o.save(:validate=>opts[:validate]) if o.new? 1539: raise(Sequel::Error, "associated object #{o.inspect} does not have a primary key") unless o.pk 1540: end 1541: end
Load the associated objects using the dataset, handling callbacks, reciprocals, and caching.
# File lib/sequel/model/associations.rb, line 1544 1544: def load_associated_objects(opts, dynamic_opts=nil) 1545: if dynamic_opts == true or dynamic_opts == false or dynamic_opts == nil 1546: dynamic_opts = {:reload=>dynamic_opts} 1547: elsif dynamic_opts.respond_to?(:call) 1548: dynamic_opts = {:callback=>dynamic_opts} 1549: end 1550: if block_given? 1551: dynamic_opts = dynamic_opts.merge(:callback=>Proc.new) 1552: end 1553: name = opts[:name] 1554: if associations.include?(name) and !dynamic_opts[:callback] and !dynamic_opts[:reload] 1555: associations[name] 1556: else 1557: objs = _load_associated_objects(opts, dynamic_opts) 1558: if opts.set_reciprocal_to_self? 1559: if opts.returns_array? 1560: objs.each{|o| add_reciprocal_object(opts, o)} 1561: elsif objs 1562: add_reciprocal_object(opts, objs) 1563: end 1564: end 1565: 1566: # If the current object is frozen, you can't update the associations 1567: # cache. This can cause issues for after_load procs that expect 1568: # the objects to be already cached in the associations, but 1569: # unfortunately that case cannot be handled. 1570: associations[name] = objs unless frozen? 1571: run_association_callbacks(opts, :after_load, objs) 1572: frozen? ? objs : associations[name] 1573: end 1574: end
Remove all associated objects from the given association
# File lib/sequel/model/associations.rb, line 1577 1577: def remove_all_associated_objects(opts, *args) 1578: raise(Sequel::Error, "model object #{inspect} does not have a primary key") unless pk 1579: send(opts._remove_all_method, *args) 1580: ret = associations[opts[:name]].each{|o| remove_reciprocal_object(opts, o)} if associations.include?(opts[:name]) 1581: associations[opts[:name]] = [] 1582: ret 1583: end
Remove the given associated object from the given association
# File lib/sequel/model/associations.rb, line 1586 1586: def remove_associated_object(opts, o, *args) 1587: klass = opts.associated_class 1588: if o.is_a?(Integer) || o.is_a?(String) || o.is_a?(Array) 1589: o = remove_check_existing_object_from_pk(opts, o, *args) 1590: elsif !o.is_a?(klass) 1591: raise(Sequel::Error, "associated object #{o.inspect} not of correct type #{klass}") 1592: elsif opts.remove_should_check_existing? && send(opts.dataset_method).filter(o.pk_hash).empty? 1593: raise(Sequel::Error, "associated object #{o.inspect} is not currently associated to #{inspect}") 1594: end 1595: raise(Sequel::Error, "model object #{inspect} does not have a primary key") unless pk 1596: raise(Sequel::Error, "associated object #{o.inspect} does not have a primary key") if opts.need_associated_primary_key? && !o.pk 1597: return if run_association_callbacks(opts, :before_remove, o) == false 1598: send(opts._remove_method, o, *args) 1599: associations[opts[:name]].delete_if{|x| o === x} if associations.include?(opts[:name]) 1600: remove_reciprocal_object(opts, o) 1601: run_association_callbacks(opts, :after_remove, o) 1602: o 1603: end
Check that the object from the associated table specified by the primary key is currently associated to the receiver. If it is associated, return the object, otherwise raise an error.
# File lib/sequel/model/associations.rb, line 1608 1608: def remove_check_existing_object_from_pk(opts, o, *args) 1609: key = o 1610: pkh = opts.associated_class.qualified_primary_key_hash(key) 1611: raise(Sequel::Error, "no object with key(s) #{key.inspect} is currently associated to #{inspect}") unless o = send(opts.dataset_method).first(pkh) 1612: o 1613: end
Remove/unset the current object from/as the given object’s reciprocal association.
# File lib/sequel/model/associations.rb, line 1616 1616: def remove_reciprocal_object(opts, o) 1617: return unless reciprocal = opts.reciprocal 1618: if opts.reciprocal_array? 1619: if array = o.associations[reciprocal] 1620: array.delete_if{|x| self === x} 1621: end 1622: else 1623: o.associations[reciprocal] = nil 1624: end 1625: end
Run the callback for the association with the object.
# File lib/sequel/model/associations.rb, line 1628 1628: def run_association_callbacks(reflection, callback_type, object) 1629: raise_error = raise_on_save_failure || !reflection.returns_array? 1630: stop_on_false = [:before_add, :before_remove, :before_set].include?(callback_type) 1631: reflection[callback_type].each do |cb| 1632: res = case cb 1633: when Symbol 1634: send(cb, object) 1635: when Proc 1636: cb.call(self, object) 1637: else 1638: raise Error, "callbacks should either be Procs or Symbols" 1639: end 1640: if res == false and stop_on_false 1641: raise(BeforeHookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false") if raise_error 1642: return false 1643: end 1644: end 1645: end
Set the given object as the associated object for the given many_to_one association reflection
# File lib/sequel/model/associations.rb, line 1668 1668: def set_associated_object(opts, o) 1669: raise(Error, "associated object #{o.inspect} does not have a primary key") if o && !o.pk 1670: _set_associated_object(opts, o) 1671: end
Whether run the associated object setter code if passed the same object as the one already cached in the association. Usually not set (so nil), can be set on a per-object basis if necessary.
# File lib/sequel/model/associations.rb, line 1663 1663: def set_associated_object_if_same? 1664: @set_associated_object_if_same 1665: end
Set the given object as the associated object for the given one_to_one association reflection
# File lib/sequel/model/associations.rb, line 1674 1674: def set_one_to_one_associated_object(opts, o) 1675: raise(Error, "object #{inspect} does not have a primary key") unless pk 1676: _set_associated_object(opts, o) 1677: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.