Функция поиска или область действия, которые вы определили, определены в объекте 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}