返回对象的模型中的自定义方法

时间:2008-09-29 20:31:03

标签: ruby-on-rails ruby

在数据库中,我有一个名为“body”的字段,其中包含XML。该 我在模型中创建的方法如下所示:

def self.get_personal_data_module(person_id) 
    person_module = find_by_person_id(person_id) 
    item_module = Hpricot(person_module.body) 
    personal_info = Array.new 
    personal_info = {:studies => (item_module/"studies").inner_html, 
                            :birth_place => (item_module/"birth_place").inner_html, 
                            :marrital_status => (item_module/"marrital_status").inner_html} 
    return personal_info 
end 

我希望函数返回一个对象而不是一个数组。所以我可以 使用Module.studies而不是Model [:studies]。

3 个答案:

答案 0 :(得分:4)

这相对简单;你得到一个数组,因为代码正在建立一个。如果你想返回一个对象,你可以这样做:

class PersonalData
  attr_accessor :studies
  attr_accessor :birth_place
  attr_accessor :marital_status

  def initialize(studies,birth_place,marital_status)
    @studies = studies
    @birth_place = birth_place
    @marital_status = marital_status
  end
end

您的翻译代码如下:

def self.get_personal_data_module(person_id) 
  person_module = find_by_person_id(person_id) 
  item_module = Hpricot(person_module.body) 
  personal_info = PersonalData.new((item_module/"studies").inner_html,
                                   (item_module/"birth_place").inner_html,
                                   (item_module/"marital_status").innner_html)
  return personal_info 
end

答案 1 :(得分:2)

或者,如果你想避开一个模型类,你可以做一些奇怪的事情:

class Hash
  def to_obj
    self.inject(Object.new) do |obj, ary| # ary is [:key, "value"]
      obj.instance_variable_set("@#{ary[0]}", ary[1])
      class << obj; self; end.instance_eval do # do this on obj's metaclass
        attr_reader ary[0].to_sym # add getter method for this ivar
      end
      obj # return obj for next iteration
    end
  end
end

然后:

h = {:foo => "bar", :baz => "wibble"}
o = h.to_obj # => #<Object:0x30bf38 @foo="bar", @baz="wibble">
o.foo # => "bar"
o.baz # => "wibble"

就像魔术一样!

答案 2 :(得分:1)

略有不同的大头钉。

从OO的角度来看,使用类方法执行此操作的想法是错误的。

你应该重构这个,以便它可以从实例方法中运行。

  def personal_data_module
    item_module = Hpricot(body) 
    {
      :studies => (item_module/"studies").inner_html, 
      :birth_place => (item_module/"birth_place").inner_html, 
      :marrital_status => (item_module/"marrital_status").inner_html
    }
  end

然后,你需要使用它,而不是做....

Foobar.get_personal_data_module(the_id)
你会做的

Foobar.find_by_person_id(the_id).personal_data_module

这看起来更糟,但事实上,这有点人为,通常,你会 从其他对象引用它,实际上你会在person对象上有一个'handle',所以不必自己构造它。

例如,如果您有另一个类,您将person_id作为外键引用,那么您将拥有

班级组织   belongs_to:person 端

然后,你有一个组织,你可以去

organisation.person.personal_information_module

是的,我知道,这会打破demeter,所以最好将它包装在委托

class Organisation
  belongs_to :person

  def personal_info_module
    person.personal_info_module
  end
end

然后从控制器代码中,您可以说

organisation.personal_info_module

根本不用担心它的来源。

这是因为'personal_data_module'实际上是该类的属性,而不是通过类方法访问的内容。

但是这也提出了一些问题,例如,person_id是这个表的主键吗?这是一个遗留的情况,表的主键不是'id'?

如果是这种情况,你有没有告诉过ActiveRecord,或者你是否必须在你真正想写'find'的地方使用'find_by_person_id'?