meta_programming中的method_missing

本文深入探讨了 Ruby 的 ActiveRecord 模型中 find_by 方法的工作原理。通过源代码解析,揭示了该方法如何动态地根据属性查找记录,并将其应用于实际案例。


当你使用ruby的activerecord的时候,你是否会经常遇到以下的程序了


    Post.find_by_title("Awesomeness!")
    User.find_by_email("bob@example.com")
    User.find_by_email_and_login("bob@example.com", "bob")

那么这些程序是如何实现的呢? 


让我们来看一下源代码吧!


    class ActiveRecord::Base
      def method_missing(meth, *args, &block)
        if meth.to_s =~ /^find_by_(.+)$/
          run_find_by_method($1, *args, &block)
        else
          super # You *must* call super if you don't handle the
                # method, otherwise you'll mess up Ruby's method
                # lookup.
        end
      end

      def run_find_by_method(attrs, *args, &block)
        # Make an array of attribute names
        attrs = attrs.split('_and_')

        # #transpose will zip the two arrays together like so:
        #   [[:a, :b, :c], [1, 2, 3]].transpose
        #   # => [[:a, 1], [:b, 2], [:c, 3]]
        attrs_with_args = [attrs, args].transpose

        # Hash[] will take the passed associative array and turn it
        # into a hash like so:
        #   Hash[[[:a, 2], [:b, 4]]] # => { :a => 2, :b => 4 }
        conditions = Hash[attrs_with_args]

        # #where and #all are new AREL goodness that will find all
        # records matching our conditions
        where(conditions).all
      end
    end


当你执行find_by_mail 的时候,你发现class中没有这个函数定义, 这个时候系统就会转向method_missing 函数


进入函数就遇到一个正规表达式, 如果函数名开头是以find_by_开头的, 就当作匹配成功,这个时候就要执行run_find_by_method


而这个函数的参数里面出现了$1, 这个是用来获取  

/^find_by_(.+)$/ 括号里面的参数。

比如find_by_mail $1 = 'mail'

find_by_mail_and_login  $1 = 'mail_and_login'

函数进去之后,就先分割字符串

比如说 ‘mail_and_login’ 分割为 ['mail', 'login']

下一步就是对号入座

[['mail', 'login'], ['bob@163.com', 'bob']]

再将数组变换为hash

{ :mail => 'bob@163.com', :login => 'bob'}

是不是突然有一种ruby很高深的感觉了。。。。。。。。。。。。。。。。。。

### 关于 `meta_list` 的使用方法 在 TensorFlow 和其他框架中,`meta_list` 并不是一个标准的概念或对象名称。然而,在某些特定场景下,它可能被用来表示一组元数据(metadata),这些元数据可以描述模型的状态、参数或其他相关信息。 以下是关于如何创建和操作类似于 `meta_list` 的结构的一些常见方式: #### 创建 Meta List 示例 假设我们有一个列表来存储多个分类器的元数据信息,可以通过如下代码实现: ```python class ClassifierMeta: def __init__(self, name, accuracy, threshold): self.name = name self.accuracy = accuracy self.threshold = threshold def create_meta_list(): meta_list = [ ClassifierMeta(name="SVM", accuracy=0.85, threshold=0.7), ClassifierMeta(name="RandomForest", accuracy=0.92, threshold=0.6), ClassifierMeta(name="NeuralNetwork", accuracy=0.95, threshold=0.5) ] return meta_list meta_list = create_meta_list() for meta in meta_list: print(f"Classifier Name: {meta.name}, Accuracy: {meta.accuracy}, Threshold: {meta.threshold}") ``` 上述代码定义了一个简单的类 `ClassifierMeta` 来保存每个分类器的相关属性,并将其存入一个列表中[^1]。 --- #### 加载自定义 `.so` 文件并处理元数据 如果涉及加载动态链接库(`.so` 文件)并与之交互,则可以参考以下代码片段。此部分基于您提到的内容进行了扩展说明: ```python import tensorflow as tf # 动态加载 .so 库文件 lib_backproject = tf.load_op_library('backproject.so') # 解决 KeyError 报错问题[^2] # 假设 backproject.so 提供了一些函数接口用于处理元数据 def process_with_so(meta_list): processed_results = [] for meta in meta_list: result = lib_backproject.back_project( input_data=[meta.name], parameters={"accuracy": meta.accuracy, "threshold": meta.threshold} ) processed_results.append(result.numpy()) # 将返回的结果转换为 NumPy 数组以便进一步分析 return processed_results processed_output = process_with_so(create_meta_list()) print(processed_output) ``` 在此示例中,通过调用 `tf.load_op_library()` 方法成功加载了外部共享库 `backproject.so`,从而解决了之前遇到的 `KeyError` 错误。随后利用该库的功能对接收到的 `meta_list` 进行逐项处理。 --- #### 结合 NvDsAddClassifierMetaDataToObj 函数的应用 如果您正在开发与 NVIDIA DeepStream SDK 相关的应用程序,那么可能会频繁接触到像 `nvds_add_classifier_meta_to_object` 这样的 API 调用。下面展示了一种情景下的应用实例: ```c // 定义一个新的分类器元数据条目 NvDsInferClassInfo class_info; memset(&class_info, 0, sizeof(NvDsInferClassInfo)); strcpy(class_info.className, "Person"); // 初始化分类器元数据 NvDsClassifierMeta *classifier_meta = nvds_alloc_classifier_meta(); classifier_meta->numClasses = 1; classifier_meta->classes = g_new0 (NvDsInferClassInfo, classifier_meta->numClasses); memcpy(&(classifier_meta->classes[0]), &class_info, sizeof(NvDsInferClassInfo)); // 添加到目标对象上 nvds_add_classifier_meta_to_object(obj_meta, classifier_meta); ``` 以上 C/C++ 片段展示了如何向某个检测框的目标对象附加额外的分类器元数据。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值