2008-09-29 142 views
1

在数据库中,我有一个名为“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]来使用 。

谢谢你的时间。
Silviu

p.s我是rails和ruby的新手。我有一个C背景。

回答

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 
+0

工程就像一个魅力;) – 2008-09-29 21:04:35

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" 

这就像魔法!

+1

任何情况下,你可以想到什么时候使用这种方法在逻辑上比回答的方法更好? – junkforce 2008-09-30 04:09:45

+0

对于这些类型的解决方案,我开始喜欢Ruby – 2008-09-30 10:17:20

1

略有不同的粘性。

从面向对象的角度来看,使用类方法做这件事的想法是错误的。

你应该真的重构这个,以便它从一个实例方法。

 
    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对象有一个“处理”,所以不必自己构造它。

举例来说,如果你有另一个类,在这里引用为person_id作为外键,你就必须

类组织 belongs_to的:人 结束

话,那就是你有一个组织,你可以去

 
organisation.person.personal_information_module 

是的,我知道,得墨忒耳突破,所以这将是更好地包装在一个委托

 
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'?

相关问题