Module: Citier4::ChildInstanceMethods

Includes:
InstanceMethods
Defined in:
lib/citier4/child_instance_methods.rb

Instance Method Summary collapse

Methods included from InstanceMethods

#attributes_for_current, #attributes_for_parent, #changed_attributes_for_current, #changed_attributes_for_parent, included

Instance Method Details

#becomes_superObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/citier4/child_instance_methods.rb', line 6

def becomes_super
  keys = self.class.superclass.attribute_names.dup  # car sinon, c'est la même référence
  keys.delete(self.class.inheritance_column)
  parent = self.class.superclass.new self.attributes.slice(*keys)
  
  # parent = self.class.superclass.new
  parent.id = self.id # nul if create, a real id otherwise
  parent.clear_changes_information 
  # Natural Rail STI process, in new, change the "type" colomn from nil to "class.superclass.name"
  # so we have a flaged change for this "type" colomun.
  # And we have to clear these change
  # Clear all changes is more simple and probably more efficient that a specific clear on the STI "type" column
  # like the line bellow
  # parent.clear_attribute_change(parent.class.inheritance_column)
  parent.force_attributes(attributes_for_parent)
  # parent.force_attributes(attributes_for_parent, :merge => true)
  # parent = self.class.superclass.new self.changed_attributes_for_parent
  # these doen't work, because parent.class IS NOT self.superclass, but self.class
  # sinon, TODO, pourquoi descendre en superclass. Il faut sauter et aller a la prochaine superclass dure ...
  parent.is_new_record(self.new_record?)
  parent.force_changed_attributes(changed_attributes_for_parent)
  parent
end

#save(options = {}) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/citier4/child_instance_methods.rb', line 30

def save(options={})
  return false if (options[:validate] != false && !self.valid?)

  #citier_debug("Callback (#{self.inspect})")
  citier_debug("SAVING #{self.class.to_s}")

  #AIT NOTE: Will change any protected values back to original values so any models onwards won't see changes.
  # Run save and create/update callbacks, just like ActiveRecord does
  self.run_callbacks(:save) do
    self.run_callbacks(self.new_record? ? :create : :update) do
      
      # changed_attributes_for_parent = self.changed_attributes.reject { |key,value| !self.class.superclass.column_names.include?(key) }

      # Get the attributes of the class which are unique to this class and not inherited.
      #attributes_for_current = self.attributes.reject { |key,value| self.class.superclass.column_names.include?(key) }
      #changed_attributes_for_current = self.changed_attributes.reject { |key,value| self.class.superclass.column_names.include?(key) }

      # debugger
      citier_debug("Attributes for #{self.class.superclass.to_s}: #{attributes_for_parent.inspect}")
      citier_debug("Changed attributes for #{self.class.superclass.to_s}: #{changed_attributes_for_parent.keys.inspect}")
      citier_debug("Attributes for #{self.class.to_s}: #{attributes_for_current.inspect}")
      citier_debug("Changed attributes for #{self.class.to_s}: #{changed_attributes_for_current.keys.inspect}")

      ########
      #
      # Parent saving

      #create a new instance of the superclass, passing the inherited attributes.
      # It is not good : new start callback, like after_initialise, and we doen't want to lauch such callback
     
      #parent1 = self.class.superclass.new 
      #parent1.id = self.id # nul if create, a real id otherwise
      #parent1.clear_changes_information 
      #parent1.force_attributes(attributes_for_parent)
      #parent1.is_new_record(self.new_record?)  
      #parent1.force_changed_attributes(changed_attributes_for_parent)
    
      parent = self.becomes_super
      # parent = parent2
      # If we're root this will just be saved as normal through AR. If we're a child it will call this method again. 
      # It will try and save it's parent and then save itself through the Writeable constant.
      # For a new record, we will have an id, only when the root is saved.
    
      parent_saved = parent.save
     #  self.id = parent.id

      if !parent_saved
        # Couldn't save parent class
        citier_debug("Class (#{self.class.superclass.to_s}) could not be saved")
        citier_debug("Errors = #{parent.errors.to_s}")
        return false # Return false and exit run_callbacks :save and :create/:update, so the after_ callback won't run.
      end
      ###### End of parent saving #####
      ###### Self Saving
      # If there are attributes for the current class (unique & not inherited), save current model
      # attention, si aucun attribut pour le parent, mais que on est en new_record
      # il faut quand meme sauver le current. DOTO Faire un test.
      if !attributes_for_current.empty?
       # ici, parrent est sauvé, et on a un ID
      current = self.class::Writeable.new
      # current.force_attributes(attributes_for_current, :merge => true)
      current.force_attributes(attributes_for_current)
        # marche pas non plus current = self.class::Writeable.new attributes_for_current
        
      current.force_changed_attributes(changed_attributes_for_current)
    
        # current.id = self.id  # NON
        current.id = parent.id
        current.is_new_record(new_record?)
        clear_attribute_changes(:id) if !current.new_record?
  
        current_saved = current.save
        
        current.after_save_change_request if current.respond_to?('after_save_change_request') #Specific to an app I'm building

        if !current_saved
          citier_debug("Class (#{self.class.superclass.to_s}) could not be saved")
          citier_debug("Errors = #{current.errors.to_s}")
          return false # Return false and exit run_callbacks :save and :create/:update, so the after callback won't run.
        end
      end  

      # at this point, parent_saved && current_saved 
    
      # if self.class.name == self.attributes[self.class.inheritance_column]  
          is_new_record(false) # This is no longer a new record
          #self.force_changed_attributes({}) # Reset changed_attributes so future changes will be tracked correctly
          self.id = parent.id
          self.clear_changes_information
      # end
      # No return, because we want the after callback to run.
    end
  end
  return true
end

#save!(options = {}) ⇒ Object

Raises:

  • (ActiveRecord::RecordInvalid)


126
127
128
129
# File 'lib/citier4/child_instance_methods.rb', line 126

def save!(options={})
  raise ActiveRecord::RecordInvalid.new(self) if (options[:validate] != false && !self.valid?)
  self.save || raise(ActiveRecord::RecordNotSaved)
end