我的模型Foo
包含许多属性(由Paperclip
,Devise
和其他内容生成)。现在我的表有43列。
优点和缺点是:
+
我尊重标准OOP。-
在数据库选择之后创建每个模型实例的时间更长。-
.inspect
方法难以阅读(我认为不是最重要的,也很容易覆盖)。-
模型的源代码需要超过700行(可以使用Concern
解决)我的问题是,我不需要90%的网页上的所有论文信息。
我想到了一个解决方案,但需要一些专业知识才能知道这是一个好主意还是坏主意。
我们的想法是将模型切割成分为两部分:Foo
和FooInfos
,其中:
Foo
包含所有主要信息FooInfos
包含10%剩余页面的所有信息,仅在必要时加载(使用delegate
方法,例如。)foo
对象has_one
foo_info
使用这种方法,上面提到的所有优点都会成为缺点,反之亦然。
这是个好主意吗?你有一些不这样的情况吗?你还有其他想法吗?
此致
答案 0 :(得分:3)
正如您所描述的那样,您的模型Foo
包含的信息太多了。
将信息移动到通用FooInfos
类/表中只会掩盖间接背后的原始问题,而不是解决它。
指出正确的方向:询问"如何使这个模型更小"是第一步,但你需要问一个稍微不同的问题:
这样做的一个变体是:"这个课程中隐藏着哪些不同的问题?"有多种方法可以将隐藏在单个页面对象中的信息和关注点分开。
一些工具:
分析您的代码并注意以下事项:一组方法正在使用一组属性并使用单独的视图元素。或者通常通过一组相关的接口方法在模型级别上访问。
每次你写一个(更大的)新功能时,问问自己这是否真的是一个直接属于当前模型的特征,或者它是否是它自己的模型(或者是一个辅助模型) )。
你可以像你在问题中描述的那样拆分一些信息:引入另一个模型(比如FooInfo,但实际上不是就像这样!):
不要只提取一些元信息,但要让模型名称重要!
例如:
我确定你会在你的Page对象中发现很多东西,实际上这是另一个问题。
您仍然可以通过部分呈现附加信息,并将@page.sidebar
传递给它,这样您的网页视图就不会太大。此外,在后端,您可以使用嵌套表单和部分,因此在外部,具有多个模型的解决方案与您当前的解决方案没有区别,但可以很好地分解为几个问题。
我在嵌套表单上进行了快速谷歌搜索,结果出现了:http://iroller.ru/blog/2013/10/14/nested-model-form-in-rails-4/ 不知道它是否有用,但有疑问你可以自己谷歌或者在轨道上找到一本带有例子的书。
如果您将信息卸载到其他模型,它不仅仍然是OOP,更是如此:
class Page < ActiveRecord::Base
has_one :sidebar
accepts_nested_attributes_for :sidebar
end
class Sidebar < ActiveRecord::Base
belongs_to :page
end
@page.sidebar # => very OOP!
这是官方文档页面:http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html
基本上,您可以将每个页面上不需要的信息移动到某些特殊情况中:
class Page < ActiveRecord::Base
end
class ImprintPage < Page
def do_something_with_terms_and_conditions
end
end
class IntroPage < Page
has_one :logo
end
class Logo < ActiveRecord::Base
# paperclip stuff
end
您甚至可以从图像中获取徽标,使其成为一种特殊的图像(图像中包含所有回形针的内容)。
ActiveRecord会将类类型存储在数据库中,因此您可以在视图中执行类似的操作(伪代码):
if @page.is_a?(IntroPage)
# render intro partial
您可以将问题转移到mixins中:
class Page
include PageTools::UserMethods
include PageTools::ImageHandling
end
但要非常小心,因为这可能导致信息遍布/lib
文件夹,这可能只会掩盖原始问题。
您可以做更多的事情来使类/模型更少整体(例如服务对象,关注点)。这些只是实现一些重要原则的工具:不要让你的课程变大,并尝试经常分离信息/关注/功能。
大部分内容都是通过练习来实现的,只是永远不要为一个功能添加一堆方法而不首先问自己是否必须真正进入这个确切的模型 - 重建一个巨大的Page怪物模型后,它总是增长太多了痛苦!