Rails:模型中的方法太多了

时间:2017-01-11 01:08:02

标签: ruby-on-rails ruby oop

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目录中创建模块还是应该将方法移动到其他模型?

3 个答案:

答案 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