Метод отправки Ruby с ассоциациями рельсов
Я возился с созданием сортируемого модуля таблицы. Я знаю, что некоторые могут существовать, но хочу получить опыт, делая это сам. У меня была идея сделать это так:
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, но я пытаюсь.
PS Приведенный выше код может не работать, поскольку я не на компьютере с ruby / rails для тестирования, но, надеюсь, вы поняли концепцию.
ура
1 ответ
Первое и самое грязное решение 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
И ваш дизайн уродлив
РЕДАКТИРОВАТЬ
Внедрение может быть написано более кратко, как field.split('.').inject(model, :send)
, И я бы сильно отговорил eval
путь - ненужный evals
Это еще один случай, когда вы можете ускользнуть и разрешить выполнение произвольного кода, и они также медленны. (Кроме того, я уверен, что это должно быть eval("model.#{field}")
- вы не хотите интерполировать строковое значение model
, Еще один пример того, как легко проскользнуть eval
выражение.) - @Chuck