2010-01-15 67 views
0

考虑迁移如何2分贝列映射到一个属性

class CreateTalks < ActiveRecord::Migration 
    def self.up 
    create_table :talks do |t| 
     t.integer :duration_hours 
     t.integer :duration_minutes 
    end 
    end 

    def self.down 
    drop_table :talks 
    end 
end 

和模型

class Talk < ActiveRecord::Base 
end 

和对象

class Duration 
    attr_accessor :hours, :minutes 
end 

我怎么映射DURATION_HOURS和DURATION_MINUTES列Talk中的Duration属性,以便我可以做

d = Talk.first.duration 
hours = d.hours 
minutes = d.minutes 

我知道在这种情况下,我可以将小时和分钟转换为秒,并将它们存储在单个列中,但我期望了解如何使用ActiveRecord实现这种类型的映射。

回答

0

编写自定义访问器方法。

+1

你能否展开一下,你的意思是说我添加了duration_hours和duration_minutes的存取方法来填充持续时间属性?如果是这种情况,他们需要成为公众访问者还是可以让他们变成私人的? (我想封装duration_hours和duration_minutes,以便应用程序的其余部分只使用duration属性) – opsb 2010-01-15 23:49:25

+0

我会写两种方法(duration =(setter)和duration(getter))。首先解析传递的字符串(以任何可能的格式),并适当设置小时和分钟的持续时间,第二个 - 从db中获取这两个值,并以任意格式将它们组合在一起。 但开始 - 我会保持持续时间为整数秒。或者,如果你需要更好的精度,如浮点数。 – Eimantas 2010-01-16 08:55:13

0

我不知道我明白你想要完成什么......特别是在两个不同的列中存储小时和分钟,而不是存储日期/时间和提取小时和分钟.... buuuut。 ..我的attr_accessor的理解是:

attr_accessor :duration_hours 

等于:

def duration_hours 
    @duration_hours 
end 

def duration_hours=(d) 
    write_attribute(:duration_hours, d) 
end 

那么什么Eimantas指的是自定义上面的方法来存储或您认为合适的显示信息......你应该已经能够做到了:

d = Talk.first 
hours = d.duration_hours 
minutes = d.duration_minutes 

对不对?

编辑:

如果你想使演讲或某事的名单和时间分别使用您的列经过的量,我会做的方式是(仅用于显示):

def duration 
    @duration = self.duration_hours.to_s + ":" + self.duration_minutes.to_s 
end 

然后使用talk.duration调用。马虎,但它的作品。

+0

回想起来,我认为我的思维被我对java的ORM框架(如hibernate)的经验所笼罩。在休眠的情况下,数据库表和模型可以完全不同,通过定义映射来实现。我开始意识到active_record模式的完整意图,即模型和数据库表之间没有区别。如上所述,必须使用自定义访问器来实现表示中的任何差异。 – opsb 2010-01-16 02:50:59

+0

我有一个很小的感觉,这是一个稍微低效的方法,因为每次访问者被调用时都必须完成翻译。这与检索模型时执行一次翻译相反。但是,从实用的角度来看,自定义访问器可能只会按请求调用一次,在这种情况下效率问题无论如何都是学术问题。 – opsb 2010-01-16 02:52:00

+0

顺便说一下,我不想使用时间列的原因是它表达了完全不同的意图。它意味着与相对点相对的时间点,例如,开始时间后1小时(start_time也包含在真实模型中)。也许我应该去开始/结束时间而不是开始/持续时间,但是模型会经常被移动一段时间,所以它看起来更合适。通过使用开始/持续时间,移动只需要更新一列。这也是对用户具有的概念模型的更准确反映。 – opsb 2010-01-16 02:57:30