更改实例变量的方法是否属于我的Rails控制器或模型?

时间:2016-05-11 21:30:40

标签: ruby-on-rails ruby

我有一个基本的"最佳实践"关于控制器和实例变量的问题。

假设您在控制器中有新的实例变量或更新操作,是否可以通过控制器中的私有方法修改该实例变量?或者该方法是否存在于模型中?

e.g。在下面的这个例子中,我需要循环实例变量的属性,并添加或删除一些东西。例如,如果我使用3层深度的嵌套属性并且必须删除某些属性,请更改它们然后重新添加它们。我知道这可能看起来很奇怪,但是假设它是必要的。

def new
  @some_thing = SomeThing.new(:some_params)
  do_something_to_inst_var # method call
  @some_thing.save
end

private

def do_something_to_inst_var
  @some_thing.addresses.each do |address|
    # modify it in some  way
  end
end

或者这是不好的做法?这应该是模型中的方法,应该被称为:

@some_thing.do_something_to_inst_var

OR

我们应该将实例变量显式传递给类似的方法:

def new
  @some_thing = SomeThing.new(:some_params)
  do_something_to_inst_var(@some_thing) # method call
  @some_thing.save
end

private

def do_something_to_inst_var(some_thing)
  some_thing.addresses.each do |addresses|
    # modify it in some way
  end
end

我在这里寻找一些清晰度,如果可能的话,举个例子。我还在学习并试图改进,但我没有找到答案。

3 个答案:

答案 0 :(得分:1)

Rails应用程序应该有"thin controllers" and "fat models",原因有两个:

  • 每个对象应该只处理自己的职责。控制器应该只是关于连接Web,模型和视图,这要感谢Rails不需要太多代码。如果控制器方法反复引用同一模型的方法,则它会错误地承担模型责任;我们说它不是cohesive或它有"Feature Envy"。如果模型更改,控制器更有可能必须并行更改。

  • 测试模型比测试控制器更容易。

通过在模型中编写一个方法来修复它,该方法执行特定于模型的工作并在控制器中调用它(第二个选项)。 (最终你的模型会变得太胖,你也必须分解它,但这是另一个故事。)例如:

class SomeThingsController
  def new
    @some_thing = SomeThing.new(:some_params)
    @some_thing.do_something # method call
    @some_thing.save
  end
end

class SomeThing
  def do_something
    addresses.each do |address|
      # modify it in some  way
    end
  end
end

关于实例变量。

  • 仅在必要时定义它们。据推测,视图中需要您的示例中的那个。

  • 假设一个实例变量完全合理,没有理由不在包含它的类的私有方法中引用它。这就是他们的目的。所以你的第一个选项(直接引用实例变量)比你的第三个选项(传入它)好一点。但是,如上所述,提取模型方法优于其他两个选项。

答案 1 :(得分:1)

在我看来,如果您的控制器只有100行,则可以从私有方法修改@instance_vars

想象一下这样一个场景,你的控制器中有500个LOC,经过几个小时的努力,你发现某个私有方法正在修改@intance_var

有用的提示

  • 创建具有单一责任的小型私人方法
  • !放在method_name!的末尾,表示它会修改某些内容。特别是当您看到my_private_method!!让您意识到它正在修改某些内容时,此功能非常有用。
  • 不允许将代码放在不属于此处的控制器中。

答案 2 :(得分:1)

还有一个选择:

在控制器中:

def new
  @some_thing = SomeThing.new(:some_params)
  @some_thing_modified = @some_thing.modify_somehow(params)
  @some_thing_modified.save
end

SomeThing模型:

def modify_somehow(params)
  result = self.clone
  # ... modify result ...
  return result
end

因为modify_somehow现在是pure function(假设你不在... modify result ...部分做任何事情,这会让它变得不纯净),你在这里获得的是Referential transparency 。引用透明性的主要好处是,您可以通过查看其参数来确定要执行的函数/方法调用,并仅通过返回值获取其工作结果,而不是通过side effects。这使您的代码更具可预测性,从而使其更易于理解和调试。

当然有一些缺点:因为您创建了新对象,所以此选项的性能可能较低,而且其替代方案也更加冗长。

函数式编程概念,如引用透明性,在Rails社区中并不常见(可能是因为以OO为中心的Ruby)。但是,如果你想要它,它的优点和缺点就是参考透明度。