带有 Rails 关联的 Ruby 发送方法 [英] Ruby send method with rails associations

查看:31
本文介绍了带有 Rails 关联的 Ruby 发送方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在忙于制作可排序的表格模块.我知道有些可能存在,但想获得自己做这件事的经验.我有这样的想法:

I have been messing about with making a sortable table module thing. I know some might exist but want to get experience doing this myself. I had the idea of have it like so:

SortedTable.new(ModelName, Hash_Of_Columns_And_Fields, ID)

示例

SortedTable.new(Post, {"Title" => "title", "Body" => "body", "Last Comment" => "comment.last.title"}, params[:id])

我打算做这样的事情:

def initialize(model, fields, id)
  data = {}
  model = model.capitalize.constantize
  model.find(id)
  fields.each do |column, field|
    data[column] = model.send(field)
  end
end

这适用于标题和正文,但是当使用 comment.last.title 获取 Last Comment 时,它会出错.我试过做 Post.send("comments.last.title") 但说 NoMethodError: undefined method 'comments.last.title' for #<Post:0x0000010331d220>

This works fine for title and body but when it comes to getting the Last Comment with comment.last.title it errors out. I have tried doing Post.send("comments.last.title") but says NoMethodError: undefined method 'comments.last.title' for #<Post:0x0000010331d220>

我知道我可以做 Post.send("comments").send("last").send("title") 并且可以,但我想不出怎么做通过获取字段并在 .然后链接发送.任何人都可以就如何做到这一点给我建议吗?如果我这样做也完全错误,那么请说或指向我做类似事情的代码的方向.我不是专业的 ruby​​ 开发人员,但我正在尝试.

I know I can do Post.send("comments").send("last").send("title") and that works but I can not think of how to do that dynamically by taking the fields and spliting the on . then chaining the sends. Can anyone give me advice on how to do this? If I am doing this completely wrong also then please say or point me in the direction of code that does something similar. I am not a expert ruby developer but I am trying.

P.S 上面的代码可能无法工作,因为我不在一台带有 ruby​​/rails 的计算机上进行测试,但希望你能理解这个概念.

P.S The above code might not work as I am not at a computer with ruby/rails to test, but hopefully you get the concept.

干杯

推荐答案

第一个也是最脏的解决方案是 eval

first and dirtiest solution is eval

fields.each do |column, field|
  data[column] = eval("#{model}.#{field}")
end

下一个更实用的解决方案

next solution little more functional

fields.each do |column, field|
  data[column] = field.split(".").inject(model){|obj, met| obj.send(met)}
end

附注

你的设计很丑

编辑

注入可以更简洁地写成field.split('.').inject(model, :send).而且我强烈反对 eval 方式——不必要的 evals 是另一种情况,你可以滑倒并允许任意代码执行,而且它们也很慢.(另外,我很确定应该只是 eval("model.#{field}") — 你不想插入 model 的字符串值. 另一个例子说明了 eval 表达式是多么容易.) – @Chuck

The inject can be written more concisely as field.split('.').inject(model, :send). And I'd strongly discourage the eval way — unnecessary evals are one more case where you can slip up and allow arbitrary code execution, and they're also slow. (Also, I'm pretty sure that should just be eval("model.#{field}") — you don't want to interpolate the string value of model. Yet another example of how easy it is to slip up an eval expression.) – @Chuck

这篇关于带有 Rails 关联的 Ruby 发送方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆