Как работают вложенные ресурсы? - PullRequest
2 голосов
/ 05 августа 2011

На официальном сайте я определил две модели Post и Comment.Comment вложено в Post.

resources :posts do
  resources :comments
end

Так что я могу использовать @post.comments, чтобы получить доступ ко всем комментариям поста.В консоли:

$ post = Post.new()
$ post.comments.class
> Array

Но:

$ post.comments.respond_to?("build")
> true

Почему?Массив имеет метод build?Как сделали Rails?И как я могу узнать другие скрытые методы post.comments?

Ответы [ 2 ]

1 голос
/ 05 августа 2011

Во-первых, ваши resources вызовы находятся в вашем routes.rb файле, который имеет дело только с парсингом URL в Rails.Это никак не связано с ассоциациями между вашими моделями, которые настраиваются с помощью вызовов has_many и belongs_to в соответствующих файлах модели.Пока игнорируйте файл маршрутов, поскольку он не связан с основной частью вашего вопроса.

Что касается ассоциаций, вы обнаружите, что post.comments не возвращает вам Array, а фактически возвращаетActiveRecord::Relation объект.Relation объект подобен массиву - фактически любой вызываемый вами метод, который не привязан к отношению (например, build), фактически передается в Array представление Relation содержание.Поэтому, когда вы вызываете post.comments.length, объект ассоциации comments вызывает .length для своего внутреннего массива.

Одним из последствий этого является то, что вызов post.comments.class фактически передает .classтоже вызовите массив!

Итак, что же на самом деле может делать этот объект Relation?Поскольку связь устанавливается с помощью вызова has_many, вы можете найти в документации has_many .Аналогично для belongs_to ассоциации

0 голосов
/ 05 августа 2011

В ruby ​​вы можете добавить или изменить любой метод в любом объекте. Вы даже можете добавить новый метод к экземпляру строки, например:

x = "xyzzy"
x.name     # => NoMethodError: undefined method `name' for "xyzzy":String
x.instance_eval do
  class << self
    define_method(:name) {"I got a name"}
  end
end
x.class    # => String
x.name     # => "I got a name"

y = "other"
y.class    # => String
y.name     # => NoMethodError: undefined method `name' for "other":String

Этот метод build мог быть «добавлен» к экземпляру Array, возвращенному средством доступа comments, созданным макросом has_many. (Как указал Гарет, Rails немного усложнил ситуацию, и ассоциации не работают таким образом. Однако расширение объектов может быть более «чистым» способом по сравнению с работой в качестве прозрачного прокси. Рассмотрим мой пример как ruby , не рельсы)

Что касается второй части вашего вопроса, вы можете узнать методы данного объекта, обратившись к его функции methods. Он возвращает имена всех (открытых) методов, определенных для этого объекта. (Если вам нужны частные, см. Функцию private_methods.)

В моем примере x.methods будет включать также недавно определенный метод "name", но y.methods не будет.

В ruby ​​есть и другие функции, с помощью которых вы можете исследовать объекты. Вы можете найти их в документации Ruby API . API может иметь некоторые (обычно незначительные) изменения в различных версиях ruby. См. Документацию по используемой версии.

Если вы хотите изучить код какого-либо метода, то это может быть небольшой проблемой, поскольку «исполняемый код» функции может быть создан разными способами: это может быть копия (псевдоним) другой функции, она может быть создана динамически с помощью функции eval и т. Д.

Зная название метода, вы можете «найти» исходный код, который у вас есть, и, возможно, нужный метод не был создан динамически.

Я вижу, что проект ParseTree все еще жив. Может быть, вы найдете это полезным, если вы действительно хотите знать код функции, к которой у вас нет источников.

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