【问题标题】:Rails the best way to scope varsRails 定义变量范围的最佳方法
【发布时间】:2016-12-10 00:35:40
【问题描述】:

我有一个具有以下属性的“课程”模型;

Course
  Price - float 
  Featured - boolean

我的问题如下,我的控制器中需要 4 个列表,最近的课程、付费课程、免费课程和特色课程。

按如下方式编写我的控制器是个好习惯吗?

def index
  @courses = Course.order(created_at: :desc)

  @free_courses = []
  @courses.map {|c| @free_courses << c if c.price == 0}

  @premium_courses = []
  @courses.map {|c| @premium_courses << c if c.price> 0}

  @featured_courses = []
  @courses.map {|c| @featured_courses << c if c.featured}
end

还是分开咨询?

def index
  @courses = Course.order(created_at: :desc)
  @free_courses = Course.where("price == 0")
  @premium_courses = Course.where("price > 0")
  @featured_courses = Course.where(featured: true)
end

我检查了日志,第一个选项是更好的性能,但我怀疑它是否是反合作伙伴。

谢谢大家!

【问题讨论】:

    标签: ruby-on-rails performance scope


    【解决方案1】:

    随着课程表大小的增加,第二种方法将比第一种方法更快。第一种方法必须遍历表中的每条记录 4 次。第二种方法只创建与 where 子句匹配的记录的关系,因此它的工作量较少。

    另外,第二种方法具有懒惰的优势。每个查询仅在使用时运行,因此可以沿代码路径进一步更改。它更灵活。

    请注意,这将是对在处理逻辑的 Course 模型上创建范围的第二种方法的改进。例如,课程、free_courses、premium_courses 和特色课程各一个。这样做的好处是将数据库逻辑放在模型而不是控制器中,这样可以更容易地重用和维护。

    【讨论】:

    • 感谢您的回答
    【解决方案2】:

    第二种方法更好,因为当您使用 .where() 方法时,您是在数据库本身而不是控制器中安排查询。

    【讨论】:

    • 感谢您的回答
    【解决方案3】:

    为了性能和内存使用,在 Rails 中迭代数据库中的所有记录(即Course.mapCourse.all)通常是不好的做法。随着您的数据库的增长,这将成为成倍增加的问题。使用Course.where() 方法要好得多。您可能需要一个默认的排序顺序,这样您就可以在模型中添加一行。

    default_scope { order(created_at: :desc) }
    

    然后您可以在控制器中执行此操作,默认情况下它们将进行排序:

    @courses = Course.all
    

    我还建议为您的模型添加范围以便于访问。 所以在你的 course.rb 文件中

    scope :free -> { where("price == 0") }
    scope :premium -> { where("price > 0") }
    scope :featured -> { where(featured: true) }
    

    然后在你的控制器中你可以这样做:

    @courses = Course.all
    @free_courses = Course.free
    @premium_courses = Course.premium
    @featured_courses = Course.featured
    

    如果您需要组合这些范围,也可以链接这些范围,以便您可以执行以下操作:

    @mixed_courses = Course.premium.featured
    

    正如其他人所解释的,Model.where() 通过在where("Write Pure SQL QUERIES HERE") 中传递 sql 来执行数据选择,其中常规 ruby​​ 可枚举方法 (.map) 遍历数组,该数组必须实例化为 ruby​​ 对象。这就是内存/性能问题受到打击的地方。如果您使用的是小型数据集,那没关系,但任何数据量大的东西都会变得丑陋。

    【讨论】:

    • 感谢您的回答
    • 我的回答-“这些范围也可以更改”错字应该是“这些范围也可以链接”。我的回答有什么不值得赞成的地方吗?谢谢
    猜你喜欢
    • 2020-04-22
    • 2011-04-13
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 2016-01-14
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多