【问题标题】:Rails - Add attributes not in model and update model attributeRails - 添加不在模型中的属性并更新模型属性
【发布时间】:2012-02-21 11:26:55
【问题描述】:

我的表单中有 3 个字段不在我的数据库中:opening_type、opening_hours、opening_minutes。我想用这 3 个字段更新主要属性“opening”(在数据库中)。

我尝试了很多不起作用的东西。

其实我有:

  attr_accessor :opening_type, :opening_hours, :opening_minutes

  def opening_type=(opening_type)
  end
  def opening_type
    opening_type = opening.split("-")[0] if !opening.blank?
  end

  def opening_hours=(opening_hours)
  end
  def opening_hours
    opening_hours = opening.split("-")[1] if !opening.blank?
  end  

  def opening_minutes=(opening_minutes)
  end
  def opening_minutes
    opening_minutes = opening.split("-")[2] if !opening.blank?    
  end

我尝试添加类似:

  def opening=(opening)
    logger.info "WRITE"

    if !opening_type.blank? and !opening_hours.blank? and opening_minutes.blank?
      opening = ""
      opening << opening_type if !opening_type.blank?
      opening << "-" 
      opening << opening_hours if !opening_hours.blank?
      opening << "-" 
      opening << opening_minutes if !opening_minutes.blank?
    end
    write_attribute(:opening, opening)
  end

  def opening
    read_attribute(:opening)
  end

但是,没有调用访问器方法,我认为如果调用访问器,opening_type、opening_hours、opening_minutes 也是空的......

我认为我不需要 before_save 回调,应该重写访问器。

注意事项: - 轨道 3.0.5, - opening_type, :opening_hours, :opening_minutes 可以为空

编辑:我更新了我的代码

【问题讨论】:

    标签: ruby-on-rails accessor


    【解决方案1】:

    请注意,attr_readerattr_writerattr_accessor 只是用于定义您自己的方法的宏。

    # attr_reader(:foo) is the same as:
    def foo
      @foo
    end
    
    # attr_writer(:foo) is the same as:
    def foo=(new_value)
      @foo = new_value
    end
    
    # attr_accessor(:foo) is the same as:
    attr_reader(:foo)
    attr_writer(:foo)
    

    目前,您的 setter 方法没有做任何特别的事情,所以如果您只是切换到 attr_accessor,您的代码会变得更简洁。

    您的另一个问题是您的 opening= 方法永远不会被调用,这是有道理的,因为您的代码中没有任何地方调用它。您真正想要的是在所有单独的部分都设置好之后设置您的开口。现在没有简单的方法可以做到这一点,但 Rails 确实有一个 before_validation 回调,您可以在其中放置在设置值之后但在验证运行之前运行的代码:

    class Shop < ActiveRecord::Base
    
      attr_accessor :opening_type, :opening_hours, :opening_minutes
    
      before_validation :set_opening
    
      private
      def set_opening
        return unless opening_type && opening_hours && opening_minutes
        self.opening = opening_type + "-" + opening_hours + "-" + opening_minutes
      end
    end
    

    【讨论】:

    • 请注意,此答案假定您只想将组合的 opening 字段存储在数据库中。另一种方法是将各个组件存储在数据库中,并根据需要动态构建组合字符串。根据您的要求,这对您来说可能是更好的方法。
    • 我得到这个数据库的开头字段。该数据库与智能手机应用程序同步,我无法更改其结构来存储 3 个不同的字段。 ;-) before_validation 回调的问题在于,当我们要编辑表单时,您没有处理这种情况......并且我需要在 3 个变量中截断开头字段......对于表单。我知道我可以手动执行此操作,但我认为有更好的方法可以使用访问器执行此操作...
    • 都是正确的,但是您关于覆盖 opening= 的建议会破坏很多事情。此外,拥有一个完全丢弃传入参数的 setter 方法是一个非常粗略的想法。最好有一个单独的方法(比如我的set_opening),它可以清楚地说明它在做什么。您没有必须使用 before_validation 来调用该方法,但我强烈建议它是一个单独的方法
    • 实际上我可以用我的代码读取 3 个字段并填写表格。好的,我将在 before_validation() 中使用您的提示。谢谢。
    【解决方案2】:

    而不是

    attr_reader :opening_type, :opening_hours, :opening_minutes
    

    你需要

    attr_accessor :opening_type, :opening_hours, :opening_minutes
    attr_reader :opening_type, :opening_hours, :opening_minutes
    

    高频...

    // :opening_type, :opening_hours, :opening_minutes 是真实字段吗?如果是,那么您只需要这个?

    attr_accessor:打开 attr_reader :opening

    【讨论】:

    • 没有。真正的领域是在我的数据库中“打开”。我需要连接从我的表单发送的 3 个字段:opening_type、opening_hours、opening_minuts 来填写主要的“开放”字段。这 3 个字段不在数据库中。我更新了第一篇文章。
    • 那么访问器是最流行的方式。您可以使用它们将一个字符串分成许多其他字符串,但不能反过来。您应该将这些数据存储在数据库中,然后您可以编写一个opening 方法来显示连接字段!
    • 不,我不能。我得到了这些带有开放字段的数据库。该数据库与智能手机应用程序同步,我无法更改其结构来存储 3 个字段。 ;-)
    • 好的,那么请添加您用于将数据提交到您的帖子的表单!
    • 请同时发布参数哈希
    猜你喜欢
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2013-12-05
    • 2016-06-20
    相关资源
    最近更新 更多