瞎扯淡 在 Rails 的 Model 中定义 method_missing 覆盖了 AR 默认的肿么办……

cassiuschen · 2014年07月26日 · 最后由 cassiuschen 回复于 2014年07月27日 · 2228 次阅读

因为想给照片(image 模型)加入 EXIF,所以给 Image 加了叫 exif 的 hstore 项,然后不想费事写每一个单项的名称,所以想到了method_missing…… 写了一段:

def method_missing(m,*a)  
  if m.to_s =~ /=$/  
    self.exif[$`] = a[0] 
  else  
    raise NoMethodError, "#{m}这个方法你真的定义了嘛>~<人家木有找到耶……"  
  end  
end 

后果可想而知……AR 自带的attribute_methods被覆盖了…… 正在翻 AR 源码……不知有没有大神解决过类似问题…………

然后 Rei 大大提供了一种思路

def method_missing(m,*a)  
  if has_attributes? m
    super
  else
    # code here
  end
end 

虽然最后被报错嵌套过深……

AR 的 method_missing 会先判断有没有这个 方法,没有才生成。

你还是 image.exif[name] 这样用吧。

#1 楼 @Rei 但是在 Rails Console 里测试结果是这段是先于 AR 进行的……所以 attribute_methods 比如@image.title这些都丢失了呢……

#2 楼 @Rei 咦?image.exif[name]是什么用法?

#3 楼 @cassiuschen

大概这样

def method_missing(m,*a)  
  if has_attributes? m
    super
  else
    # code here
  end
end 

method_missing 很难 debug,建议避免。

#4 楼 @cassiuschen 不是 hstore 么。

#5 楼 @Rei 哇!谢谢!!原来还有这个 api……Rei 桑好厉害!!话说这都肿么发现这些用法的>~<

#7 楼 @cassiuschen hstore 映射过来是 Hash,所以应该像 Hash 那样用。

#7 楼 @cassiuschen "self.exif[$`] = a[0]" 你自己知道的嘛……

#9 楼 @Rei 啊明白了……

话说你用 hstore 不用这个 gem 的么? https://github.com/diogob/activerecord-postgres-hstore 除了[],还有很多查询都很方便。

#11 楼 @billy

If you are using Rails 4 you don't need this gem as ActiveRecord 4 provides HStore type support out of the box.

@Rei 对啊,我也是在 Rails 3 里面用过这个,习惯思维,哈哈。

#11 楼 @billy Rails 4 确实不用这个哈……只是偷懒而已>~<

exif 是个有限集合,可以不用 method_missing.

把需要的属性定义到一个 array 里面,然后 define_method 就好了,这样有一个好处就是想要显示什么属性什么是可控的。

#15 楼 @hisea 嗯……后来也这么干了……类似于:

def self.exif_include(*attrs)
  attrs.each do |attr|
    self.class_eval %Q{
      def #{attr}
        exif[:#{attr}]
      end

      def #{attr}=(something)
        exif[:#{attr}] = something
      end
    }
  end
end

exif_include :camera, :aperture 

这样实现了……

需要 登录 后方可回复, 如果你还没有账号请 注册新账号