【问题标题】:How can I improve this Rails code?如何改进这个 Rails 代码?
【发布时间】:2009-04-13 18:23:54
【问题描述】:

我正在编写一个小型浏览器游戏作为学习 RoR 的项目,我对它很陌生。

这是一个由 cronjob 定期调用的小方法。

我猜应该有一些方法可以将元素添加到药水数组中,然后在最后进行批量保存,我也不喜欢每次在循环中点击数据库来获取项目的数量再次进入市场。

def self.restock_energy_potions
  market = find_or_create_market

  potions = EnergyPotion.find_all_by_user_id(market.id)

  while (potions.size < 5)
    potion = EnergyPotion.new(:user_id => market.id)
    potion.save
    potions = EnergyPotion.find_all_by_user_id(market.id)
  end    
end

【问题讨论】:

    标签: ruby-on-rails ruby refactoring


    【解决方案1】:

    我不确定我是否理解您的问题。你在寻找这样的东西吗?

    def self.restock_energy_potions
      market = find_or_create_market   
      potions = EnergyPotion.find_all_by_user_id(market.id)
      (potions.size...5).each {EnergyPotion.new(:user_id => market.id).save }
      end    
    end
    

    注意范围内的三个点;如果已经有 5 个,你就不想制作药水了。

    另外,如果你的药水是链接的(例如通过has_many),你可以通过market.potions 属性创建它们(我在这里猜测,关于用户和市场之间的关系——细节取决于你的模型如何设置)并一次保存它们。不过,我认为节省的数据库不会很大。

    【讨论】:

    • 是的,这看起来很接近我想要的解决方案,但是有没有办法一次保存所有新药水?例如,创建您需要的额外 3 个,然后只进行一次数据库调用?还是只是想进行微优化?
    • @Kirchstein -- 是的,您可以通过将它们与 belongs_to / has_many 设置链接来做这些事情,但我认为它不会为您节省太多。充其量你会得到一个大的 INSERT INTO 而不是 1-5 个小的 INSERT INTO,但我怀疑效果是否可以测量。
    【解决方案2】:

    假设你的市场/用户has_many 药水,你可以这样做:

    def self.restock_energy_potions
      market = find_or_create_market
      (market.potions.size..5).each {market.potions.create(:user_id => market.id)}
    end
    

    【讨论】:

      【解决方案3】:

      a) 使用关联:

      class Market < AR::Base
        # * note that if you are not dealing with a legacy schema, you should
        #   rename user_id to market_id and remove the foreigh_key assignment.
        # * dependent => :destroy is important or you'll have orphaned records
        #   in your database if you ever decide to delete some market
        has_many :energy_potions, :foreign_key => :user_id, :dependent => :destroy
      end
      
      class EnergyPotion < AR::Base
        belongs_to :market, :foreign_key => :user_id
      end
      

      b) 添加后无需重新加载关联。也移动功能 进入模型:

      find_or_create_market.restock
      
      class Market
        def restock
          # * note 4, not 5 here. it starts with 0
          (market.energy_potions.size..4).each {market.energy_potions.create!}
        end
      end
      

      c) 还要注意创建!而不是创造。 你应该检测错误。 错误处理取决于应用程序。 在你的情况下,因为你从 cron 运行它,你可以做一些事情 *发送带有警报的电子邮件 * 捕获异常并记录它们,(exception_notifier 插件,或 hoptoad 托管服务) * 打印到 stderror 并配置 cron 以将错误发送到某些电子邮件。

       def self.restock_potions
          market = find_or_create
          market.restock
        rescue ActiveRecord::RecordInvalid
          ...
        rescue
          ...
        end
      

      【讨论】:

        猜你喜欢
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 2017-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多