Froze rails gems
[depot.git] / vendor / rails / activerecord / lib / active_record / associations / has_one_association.rb
1 module ActiveRecord
2 module Associations
3 class HasOneAssociation < BelongsToAssociation #:nodoc:
4 def initialize(owner, reflection)
5 super
6 construct_sql
7 end
8
9 def create(attrs = {}, replace_existing = true)
10 new_record(replace_existing) do |reflection|
11 reflection.create_association(attrs)
12 end
13 end
14
15 def create!(attrs = {}, replace_existing = true)
16 new_record(replace_existing) do |reflection|
17 reflection.create_association!(attrs)
18 end
19 end
20
21 def build(attrs = {}, replace_existing = true)
22 new_record(replace_existing) do |reflection|
23 reflection.build_association(attrs)
24 end
25 end
26
27 def replace(obj, dont_save = false)
28 load_target
29
30 unless @target.nil? || @target == obj
31 if dependent? && !dont_save
32 @target.destroy unless @target.new_record?
33 @owner.clear_association_cache
34 else
35 @target[@reflection.primary_key_name] = nil
36 @target.save unless @owner.new_record? || @target.new_record?
37 end
38 end
39
40 if obj.nil?
41 @target = nil
42 else
43 raise_on_type_mismatch(obj)
44 set_belongs_to_association_for(obj)
45 @target = (AssociationProxy === obj ? obj.target : obj)
46 end
47
48 @loaded = true
49
50 unless @owner.new_record? or obj.nil? or dont_save
51 return (obj.save ? self : false)
52 else
53 return (obj.nil? ? nil : self)
54 end
55 end
56
57 protected
58 def owner_quoted_id
59 if @reflection.options[:primary_key]
60 @owner.class.quote_value(@owner.send(@reflection.options[:primary_key]))
61 else
62 @owner.quoted_id
63 end
64 end
65
66 private
67 def find_target
68 @reflection.klass.find(:first,
69 :conditions => @finder_sql,
70 :select => @reflection.options[:select],
71 :order => @reflection.options[:order],
72 :include => @reflection.options[:include],
73 :readonly => @reflection.options[:readonly]
74 )
75 end
76
77 def construct_sql
78 case
79 when @reflection.options[:as]
80 @finder_sql =
81 "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
82 "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
83 else
84 @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
85 end
86 @finder_sql << " AND (#{conditions})" if conditions
87 end
88
89 def construct_scope
90 create_scoping = {}
91 set_belongs_to_association_for(create_scoping)
92 { :create => create_scoping }
93 end
94
95 def new_record(replace_existing)
96 # Make sure we load the target first, if we plan on replacing the existing
97 # instance. Otherwise, if the target has not previously been loaded
98 # elsewhere, the instance we create will get orphaned.
99 load_target if replace_existing
100 record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) do
101 yield @reflection
102 end
103
104 if replace_existing
105 replace(record, true)
106 else
107 record[@reflection.primary_key_name] = @owner.id unless @owner.new_record?
108 self.target = record
109 end
110
111 record
112 end
113 end
114 end
115 end