【问题标题】:Combining virtual attributes to single class attributes in super class (STI)将虚拟属性与超类 (STI) 中的单个类属性组合
【发布时间】:2013-08-23 21:00:25
【问题描述】:

我正在尝试组合Event 表单中的start_datestart hourstart_minute 虚拟属性,以创建start_datetime 属性(存储在数据库中)。

我有(通过 STI)Event 的几个子类;我们称他们为TrainingSessionWorkSessionPersonalTime

类的结构如下:

class Event < ActiveRecord::Base
  ...
end

class TrainingSession < Event
  ...
end

class WorkSession < Event
  ...
end

class PersonalTime < Event
  ...
end

event.rb的相关部分:

class Event < ActiveRecord::Base
  attr_accessor :start_date, :start_hour, :start_minute

  validates :start_datetime, :presence => true

  before_validation :merge_attributes_for_datetime_string

  def merge_attributes_for_datetime_string
    start_datetime_string = "#{ start_date } #{ start_hour }:#{ start_minute }:00"
  end

  def start_datetime=(start_datetime_string)
    self.start_datetime = start_datetime_string
  end

  def start_date
    start_datetime.strftime("%d") if start_datetime?
  end

  def start_hour
    start_datetime.strftime("%H") if start_datetime?
  end

  def start_minute
    start_datetime.strftime("%M") if start_datetime?
  end
end

...和events_controller.rb:

  def create
    @event = Event.new(event_params)
    if @event.save
      redirect_to :root, :flash => { :success => "Event added." }
    else
      redirect_to :back, :flash => { :notice => "There was an error creating the event." }
    end
  end

  private

  def event_params
    params.require(:event).permit(
      :type,
      :start_datetime,
      :start_date,
      :start_hour,
      :start_minute,
      ...
    )
  end

  def training_session_params
    params.require(:training_session).permit(
      ...
    )
  end

  def work_session_params
    params.require(:work_session).permit(
      ...
    )
  end

  def personal_time_params
    params.require(:personal_time).permit(
      ...
    )
  end

我已经在我的服务器日志中验证了正确的参数是从表单发送的:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"<TOKEN HERE>=", "event"=>{"start_date" => "2013-08-23", "start_hour"=>"15", "start_minute"=>"00", "type"=>"PersonalTime"}, "commit"=>"Add Personal Time"}

然而,每次我尝试创建一个事件(任何类型)时,我都会收到通知There was an error creating the event.(根据我的创建方法)。如果我注释掉validates :start_datetime,则创建事件,但使用start_datetimenil

这意味着start_datetime 字符串没有从虚拟属性中正确合并,但我不知道为什么。

我在这里缺少什么?有没有更好的方法来设置start_datetime

【问题讨论】:

    标签: ruby-on-rails getter-setter single-table-inheritance virtual-attribute


    【解决方案1】:

    根据您发布的内容,我看不出您在哪里调用 start_datetime 方法。

    您可以在 start_datetime 方法中进行合并,而不是定义新方法,如下所示:

    before_validation :merge_attributes_for_datetime_string
    
    def merge_attributes_for_datetime_string
      self.start_datetime = "#{ start_date } #{ start_hour }:#{ start_minute }:00"
    end
    

    【讨论】:

    • 现有的start_datetime=(value_from_other_method)方法不应该充当setter吗? (至少工作,如果不是最干净的处理方式)
    • ... 另外,如果我只使用start_datetime 作为我的方法名称,它会干扰我想从数据库中获取start_datetime 属性的任何时间。
    • @jasonmklug,是的,你是对的,在这种情况下它会导致问题。因此,在这种情况下,您的方法名称 merge_attributes_for_datetime_string 是正确的。
    • 对于您的第一个问题,start_datetime=(value_from_other_method) 是您定义的 setter,但它不会在任何地方被调用,是吗?
    • 我正在使用(或至少尝试使用):before_validation 回调来处理这个问题。
    猜你喜欢
    • 2010-10-25
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多