0

我对 Rails 比较陌生,所以我不知道我解决问题的方法是否正确,但它存在一些问题

我已经在我的 PC 上安装了 MySQL,但 Heroku 使用的是 PostgreSQL,所以我正在设计一个解决方案,以便在某些问题上同时使用这两种 DBMS。

我有下一个代码:

begin
   @products_with_valid_offers = Product.joins(:variants).active.discount_valid.discount_date_valid_mySQL

   rescue ActiveRecord::StatementInvalid
      @products_with_valid_offers = Product.joins(:variants).active.discount_valid.discount_date_valid_postgreSQL
end

范围是:

scope :active,  includes([:assets, :store]).where(:active => true, :deleted_at => nil, :stores => { :deleted_at => nil, :active => true }).order("products.created_at DESC")
scope :discount_date_valid_mySQL, where('DATE_FORMAT(NOW(),"%Y-%m-%d 23:59:59") + '" BETWEEN discount_from AND discount_to')
scope :discount_date_valid_postgreSQL, where('now()::date BETWEEN discount_from AND discount_to')

如您所见,我需要两种不同的表单来管理日期格式,每个 DBMS 都有一个。问题是流程永远不会进入异常。如果@products_with_valid_offers 是 MySQL 中的 SQL 错误,则永远不要进入救援块执行 PostgreSQL 行,它会返回错误。

一些帮助,请?:D

4

1 回答 1

0

你的引号搞砸了discount_date_valid_mySQL,你想说这个:

scope :discount_date_valid_mySQL, where("DATE_FORMAT(NOW(),'%Y-%m-%d 23:59:59') BETWEEN discount_from AND discount_to")

这至少是有效的 Ruby 代码。

也就是说,您当前的方法在各个方面都很糟糕:

  • 你确保你在生产中总是有例外。
  • 您在一个数据库之上进行开发,但在另一个数据库之上进行部署,仅此一项就会给您带来各种问题。
  • 您应该只date_format(now(), '%Y-%m-%d')在您的 MySQL 版本中使用。

可能还有其他问题,但无需花费更多时间来分解代码:有更好的方法。MySQL 和 PostgreSQL(甚至 SQLite)都支持current_date,所以你可以只使用一件事:

scope :discount_date_valid, where('current_date between discount_from and discount_to')

当然,假设您希望一切都假定为 UTC。如果你想让事情使用其他时区,那么:

  1. 将您的discount_from和存储discount_to为日期列,日期在 SQL 中没有时区。大概你已经这样做了,但我只是想确定一下。
  2. 调整您的范围以从您的客户端代码中获取当前日期(大概配置为使用正确的时区):

    def self.discount_date_valid
        where(':current_date between discount_from and discount_to', :current_date => Date.today)
    end
    

您必须对作用域使用类方法以确保Date.today在正确的时间对其进行评估(即在使用作用域时而不是在加载类时)。

如果您在 PostgreSQL 之上进行部署,那么您真的应该在 PostgreSQL 之上进行开发。您甚至应该确保在相同版本的 PostgreSQL 上进行开发和部署。在一个堆栈上进行开发并在另一个堆栈上进行部署会导致各种毫无意义的挫败感和困惑。

于 2012-08-22T03:24:50.197 回答