Отношения ActiveRecord и объектная модель - PullRequest
1 голос
/ 12 апреля 2011

Привет, я недавно столкнулся с этим при попытке сделать следующее:

posts = User.first.posts
posts.find {|p| "p.id" == 123} => ActiveRecord::RecordNotFound: Couldn't find Post without an ID

Это пытается вызвать поиск ActiveRecord.Ожидается:

posts.find(123)

Но я не хочу снова запрашивать БД.Так что мне нужно сделать:

posts.to_a.find {|p| "p.id" == 123}

Я, хотя я имел дело с массивом, в соответствии с posts.class.Зачем мне вызывать to_a для него?

posts.class => Array
posts.superclass => ActiveRecord::Base

Почему я могу вызывать суперкласс для сообщений, если это (предположительно) экземпляр массива и почему он возвращает ActiveRecord :: Base?* Также:

posts.ancestors.include? ActiveRecord::Base => false

Почему это ложно, если ActiveRecord :: Base является суперклассом массива posts?

Еще один.Если я сделаю:

posts.instance_methods(false)

Возвращает методы экземпляра класса отношения, т.е. Post.Это кажется странным, так как posts - это Array.Точно так же, если я создаю «обычный» массив:

a = [1, 2]
a.instance_methods(false) => NoMethodError: undefined method `instance_methods' for [1, 2]:Array

Таким образом, массив, возвращаемый через запрос отношения ActiveRecord, похож на массив, но не ... похоже, он наследуется от ActiveRecord, ноне ... или что-то.Как раз тогда, когда я подумал, что хорошо понимаю объектную модель Ruby :) Может быть, полезный взгляд на ActiveRecord поможет.Я не уверен, поэтому я спрашиваю, наверное.

Это просто любопытство.Любая помощь / руководство приветствуется

Ответы [ 4 ]

2 голосов
/ 12 апреля 2011

Вы хотите:

posts.detect {|p| p.id == 123}

find - это псевдоним detect, но он затеняется методом find на прокси-сервере коллекции ActiveRecord, который вы получаете от posts.

0 голосов
/ 12 апреля 2011
posts.ancestors.include? ActiveRecord::Base => false

Ложь, потому что posts - это коллекция объектов Post, а не потомок ActiveRecord::Base. Любой отдельный элемент в коллекции сообщений будет потомком ActiveRecord::Base

0 голосов
/ 12 апреля 2011

Похоже, ActiveRecord::Base переопределяет метод #find, который вы хотите от Enumerable .Вот почему вам нужно преобразовать его в массив, который не имеет перезаписанного метода поиска.

0 голосов
/ 12 апреля 2011

Метод find доступен только в классе ActiveRecord :: Base. Это метод класса, а не метод экземпляра.

Да, это не совсем массив, но он ведет себя как Enumerable.

В этом случае вы можете использовать select

posts.select{|p| p.id == 123}.first

Я добавил .first в конце, потому что select вернет другой массив, будь то только с одним элементом.Надеюсь, это поможет.

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