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

时间:2020-03-06 14:53:42  来源:igfitidea点击:

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

感谢时间。
西尔维

附言:我是Rails和ruby的新手。我有C背景。

解决方案

这是相对简单的。我们会得到一个Array,因为代码正在构建一个。如果我们想返回一个对象,则可以执行以下操作:

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

或者,如果我们想避免模型类,则可以做一些奇怪的事情:

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"

就像魔术!

略有不同。

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

我们应该真正重构它,以便它可以通过实例方法工作。

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引用为外键,则我们将拥有

班级组织
归属于: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_by_person_id"?