ruby-on-rails - 如何干燥两个不同类中使用的范围方法?

标签 ruby-on-rails ruby ruby-on-rails-3 refactoring dry

我正在使用 Ruby on Rails 3.2.2,我想通过“指定”/“过滤”这些关联对象的属性值来检索/范围关联对象。也就是此时我使用的是如下代码:

class Article < ActiveRecord::Base
  def self.search_by_title(search)
    where('articles.title LIKE ?', "%#{search}%")
  end
end

class ArticleAssociation < ActiveRecord::Base
  def self.search_by_article_title(search)
    joins(:article).where('articles.title LIKE ?', "%#{search}%")
  end
end

在上面的代码中,where('articles.title LIKE ?', "%#{search}%") 子句重复了两次,所以我认为可以通过 DRY 改进它原理:是否可以直接在 ArticleAssociation.search_by_article_title 方法中使用 Article.search_by_title 方法?


典型用例是:

  • ArticleAssociation.search_by_article_title("示例字符串")
  • Article.search_by_title("示例字符串")

最佳答案

除非你完全改变代码结构,否则不会。

您可以使用 lambda 进行一些黑客攻击,但那会比您正在 DRYing 的代码更多。有好的重构之类的东西,也有坏的重构之类的东西。除非在 2 个或更多地方使用一段非常复杂或长的代码,否则您可以担心重构。代码约定很重要,但对于像这样的微小的单一方法调用的事情来说,这是一种浪费,并且可能会使您的代码更加神秘。

不过,我知道人们不回答您的问题会很烦人,所以在这里:

class Article < ActiveRecord::Base
  SEARCH_BY_TITLE=lambda {|obj, search| obj.where('articles.title LIKE ?', "%#{search}%")}
  def self.search_by_title(search)
    SEARCH_BY_TITLE.call(self, search)
  end
end

class ArticleAssociation < ActiveRecord::Base
  def self.search_by_article_title(search)
    Article::SEARCH_BY_TITLE.call(joins(:article),search)
  end
end

这只是将 lambda 作为常量对指定对象执行 where 调用。这两种方法都只是包装那个 lambda。

注意:虽然这可能被认为更优雅,但它会大大降低性能,因为 lambda、闭包和额外调用在像 Ruby 这样的动态语言中是昂贵的。但我认为这对您来说不是问题。

关于ruby-on-rails - 如何干燥两个不同类中使用的范围方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10899972/

相关文章:

ruby-on-rails - Rails 简单表单按钮 ID

ruby - 使用 Ruby 脚本将 CSV 文件导入 sqlite3

ruby-on-rails - Rails 3 模型关注模块

ruby - OpenSSL key 长度在 Ruby 中太短,在 Bash 中则不然

sql - 选择具有不匹配 ID 计数的不同元素

ruby-on-rails-3 - Rails 回形针和倒置图像

ruby-on-rails-3 - JRuby意外的:

ruby-on-rails - 无法使用带有 Rails 4 的 ActiveAdmin 创建新用户

ruby-on-rails - 在 Active Admin 中更改只读输入文本

ruby-on-rails - 在 Ruby on Rails 中持久化购物车