Как перебирать атрибуты ActiveRecord, включая методы attr_accessor - PullRequest
6 голосов
/ 15 июня 2009

Я искал повсюду элегантное решение. Кажется, что существенная проблема заключается в том, что атрибуты ActiveRecord, которые сопоставляются со столбцами базы данных, обрабатываются в ActiveRecord :: Base совершенно иначе, чем методы attr_accessor.

Я бы хотел сделать что-то вроде:

model.attribute_names.each do |name|
  # do stuff
end

способом, который также включает поля attr_accessor, но не любые другие методы экземпляра. Я знаю это не встроенным, но какой самый элегантный способ сделать это?

Ответы [ 3 ]

9 голосов
/ 15 июня 2009

Вы не можете действительно решить это. Вы можете аппроксимировать хак, но это не то, что когда-либо будет хорошо работать.

model.attribute_names должен получить все ActiveRecord, но поля attr_accessor не являются полями. Это обычные рубиновые методы, и единственный способ получить их - model.instance_methods.

Идея 1

Вы можете сделать model.attribute_names + model.instance_methods, но тогда вам придется отфильтровать все другие обычные рубиновые методы initialize, save и т. Д., Что было бы непрактично.

Чтобы помочь отфильтровать instance_methods, вы можете сопоставить их с model.instance_variables (вам придется учитывать знак @ в переменных экземпляра вручную), но проблема в том, что переменные экземпляра не на самом деле существует вообще, пока не будет назначен.

Идея 2

В вашем environment.rb, прежде чем загрузится что-либо еще , определите свой собственный self.attr_accessor в ActiveRecord::Base. Это может затем обернуть базовый attr_accessor, но также сохранить имена атрибутов в личном списке. Тогда вы сможете выйти из этого списка позже. Тем не менее, я бы посоветовал против этого ... исправление основных языковых возможностей, таких как attr_accessor, гарантированно принесет вам много боли.

Идея 3

Определите свой собственный custom_attr_accessor в ActiveRecord::Base, который делает то же самое, что и идея 2, и используйте его в своем коде, где вы хотите иметь возможность получать имена атрибутов. Это было бы безопасно, так как вы больше не будете загромождать встроенный метод attr_accessor, но вам придется изменить весь код, чтобы использовать custom_attr_accessor там, где это необходимо

В общем, я думаю, что вы пытаетесь сделать, что нужно знать обо всех полях attr_accessor? Попробуйте взглянуть на свою проблему под другим углом, если можете.

3 голосов
/ 11 июня 2012

Я пришел сюда, чтобы сделать то же самое, и обнаружил, что это совершенно неправильный подход, благодаря ответу Ориона.

В случае, если чей-либо другой вариант использования похож на мой, вот мое решение. Я использовал attr_accessor, чтобы добавить дополнительные свойства к моделям после запроса их из ActiveRecord. Затем я хотел вывести результаты в формате JSON и т. Д.

Лучшее решение - сначала преобразовать модели из ActiveRecord в обычные хэши, а затем добавить свойства attr_accessor в качестве обычных хеш-ключей.

Пример:

model_hash = model_from_activerecord.attributes.to_options
model_hash[:key] = value
0 голосов
/ 16 декабря 2016

Решение, которое я нашел для себя, основано на ответе Ориона Эдвардса.

Код:

klass_attributes = klass.column_names + klass.instance_methods(false). map(&:to_s).keep_if{|a| a.include?('=')}.map{|a| a.sub('=', '')}

Разбивка:

klass.instance_methods(false) возвращает только методы экземпляра, а не наследуемые методы.

map(&:to_s) преобразует массив символов в массив строк, поэтому мы можем использовать метод include?. Также необходимо объединить массив строк, возвращаемых column_names.

keep_if{|a| a.include?('=')} удалит все строки в массиве, которые не имеют знака равенства. Это было важно, так как я заметил, что все атрибуты attr_accessor имеют '='. Пример: 'app_url' vs 'login_url ='

map{|a| a.sub('=', '')} - последний фрагмент, который затем удаляет '=' из каждой строки в массиве.

В результате вы получите массив строк, представляющих атрибуты, включая атрибуты attr_accessor.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...