Rails child object 使用 parent 方法而不是它自己的方法
Rails child object using parent method instead of its own
我有继承自 Interaction
的 Child class Vibe::Interaction::SurveyMessage
。它们共享相同的 table,并且 SurveyMessage
由 {app: :vibe, kind:"survey"}
标识。
控制器通过parentclass调用方法:
Interaction.find(param[:id]).refresh
问题是,即使 object 是 SurveyMessage Object
,它也使用 parent 的 update_message
方法(空方法)。
有没有办法强制 object 充当 SurveyMessage Object
用 parent class (Interaction
) 实例化它?
或者有没有办法通过 parent class 来识别 object 是否属于 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
我设法解决了在父级上创建路由方法的问题 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
虽然不优雅,但很管用。如果有人有更好的解决方案,我很想听听。
可以使用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
我有继承自 Interaction
的 Child class Vibe::Interaction::SurveyMessage
。它们共享相同的 table,并且 SurveyMessage
由 {app: :vibe, kind:"survey"}
标识。
控制器通过parentclass调用方法:
Interaction.find(param[:id]).refresh
问题是,即使 object 是 SurveyMessage Object
,它也使用 parent 的 update_message
方法(空方法)。
有没有办法强制 object 充当 SurveyMessage Object
用 parent class (Interaction
) 实例化它?
或者有没有办法通过 parent class 来识别 object 是否属于 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
我设法解决了在父级上创建路由方法的问题 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
虽然不优雅,但很管用。如果有人有更好的解决方案,我很想听听。
可以使用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