【问题标题】:Struct with types and conversion具有类型和转换的结构
【发布时间】:2011-09-20 14:39:20
【问题描述】:

我正在尝试在 Ruby 中完成以下任务:

person_struct = StructWithType.new "Person", 
                                   :name => String, 
                                   :age => Fixnum, 
                                   :money_into_bank_account => Float

我希望它同时接受:

person_struct.new "Some Name",10,100000.0

person_struct.new "Some Name","10","100000.0"

也就是说,我希望它自动进行数据转换。

我知道 Ruby 是动态的,我不应该关心数据类型,但这种转换会很方便。

我要问的是类似于 ActiveRecord 已经做过的事情:将字符串转换为表列中定义的数据类型。

在搜索 ActiveModel 后,我无法弄清楚如何使用一些 TableLess 进行这种转换。

毕竟我认为我的问题可能需要 ActiveModel 模块提供的更少。

当然我可以自己实现一个类来呈现这种转换功能,但我宁愿知道这还没有完成,以免重新发明轮子。

Tks 提前。

【问题讨论】:

标签: ruby-on-rails ruby activerecord struct activemodel


【解决方案1】:

我觉得在一个类里面实现就是这么简单,而且完全没有开销,所以我完全看不出使用StructWithType的理由。 Ruby 不仅是动态的,而且在存储其实例方面非常高效。只要你不使用属性,就没有。

类中的实现应该是:

def initialize(name, age, money_into_bank_account)
  self.name = name
  self.age = age.to_i
  self.money_into_bank_account = money_into_bank_account.to_f
end

StructWithType 中的实现会更高一层:

  • 为每种类型实现一个转换器。
  • 在类中绑定该转换器的实例。
  • StructWithType 实例(非类)的new 实现中使用类的转换器进行转换。

它的第一个草图可能是这样的:

class StructWithType
  def create(args*)
    <Some code to create new_inst>
    args.each_with_index do |arg,index|
      new_value = self.converter[index].convert(arg)
      new_inst[argname[index]]= new_value
    end
  end
end

这里的想法是:

  • 您有一个名为 create 的实例方法,它从工厂创建一个新的结构实例。
  • 工厂遍历所有 args(带有索引)并搜索转换器要使用的每个 args。
  • 它使用转换器转换 arg。
  • 它将新值存储在新实例的 argname 处(必须写入方法 argname[])。

因此您必须实现结构的创建、转换器的查找、参数名称的查找以及新实例属性的设置器。抱歉,今天没时间了…… 我使用了create,因为new 在Ruby 中有不同的含义,我不想把它搞砸。

【讨论】:

  • 感谢您的回答。我试图避免创建类,因为一个类需要一个名称,而我只捆绑了很多我不想在某些特定想法下分组的属性。假设我有以下属性:姓名、性别和年龄。我是否应该创建另一个类,例如:Person2?当然,我可以通过创建很多 os 类来重构整个系统,但我认为这不值得。
【解决方案2】:

我在 github 中找到了一个满足我的一些要求的项目:ActiveHash。 即使我仍然需要为每种类型创建一个类,但类型转换是免费的。 我试试看。

使用示例:

class Country < ActiveHash::Base
  self.data = [
                {:id => 1, :name => "US"},
                {:id => 2, :name => "Canada"}
              ]
end

country = Country.new(:name => "Mexico")
country.name  # => "Mexico"
country.name? # => true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    相关资源
    最近更新 更多