Use find to initialize a constant?

前端 未结 3 2082
终归单人心
终归单人心 2021-01-28 09:28

Something like this:

class Category

   SOME_CATEGORY = find_by_name(\"some category\")

end

Category::SOME_CATEGORY
tried wi

3条回答
  •  甜味超标
    2021-01-28 10:11

    It's not a terrible idea, but it's not really a good one either. It doesn't really fall in line with the way Rails does things. For one thing, you'll end up with a lot of ugly constant code. Too many ALL_CAPS_WORDS and your Ruby starts to look like C++. Bleah.

    For another, it's inflexible. Are you going to make one of these constants for every category? If you add a new category two months from now, will you remember to update your Rails code, add a new constant, redeploy it and restart your server?

    If it's important to you to be able to access categories very easily, and not repeat DB queries, here's a bit of metaprogramming that'll automatically look them up and create static methods like Lichtamberg's for you on first access:

    def self.method_missing(category, *args)  # The 'self' makes this a class method
      @categories ||= {}
      if (@categories[category] = find_by_name(category.to_s))
        class_eval "def self.#{category.to_s}; @categories[#{category}]; end" 
        return @categories[category]
      end
      super
    end
    

    With this method in place, whenever you first call Category.ham, it'll create a class method that returns the value of find_by_name("ham") -- so that neither the query nor method_missing() runs again the next time you call it. This is pretty much the way the OpenStruct class works, BTW; look it up in the Pickaxe book if you want to learn more.

    (Of course you'll still have the risk that, because these are all memoized, your Rails app won't reflect any changes you make to your category objects. This makes the assumption that changes won't happen or don't really matter. It's up to you to determine whether that assumption is valid for your app. You could always put an after_update callback in your code that resets @@categories if that's a problem; but at that point this starts to get complicated.)

提交回复
热议问题