【问题标题】:Rails child object using parent method instead of its ownRails 子对象使用父方法而不是它自己的方法
【发布时间】:2020-01-16 22:25:23
【问题描述】:

我有继承自Interaction 的子类Vibe::Interaction::SurveyMessage。它们共享同一张表,SurveyMessage{app: :vibe, kind:"survey"} 标识。

控制器通过父类调用方法: Interaction.find(param[:id]).refresh

问题是即使对象是SurveyMessage Object,它也使用父级的update_message 方法(空的)。

有没有办法强制对象充当 SurveyMessage Object 用父类 (Interaction) 实例化它? 或者有没有办法通过父类来识别对象是否属于子类?

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

【问题讨论】:

  • 试试Vibe::Interaction::SurveyMessage.find(param[:id]).refresh
  • 在定义嵌套类时不要使用范围解析运算符 (::)。这将导致令人讨厌的意外,因为它取决于定义点的模块嵌套。在这种情况下,它是全局范围。所以当你在Vibe::Interaction::SurveyMessage 中引用Interaction 时,你实际上会得到::Interaction 而不是Vibe::Interaction。使用显式嵌套并重新打开模块module Vibe; class Interaction; class SurveyMessage &lt; Interaction ...github.com/rubocop-hq/ruby-style-guide#namespace-definition
  • 嘿@PGill!如果我使用Vibe::Interaction::SurveyMessage.find(param[:id]),它会起作用,但我想在控制器中使用父Interaction.find(),因为我会有很多不同的孩子。

标签: ruby-on-rails inheritance activerecord ruby-on-rails-5


【解决方案1】:

你可以使用becomes方法

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

如果你的子类有模式

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

【讨论】:

  • 这就是我想要的!谢谢
【解决方案2】:

我已经设法解决它在父 Interaction 上创建路由器方法:

  def self.find_child(id)
    i = Interaction.find_by(id: id)
    if i&.vibe? and i.kind=="survey"
      ans = Vibe::Interaction::SurveyMessage.find(id)
    elsif i&.vibe? and i.kind=="partial"
      ans = Vibe::Interaction::PartialMessage.find(id)
    elsif (etc)
      ...
    else
      ans = i
    end
    ans
  end

它并不优雅,但它确实有效。如果有人有更好的解决方案,我很想听听。

【讨论】:

    猜你喜欢
    • 2014-01-22
    • 2015-04-21
    • 2017-07-20
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    相关资源
    最近更新 更多