如何将动态生成的Mailer调用字符串转为可执行Ruby代码?
实现动态执行Mailer调用的Ruby方法
原方法仅拼接了执行语句的字符串,要实际触发Mailer调用,推荐使用常量解析+动态方法调用的方式(比eval更安全,可避免代码注入风险),具体修改如下:
def mail(mail_options) # 解析应用命名空间对应的常量类 application_namespace = mail_options[:application].capitalize.constantize # 提取Mailer类名并获取对应常量 mailer_prefix = mail_options[:template].split('/')[0] mailer_class = application_namespace.const_get("#{mailer_prefix}Mailer") # 获取要调用的模板方法名 template_method = mail_options[:template].split('/').second # 整理调用参数 email_params = mail_options[:params].values # 实际执行Mailer发送逻辑 mailer_class.send(template_method, *email_params).deliver_now end
关键修改说明
- 修正原代码的递归问题:原方法内直接用
mail[:application]会触发方法自身递归调用,改为显式传入mail_options参数 - 常量解析:用
constantize(Rails内置方法)将字符串命名空间转为实际类常量;纯Ruby环境可替换为Object.const_get - 动态方法调用:通过
send方法触发模板方法,用*将参数数组展开为方法的位置参数,避免字符串拼接的安全风险 - 直接执行发送:链式调用
deliver_now完成邮件发送,而非返回字符串语句
纯Ruby环境兼容调整
若未使用Rails框架,替换命名空间解析逻辑即可:
# 替换application_namespace的解析代码 application_namespace = Object.const_get(mail_options[:application].capitalize)
注意事项
- 确保
mail_options[:application]对应的命名空间真实存在,否则会抛出NameError mail_options[:template]需严格遵循"类前缀/方法名"格式,例如"test/test_name"对应TestMailer#test_name- 禁止使用
eval执行拼接字符串,防止恶意参数引发安全问题
内容的提问来源于stack exchange,提问作者TheGame
相关产品推荐
相关产品推荐

