Search code examples
ruby-on-railsinheritanceactiverecordruby-on-rails-5

Rails child object using parent method instead of its own


I have the Child class Vibe::Interaction::SurveyMessage that inherits from Interaction. They share the same table, and the SurveyMessage is identified by {app: :vibe, kind:"survey"}.

The controller calls the method through the parent class: Interaction.find(param[:id]).refresh

The problem is that even when the object is a SurveyMessage Object, it uses the parent's update_message method (the empty one).

Is there a way to force the object to act as a SurveyMessage Object instantiating it with the parent class (Interaction)? Or is there a way to identify through the parent class if the object belongs to a child class?

class Interaction < ApplicationRecord
  enum app: [ :praise, :review, :vibe, :atlas, :goals ]
  belongs_to :survey, class_name: 'Survey', foreign_key: :vibe_survey_id, required: false
  serialize :attachments 

  def message
    {
      text: self.text,
      attachments: self.attachments
    }
  end

  def update_message
  end

  def refresh(options = {})
    update_message
    h = self.history << {
            :type => :refresh,
            :timestamp => Time.current.to_s
          }
    update( 
      history: h 
    )
    # Submit code
    message
  end

end
class Vibe::Interaction::SurveyMessage < Interaction
  default_scope -> { where(app: :vibe, kind: "survey") }

  def update_message
    msg = survey.answer(user_id, self, additional_options||{} )
    update( text: msg[:text], attachments: msg[:attachments])
  end

end


Solution

  • You can use becomes method

    https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-becomes

    If your subclasses have a pattern

    i = Interaction.find_by(id: id)
    i = i.becomes("#{i.kind.capitalize}Message".constantize) if i&.vibe? # or in parent class as a method #downcast
    i.refresh