Rails 3 - неопределенный метод в определенных коллекциях - PullRequest
2 голосов
/ 12 марта 2011

У меня есть метод поиска, написанный для моей модели. Ссылка.

Мне удалось вызвать этот метод без ошибок до реализации голосования. Например, все это работает:

Link.search(params[:search])
current_user.links.search(params[:search])
current_account.links.search(params[:search])

Не работает следующее:

@links = current_user.votes.collect {|vote| vote.voteable}
@favorites = @links.search(params[:search])

и вернуть эту ошибку:

 undefined method `search' for #<Array:0x00000006919ac8>

Я провел некоторое тестирование, чтобы убедиться, что мой класс неправильный, в консоли:

links = user.votes.map {|vote| vote.voteable}
links.class
 => Array 
links.first.class
 => Link

Это не должно отличаться от моих рабочих примеров:

user.links.class
 => Array
user.links.first.class
 => Link

Я подумал, что, возможно, ошибка была в том, что я вызвал поиск по массиву, а не по ссылке. Но в предыдущих примерах я также вызывал его в массиве.

Я использую Vote_fu для обработки голосования, таким образом, голосование / голосование.

1 Ответ

8 голосов
/ 12 марта 2011

Функция поиска или область действия, которые вы определили, определены в объекте Link и могут использоваться в отношениях Link, но они не определены в простом массиве, что и возвращается в первом примере сбора.Вот простое различие:

class User
  scope :search, lambda{ |name| where(name: name) }
end

User.search('Kombo').all # Returns an array of the SQL result run against the DB
User.all.search('Kombo') # NoMethodError: undefined method `search' for #<Array:0x000001079b15b0>

В вашем первом примере, Link.search(params[:search]), вы выполняете эквивалент User.search.all, а User - это отношение / объект ActiveRecord в определенной области, что означает, что он может продолжатьбыть объединенным с другими областями, такими как, где, предел и группа.Во втором примере, @links = current_user.votes.collect {|vote| vote.voteable}, collect действует на такое отношение и возвращает простой массив, на который больше нельзя воздействовать с помощью этих функций с областями видимости.Второй пример подобен выполнению User.all.search.

. Это сбивает с толку, потому что оба эти примера в конечном итоге разрешаются в массив, но разница в том, что происходит перед этим разрешением в массиве, и когда вы на самом деле вызываетефункция поиска.Чтобы обойти это, вам нужно будет на самом деле вызвать область поиска или функцию для объекта ActiveRecord, например, Link или ActiveRecord Relation, например current_user.links, но вы не сможете вызвать его для результата.Просто чтобы уточнить:

Link.search(params[:search]) # will work
Link.all.search(params[:search]) # will not work

current_user.links.search(params[:search]) # will work
current_user.links.all.search(params[:search]) # will not work

current_account.links.search(params[:search]) # will work
current_account.links.all.search(params[:search]) # will not work

Когда вы звоните .collect, вы неявно звоните .all, что нарушает цепочку области видимости.Следующие две команды эквивалентны в этом отношении:

@links = current_user.votes.collect {|vote| vote.voteable}
@links = current_user.votes.all.collect {|vote| vote.voteable}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...