Ruby on Rails OOP - 我知道嵌套/内部类,嵌套'记录'怎么样?

时间:2014-05-09 00:47:31

标签: ruby-on-rails oop software-design

我的记录/模型中充满了许多布尔标志,短字符串,misc设置等,我想将它们重构为封装类。

我通常会为父母创建一个内部类来拥有'但是Rails中最好的做法是什么?

  • 只留下记录中的所有内容? composed_of?虽然不是很干净。
  • 序列化?变得不容易搜索+开销+可扩展性问题。还是不干净。
  • 创建另一条记录,关联它和delegate?但是必须委托和管理赋值,别名(布尔?字段),创建/保存回调,更多我不知道的东西......
  • 有没有办法创建内部记录'?
  • 另一种方式?

一个例子是拥有一个表Client,行数为10~20。每个Client都有很长的选项列表,目前存储在Client列下。所以有以下字段:

c = Client.find(1)
c.theme_color # "blue"
c.session_timeout_seconds # 1800
c.branding_logo # "client_a.png"
c.require_logout_confirmation # true

在没有rails的纯OOP系统中,我会重构这些"实例变量"进入嵌套的Client::Options类。然后,所有选项都组织在一个嵌套类中,并封装在Client内。通过这种方式,没有其他人需要知道Client::OptionsClient密切相关(他们仍然会在不知道c.theme_color会将呼叫委托给{{1}的情况下发送消息Client因为没有其他类或方法调用需要改变,所以这也将成为一个松散耦合的重构。

但是,在rails中,嵌套类的东西是不可能的(据我所知),所以我正在寻找最佳实践'溶液

1 个答案:

答案 0 :(得分:0)

这是我最终选择的解决方案:

class Client < ActiveRecord::Base
  has_one :option_set, :dependent => :destroy, :autosave => true, :validate => true, :inverse_of => :client
  before_create :build_option_set

  # accesses all these fields through OptionSet
  # :allow_nil is required or else delegation will fail - it appears delegation occurs before :build_option_set
  delegate_option_set_args = [
    :option_a,
    :option_b,
    :option_c,
    # etc
  ].map { |f| [f, :"#{f}=", :"#{f}?" ] }.flatten << { :to => :option_set, :allow_nil => true }

  delegate(*delegate_option_set_args)
end


class OptionSet < ActiveRecord::Base
  validates_presence_of :client_id
  validates_inclusion_of :option_c, :in => [ "foo", "bar", "buzz", "fizz" ]
  belongs_to :client, :inverse_of => :option_set
end

现在,虽然仍然可以从&#34;外部&#34;访问OptionSet。在Client中,它仍然有效地将所有这些字段封装到它们自己的类中。访问这些字段应通过Client的消息传递来完成,例如Client.first.option_a,而不是修改OptionSet。可以执行其他工作来强制执行OptionSet不会直接修改。

我找不到在Client创建的同时实例化选项字段的方法,但是:

client = Client.create!(client_args)
client.update_arguments!(
  :option_a => 1,
  :option_b => false,
  :option_c => "foo"
)