TL; DR:我不知道如何组织我的逻辑域类。
我有模型"应用",这个模型在"核心"应用程序,是我进入"的方式并运行其他模型,如:
@application = Application.find(params[:application_id])
@application.payment.update_attribute 'active', true
或
unless @application.report.status
或
@application.set_income(params[:income][:new_income])
所以模型付款,收入和报告基本上都是空的,因为我初始化了应用程序模型,并从那里开始做事情"在级联"改变"从属"楷模。但现在应用程序模型有超过40种方法和600行。
我做得对吗?例如,当我想添加一个我喜欢的新付款时:
payment = Payment.create params
在应用程序模型中,因为ActiveRecord"知道"如何自动处理外键。我可以使用以下方式在付款模式中创建付款:
application = Application.find(application_id)
params[:application_id] = application.id
self.create params
但是这样,我需要手动设置Application.id,看起来更冗长,更优雅。
所以 - 如果我想减少我的应用程序模型 - 我应该在APP / lib目录中创建模块还是应该将方法移动到其他模型?
答案 0 :(得分:3)
我应该在APP / lib目录中创建模块
基本上,是的,那就是你应该做的。虽然我可能会让他们成为课程而不是模块。它听起来像你所追求的模式称为“服务对象”(或有时称为“用例”)。这样做是从你想要执行的特定操作中获取逻辑,并将其放入它自己的自包含类中。那个班级然后与它需要的任何模型合作。因此,您的模型仍然非常小,您的“服务类”遵循单一责任原则。然后,您的控制器通常会调用单个“服务类”来执行他们需要执行的操作 - 因此您的控制器也会保持最小化。
如果你谷歌“铁路服务对象”或类似的,你会发现很多很棒的东西,但这里有一些资源可以帮助你入门。
服务对象rails casts:https://www.youtube.com/watch?v=uIp6N89PH-c
https://webuild.envato.com/blog/a-case-for-use-cases/
https://blog.engineyard.com/2014/keeping-your-rails-controllers-dry-with-services
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/(那里有一个关于服务对象的部分)
请记住,一旦开始使用服务对象,您不必总是通过#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/resource.h>
int main(void)
{
struct rlimit stacklim;
rlim_t cur_bytes, max_bytes;
if (getrlimit(RLIMIT_STACK, &stacklim) == 0) {
cur_bytes = stacklim.rlim_cur;
max_bytes = stacklim.rlim_max;
} else {
perror("Error in getrlimit()");
exit(EXIT_FAILURE);
}
puts("Maximum Stack Size");
printf("Soft limit: %" PRIuMAX " bytes\n", (uintmax_t)cur_bytes);
printf("Hard limit: %" PRIuMAX " bytes\n", (uintmax_t)max_bytes);
return 0;
}
模型来访问相关的模型。服务对象可能需要Application
,然后执行例如。 application_id
因此您根本不需要获取应用程序实例,并且可以直接操作@payment = Payment.find_by(application_id: application_id)
变量。
Rails使得相关模型“轻松”和“漂亮”的事实并不一定意味着你应该这样做。
答案 1 :(得分:1)
TL; DR:如果您的应用程序有四个模型都与数据库中的表绑定(即利用ActiveRecord并继承自ActiveModel :: Base),那么该框架非常注重使用模型类。
在某些情况下,服务类模式的抽象可能很有用,但请给自己一个休息时间。 Rails的一个优点是,它可以通过为您做出组织决策来消除很多开发障碍。利用您的模型类。
让我们看看这是否会引发一场史诗般的开发者争吵战。
此外,可以在模型中创建用于相关模型创建的接口:
class Application < ActiveModel::Base
has_one :payment
def create_payment(attrs)
payment.create(attrs)
end
end
而且,好吧,我的意思是框架将允许这样做。但请记住,您已经从ActiveModel::Base
继承,它定义了许多实例方法,包括create
。
我会建议,尤其是如果这是一个小项目并且您只是沾沾自喜,使用名称良好的rails控制器来读取和写入数据库中的对象:
class ApplicationPaymentsController < ActionController::Base
def create
application = Application.find(params[:id])
application.create_payment(payment_params)
end
private
def payment_params
params.require(:payment).permit(:x, :y) - whatever your attr names are.
end
end
在创建关系记录时,您正在寻找抽象外键的光滑性由Rails协会为您解决:
http://guides.rubyonrails.org/association_basics.html(良好的起点)
http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one(更明确的文档)
如果这是您的目标,那将有助于您减少模型。只是为了澄清,这是开发人员对这种或那种方式极其反对的事情之一,但事实是存在代码气味(应该被解决)然后有人随意宣扬文件长度最大值。所有这一切中最重要的是可读代码。
对于重构工作代码的一个很好的试金点是将它放下几个星期,然后回到它,如果它混乱,那么就花一些时间让它变得更好(希望通过已经编写的测试覆盖率来指导)。否则,尽情享受你的工作,特别是如果你独自工作的话。
答案 2 :(得分:1)
我不担心Rails中的长控制器和规范文件。
这些文件往往会变得很长,保持类和方法简短的通常建议不一定适用于控制器及其规范。
例如,在我们的生产系统user_controller.rb
中,长度为8500行,相应的user_controller_spec.rb
长度为7000行。
这是我们的前10名控制器的长度
1285 app/controllers/*********_controller.rb
1430 app/controllers/***********_controller.rb
1444 app/controllers/****_controller.rb
1950 app/controllers/****_controller.rb
1994 app/controllers/********_controller.rb
2530 app/controllers/***********_controller.rb
2697 app/controllers/*********_controller.rb
2998 app/controllers/*****_controller.rb
3134 app/controllers/application_controller.rb
8737 app/controllers/users_controller.rb