新手问题 Rails 有类似 J2EE 中的 value object 吗?

manaleak · 2015年03月23日 · 最后由 luikore 回复于 2015年03月24日 · 2366 次阅读

抱歉,由于我是新手,以下例子完全是 j2ee 那套,我不知道 Rails 该怎么做。

例如:

  • Person 有 name sex tel 三项内容
  • 我想统计姓“李”的和姓“张”的各有多少个
  • 所以我想建一个 Map nameMap(ruby 中的 map 怎么用,我也是一头雾水)
nameMap.put("李",0);
nameMap.put("张",0);

然后查询所有 name,只要第一个是"李",就从 nameMap 中取出"李"对应的 value,然后++,再 put

后来我需要统计 100 个姓,看看分别有多少个,所以我想建一个 Vo。

class NameStatsVo {
  private String name;
  private Integer count;
  //getter setter
}

不知道 rails 的思维方式是怎么样的?

从基础说起,可以用一个 Hash 对应一个 Person,一个 Person 数组就是:

persons = [ { name: '李xx', sex: '', tel: '' }, { name: '张', sex: '', tel: '' } ] # and more

数组(Array)内含了不少方法,其中的 inject 方法可以将数组遍历然后计算出一个结果,文档看这里 http://ruby-doc.org/core-2.2.1/Enumerable.html#method-i-inject ,对应你的需求就是:

persons.inject(Hash.new(0)) {|hash, person| hash[person[:name][0]] += 1; hash }
# => { '李' => 1, '张 => 1 }

解释一下,Hash.new(0) 创建一个空 Hash 用来存放结果(这个 Hash 每个 key 的默认值是 0),然后传到 inject block 里面;block 里面的 person[:name][0] 取到用户的姓,然后作为 key 找到 hash 的对应值 += 1;最后 block 要将 hash 作为结果返回作为下一次迭代的 hash 值,遍历完毕后 hash 就是你要的结果。

如果你希望 Person 成为一个类,方法差不多,代码变为:

class Person
  # attr_accessor 定义了 getter setter 方法
  attr_accessor :name, :sex, :tel

  def initialize(attributes)
    @name = attributes[:name]
    @sex = attributes[:sex]
    @tel = attributes[:tel]
  end
end

persons = [ Person.new( name: '李xx', sex: '', tel: ''), Person.new( name: '张xx', sex: '', tel: '') ]

persons.inject(Hash.new(0)) {|hash, person| hash[person.name[0]] += 1; hash }

以上是 Ruby 的做法,你问到了 Rails 的做法,那么假设数据是存在数据库里的,并且使用了 ActiveRecord,那么可以通过数据库查询得出:

class Person < ActiveRecord
end

# PostgreSQL 语法
Person.select('substring(name for 1) as first_name, count(*)').group('first_name').map{ |person| [person.first_name, person.count] }.to_hash

我从 Rails 在学 Spring,问题更多,很多在 Rails 里约定俗成的东西,在 Spring 中都需要各种搞来搞去,完全一头雾水。

也有的,一般情况下用不到,常见做法参见楼上。 想了解 Rails 如何实现 VO,可以参考 中 9.11 Using Value Objects

用 Rails 做完项目,再回头用 JEE, 简直就是折磨。

Person.each.with_object(Hash.new 0) {|p, h| h[p.name[0]] += 1}
需要 登录 后方可回复, 如果你还没有账号请 注册新账号