开发者

Ruby send method with rails associations

开发者 https://www.devze.com 2023-04-04 04:09 出处:网络
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:

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)

example

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

I am planning to do something like:

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

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>

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 The above code might not work as I am not at a computer with ruby/rails to test, but hopefully you get the concept.

Cheers


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

PS

And your design is ugly

EDIT

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

0

精彩评论

暂无评论...
验证码 换一张
取 消