Метод отправки Ruby с ассоциациями рельсов - PullRequest
0 голосов
/ 13 сентября 2011

Я возился с созданием сортируемого модуля таблицы. Я знаю, что некоторые могут существовать, но я хочу получить опыт, делая это сам. У меня была идея сделать это так:

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

Это прекрасно работает для заголовка и тела, но когда дело доходит до получения Last Comment с comment.last.title, это выдает ошибку. Я пытался сделать Post.send("comments.last.title"), но говорит NoMethodError: undefined method 'comments.last.title' for #<Post:0x0000010331d220>

Я знаю, что могу сделать Post.send("comments").send("last").send("title"), и это работает, но я не могу придумать, как сделать это динамически, взяв поля и разделив их на. затем приковывает цепочки Кто-нибудь может дать мне совет, как это сделать? Если я делаю это совершенно неправильно, то, пожалуйста, скажите или укажите мне направление кода, которое делает нечто подобное. Я не опытный разработчик ruby, но я пытаюсь.

P.S. Приведенный выше код может не работать, поскольку я не на компьютере с ruby ​​/ rails для тестирования, но, надеюсь, вы поняли концепцию.

Приветствия

1 Ответ

2 голосов
/ 13 сентября 2011

первое и самое грязное решение - eval

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

следующее решение чуть более функционально

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

PS

А твой дизайн уродливый

EDIT

Впрыск можно записать более кратко, как field.split('.').inject(model, :send). И я бы настоятельно не рекомендовал способ eval - ненужные evals - это еще один случай, когда вы можете ускользнуть и разрешить выполнение произвольного кода, и они также медленны. (Кроме того, я почти уверен, что это должно быть eval("model.#{field}") - вы не хотите интерполировать строковое значение model. Еще один пример того, как легко набрать выражение eval.) - @ Чак

...