has_one
- 1.0.0 (0)
- 1.1.6 (5)
- 1.2.6 (7)
- 2.0.3 (1)
- 2.1.0 (38)
- 2.2.1 (14)
- 2.3.8 (7)
- 3.0.0 (14)
- 3.0.9 (-6)
- 3.1.0 (5)
- 3.2.1 (4)
- 3.2.8 (0)
- 3.2.13 (0)
- 4.0.2 (-23)
- 4.1.8 (4)
- 4.2.1 (27)
- 4.2.7 (0)
- 4.2.9 (0)
- 5.0.0.1 (5)
- 5.1.7 (3)
- 5.2.3 (5)
- 6.0.0 (3)
- 6.1.3.1 (19)
- 6.1.7.7 (0)
- 7.0.0 (26)
- 7.1.3.2 (33)
- 7.1.3.4 (0)
- What's this?
has_one(association_id, options = {})
public
Specifies a one-to-one association with another class. This method should only be used if the other class contains the foreign key. If the current class contains the foreign key, then you should use belongs_to instead. See also ActiveRecord::Associations::ClassMethods’s overview on when to use has_one and when to use belongs_to.
The following methods for retrieval and query of a single associated object will be added:
- association(force_reload = false)
-
Returns the associated object. nil is returned if none is found.
- association=(associate)
-
Assigns the associate object, extracts the primary key, sets it as the foreign key, and saves the associate object.
- build_association(attributes = {})
-
Returns a new object of the associated type that has been instantiated with attributes and linked to this object through a foreign key, but has not yet been saved. Note: This ONLY works if an association already exists. It will NOT work if the association is nil.
- create_association(attributes = {})
-
Returns a new object of the associated type that has been instantiated with attributes, linked to this object through a foreign key, and that has already been saved (if it passed the validation).
(association is replaced with the symbol passed as the first argument, so has_one :manager would add among others manager.nil?.)
Example
An Account class declares has_one :beneficiary, which will add:
-
Account#beneficiary (similar to Beneficiary.find(:first, :conditions => "account_id = #{id}"))
-
Account#beneficiary=(beneficiary) (similar to beneficiary.account_id = account.id; beneficiary.save)
-
Account#build_beneficiary (similar to Beneficiary.new("account_id" => id))
-
Account#create_beneficiary (similar to b = Beneficiary.new("account_id" => id); b.save; b)
Options
The declaration can also include an options hash to specialize the behavior of the association.
Options are:
- :class_name
-
Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So has_one :manager will by default be linked to the Manager class, but if the real class name is Person, you’ll have to specify it with this option.
- :conditions
-
Specify the conditions that the associated object must meet in order to be included as a WHERE SQL fragment, such as rank = 5. Record creation from the association is scoped if a hash is used. has_one :account, :conditions => {:enabled => true} will create an enabled account with @company.create_account or @company.build_account.
- :order
-
Specify the order in which the associated objects are returned as an ORDER BY SQL fragment, such as last_name, first_name DESC.
- :dependent
-
If set to :destroy, the associated object is destroyed when this object is. If set to :delete, the associated object is deleted without calling its destroy method. If set to :nullify, the associated object’s foreign key is set to NULL. Also, association is assigned.
- :foreign_key
-
Specify the foreign key used for the association. By default this is guessed to be the name of this class in lower-case and “_id” suffixed. So a Person class that makes a has_one association will use “person_id” as the default :foreign_key.
- :primary_key
-
Specify the method that returns the primary key used for the association. By default this is id.
- :include
-
Specify second-order associations that should be eager loaded when this object is loaded.
- :as
-
Specifies a polymorphic interface (See belongs_to).
- :select
-
By default, this is * as in SELECT * FROM, but can be changed if, for example, you want to do a join but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
- :through
-
Specifies a Join Model through which to perform the query. Options for :class_name and :foreign_key are ignored, as the association uses the source reflection. You can only use a :through query through a has_one or belongs_to association on the join model.
- :source
-
Specifies the source association name used by has_one :through queries. Only use it if the name cannot be inferred from the association. has_one :favorite, :through => :favorites will look for a :favorite on Favorite, unless a :source is given.
- :source_type
-
Specifies type of the source association used by has_one :through queries where the source association is a polymorphic belongs_to.
- :readonly
-
If true, the associated object is readonly through the association.
- :validate
-
If false, don’t validate the associated object when saving the parent object. false by default.
- :autosave
-
If true, always save the associated object or destroy it if marked for destruction, when saving the parent object. If false, never save or destroy the associated object. By default, only save the associated object if it’s a new record.
- :inverse_of
-
Specifies the name of the belongs_to association on the associated object that is the inverse of this has_one association. Does not work in combination with :through or :as options. See ActiveRecord::Associations::ClassMethods’s overview on Bi-directional associations for more detail.
Option examples:
has_one :credit_card, :dependent => :destroy # destroys the associated credit card has_one :credit_card, :dependent => :nullify # updates the associated records foreign # key value to NULL rather than destroying it has_one :last_comment, :class_name => "Comment", :order => "posted_on" has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'" has_one :attachment, :as => :attachable has_one :boss, :readonly => :true has_one :club, :through => :membership has_one :primary_address, :through => :addressables, :conditions => ["addressable.primary = ?", true], :source => :addressable
Undocumented :inverse_of option
Support for the :inverse_of option was backported to 2.3.6+.
Here’s the description from the original commit: http://github.com/rails/rails/commit/ccea98389abbf150b886c9f964b1def47f00f237
You can now add an :inverse_of option to has_one, has_many and belongs_to associations. This is best described with an example:
class Man < ActiveRecord::Base has_one :face, :inverse_of => :man end class Face < ActiveRecord::Base belongs_to :man, :inverse_of => :face end m = Man.first f = m.face
Without :inverse_of m and f.man would be different instances of the same object (f.man being pulled from the database again). With these new :inverse_of options m and f.man are the same in memory instance.
Currently :inverse_of supports has_one and has_many (but not the :through variants) associations. It also supplies inverse support for belongs_to associations where the inverse is a has_one and it’s not a polymorphic.
Support for the option through
class Magazine < ActiveRecord::Base
has_many :subscriptions end class Subscription < ActiveRecord::Base belongs_to :magazine belongs_to :user end class User < ActiveRecord::Base has_many :subscriptions has_one :magazine, :through => :subscriptions, :conditions => ['subscriptions.active = ?', true] end
build_association deletes existing dependent record
Surprisingly (at least I was surprised), when an associated record exists, the build_association method immediately NULLs the foreign key in the database.
So if you write a singleton “new” action for the association in the obvious way (calling build_association), then just visiting the page will disconnect an existing associated record. This violates the principle that a GET request shouldn’t affect the database.
To avoid this, you can check for an existing association first, and redirect to the show action.
has_one through belongs_to not working
code example:
class Company < ActiveRecord::Base has_many :route_lists end class RouteList < ActiveRecord::Base belongs_to :company has_many :routes end class Route < ActiveRecord::Base belongs_to :route_list has_one :company :through => :route_list end
This creates an invalid SQL query, where the keys in the join between route and routelist are switched, when used as an include:
Routes.find :all, :conditions => ["companies.type = ?", "Account"], :include => :company
route_lists.route_list_id = route.id
instead of: route_lists.id = route.route_list_id