代码之家  ›  专栏  ›  技术社区  ›  zanona oldmanwiggins

rubyonrails-我应该为Album.first.photos覆盖哪个方法?

  •  2
  • zanona oldmanwiggins  · 技术社区  · 15 年前

    我已经超过了这个方法 find ActiveRecord::Base 很顺利,现在我可以很好地定制了。

    def self.find(*args)
      # my custom actions 
      super(*args)
    end
    

    然后

    Album.find(1) #=> My custom result
    

    Album.first.photos
    

    我在想一些专门用于关联查询的方法,但我不确定:(

    我需要对“ActiveRecord::Base”进行操作,建议使用动态类,这样就无法创建方法 photos 为此,我尝试了一种在所有模型中交互的方法。

    谢谢


    更新

    为了更好地解释我想要达到的目标:

    bit.ly 系统。但这是在飞行中完成的,只需声明 has_shortened :id 到您的模型,然后所有的接口和查询返回例如 DH3 12

    关注gem url http://github.com/ludicco/shortener 因此,你可以检查它,并随时提出想法,如果你认为这是一个好主意,你可能必须实施它。

    干杯

    4 回复  |  直到 5 年前
        1
  •  0
  •   edbond    15 年前

    看看友好的\u id插件( http://github.com/norman/friendly_id http://norman.github.com/friendly_id/file.Guide.html ),它执行您需要的操作:为模型生成自定义id别名。您可以定义自定义方法来生成slug。

    离开 模型中的字段

    class Album < ActiveRecord::Base
      has_friendly_id :short_id
    
      has_many :photos, :finder_sql => 'select * from photos where album_id="#{short_id}"'
    end
    
    >> Album.last.photos
    select * from photos where album_id="t54"
    
        2
  •  2
  •   Zargony    15 年前

    像您定义的关联访问器 has_many 在ActiveRecord中是非常复杂的事情。它们实际上使用反射类来返回一个代理对象,该代理对象的行为类似于模型类,但将其查找程序限制为外键(可能还有其他条件)。如果您想更深入地了解它,您可能需要查看ActiveRecord gem中的reflection.rb、associations.rb、associations/association\u proxy.rb和associations/association\u collection.rb。

    但是,最后,我们可以使用关联访问器,就好像它是类本身一样,ActiveRecord负责将所需的附加条件传递给类查找器。

    也就是说,如果你打电话 Album.first.photos ,幕后,ActiveRecord通话 Photo.find

    所以,如果你忽略了 照片.查找 ,如果您通过 相册.first.photos . 这就是ActiveRecord的魔力:)

    我的快速测试(使用Rails 2.3.8运行):

    class Album < ActiveRecord::Base
      has_many :photos
    end
    
    class Photo < ActiveRecord::Base
      belongs_to :album
    
      def self.find (*args)
        puts "XXX running custom finder"
        super
      end
    end
    

    Rails控制台:

    > Photo.all
    XXX running custom finder
    Photo Load (0.4ms)   SELECT * FROM "photos" 
    => [#<Photo id: 1, album_id: 1>, … ] 
    
    > Album.first.photos
    Album Load (0.4ms)   SELECT * FROM "albums" LIMIT 1
    XXX running custom finder
    Photo Load (0.3ms)   SELECT * FROM "photos" WHERE ("photos".album_id = 1) 
    => [#<Photo id: 1, album_id: 1>, … ] 
    
        3
  •  1
  •   kolrie    15 年前

    Album.first 返回Album的实例,您应该重写 photos Album 类本身:

    class Album < ActiveRecord::Base
    
      # ...
    
      def photos(*args)
        if my_condition_is_met
          // my custom handler
        else
          super
        end
      end
    
      # ...
    
    end
    

    现在,如果您确定每个模型实例都需要它,我宁愿将它隔离在一个模块上:

    module Photo
      def photos(*args)
        if my_condition_is_met
          // my custom handler
        else
          super
        end
      end
    end
    

    然后重新打开 ActiveRecord::Base

    class ActiveRecord::Base
      include Photo
    end
    

    通过这种方式,您的解决方案得到模块化,使其像一个“插件”。

    另一个不相关的注释: 你不必打电话 super(*args) ,因为只有 super 将传递您收到的所有参数。

    编辑: 次要格式

        4
  •  0
  •   seriousken    15 年前

    有什么特别的原因不能用关联扩展来实现这一点吗?

    http://ryandaigle.com/articles/2006/12/3/extend-your-activerecord-association-methods