ruby-on-rails – attr_accessor强类型的Ruby on Rails

只是想知道有没有人可以在Ruby on Rails上看到有关强类型的getter设置器的基础知识.我在轨道上是非常新的ruby,主要是对.NET有很好的理解.

例如,假设我们有一个名为Person的.net类

class Person
{
 public string Firstname{get;set;}
 public string Lastname{get;set;}
 public Address HomeAddress{get;set;}
}

class Address
{
 public string AddressLine1{get;set;}
 public string City{get;set;}
 public string Country{get;set;}
}

在Ruby中,我会把它写成

class Person
 attr_accessor :FirstName
 attr_accessor :LastName
 attr_accessor :HomeAddress
end

class Address
 attr_accessor :AddressLine1
 attr_accessor :City
 attr_accessor :Country
end

看看Ruby版本的Person类如何为访问者方法FirstName,LastName和HomeAddress指定类型?如果我要消费这个类,我可以将任何类型的Feed添加到HomeAddress中,但是我希望这个访问器方法只接受TYPE Address.

有什么建议么 ?

谢谢

解决方法

TL; DR:不,这是不可能的…很长的回答,是的,有可能,阅读元编程部分:)

Ruby是一种动态语言,这就是为什么你不会得到编译时类型的警告/错误,就像C#这样的语言.

与您无法为变量指定类型相同,您不能指定attr_accessor的类型.

对于来自.NET的用户来说,这可能听起来很愚蠢,但在Ruby社区,人们期望您能够编写测试.如果这样做,这些类型的问题将基本消失.在Ruby on Rails中,你应该测试你的模型.如果你这样做,你不会真的有任何麻烦,意外地分配错误的地方.

如果您正在Ruby on Rails中讨论ActiveRecord,则将String分配给数据库中定义为Integer的属性将导致抛出异常.

顺便说一句,根据惯例,你不应该使用CamelCase属性,所以正确的类定义应该是

class Person
 attr_accessor :first_name
 attr_accessor :last_name
 attr_accessor :home_address
end

class Address
 attr_accessor :address_line1
 attr_accessor :city
 attr_accessor :country
end

一个原因是,如果您将第一个字母大写,则Ruby将定义一个常量而不是一个变量.

number = 1   # regular variable
Pi = 3.14159 # constant ... changing will result in a warning,not an error

元编程黑客

顺便说一句,Ruby还具有非常庞大的元编程能力.您可以使用类型检查编写自己的attr_accessor,可以使用类似的检查

typesafe_accessor :price,Integer

有定义的东西

class Foo

  # 'static',or better said 'class' method ...
  def self.typesafe_accessor(name,type)

    # here we dynamically define accessor methods
    define_method(name) do
      # unfortunately you have to add the @ here,so string interpolation comes to help
      instance_variable_get("@#{name}")
    end

    define_method("#{name}=") do |value|
      # simply check a type and raise an exception if it's not what we want
      # since this type of Ruby block is a closure,we don't have to store the 
      # 'type' variable,it will 'remember' it's value 
      if value.is_a? type
        instance_variable_set("@#{name}",value)
      else
        raise ArgumentError.new("Invalid Type")
      end
    end
  end

  # Yes we're actually calling a method here,because class definitions
  # aren't different from a 'running' code. The only difference is that
  # the code inside a class definition is executed in the context of the class object,# which means if we were to call 'self' here,it would return Foo
  typesafe_accessor :foo,Integer

end

f = Foo.new
f.foo = 1
f.foo = "bar" # KaboOoOoOoM an exception thrown here!

或至少这些线路的东西:)这段代码工作! Ruby允许您快速定义方法,这是attr_accessor的工作原理.

也是块几乎总是关闭,这意味着我可以做如果value.is_a?类型,而不将其作为参数.

这是非常复杂的,在这里解释这是真的,何时不是.总之,有不同类型的块

> Pro,由Proc.new创建
> lambda,它是由关键字lambda创建的

区别之一是调用lambda中的返回值只能从lambda本身返回,但是当您从Proc执行相同的操作时,块周围的整个方法将返回,这在迭代时使用.

def find(array,something)
  array.each do |item| 
    # return will return from the whole 'find()' function
    # we're also comparing 'item' to 'something',because the block passed
    # to the each method is also a closure
    return item if item == something
  end
  return nil # not necessary,but makes it more readable for explanation purposes
end

如果你是这样的东西,我建议你看看PragProg Ruby Metaprogramming screencast.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...