Как определить функцию контроллера, которая работает для экземпляров любой модели - PullRequest
0 голосов
/ 20 апреля 2011

Реализация версий для приложения Rails. Мне бы хотелось иметь представление, отображающее все версии модели с некоторыми дополнительными функциями, такими как возврат и т. Д. Я использую камень paper_trail для управления версиями.

Я знаю, что мог бы сделать это, написав функцию контроллера, такую ​​как versions и представление для каждой модели, но я бы хотел сделать это для всех моделей одновременно. Это должно быть возможно, потому что атрибут model.versions всегда структурирован одинаково.

В идеале URL должен выглядеть как /pages/testpage/versions, тогда как testpage - это идентификатор страницы.

Это похоже на концепцию вложенных маршрутов в рельсах.

resources :pages do                                                    
    resources :versions                                                  
end

Проблемы с вложенными маршрутами, однако:

  • Требуется дополнительная конфигурация для модели
  • Я не могу получить доступ к testpage объекту, не зная, к какой модели он относится. Я также не смог найти способ определения модели, поскольку единственное, что предоставляется моему контроллеру версий, - это хэш параметров.

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

Ответы [ 2 ]

1 голос
/ 20 апреля 2011

Запишите его в ApplicationController и определите его как helper_method.

Например

class ApplicationController < ActionController::Base
  helper_method :current_time

  def current_time
    Time.now
  end
end

Теперь вы можете вызывать current_time везде в контроллерах или представлениях.

Также вы можете написать отдельный модуль / класс и определить там ваши вспомогательные методы.Чем вы должны включить этот файл в свой ApplicationController, а также

UPD после изменения темы

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

Вы должны создать новый ресурс вместо создания новой функциональности, которую будет сложно протестировать.Поэтому создайте новый ресурс (контроллер): версии и поэкспериментируйте с этим контроллером.

Например, как он может работать:

/versions/pages/132
/versions/comments/1003

Как его реализовать:

match "/versions/:model/:id", :to => "versions#index"

В вашем контроллере:

class VersionsController < ActionController::Base
  def index
    @object = my_type.find(params[:id])
    @versions = @object.versions
  end

  private
  def my_type
    params[:model].constantize
  end
end

Конечно, вы можете изменять маршруты так, как вы хотите:

match "/:model/:id/versions", :to => "versions#show"

Так что теперь ваша симпатичная /pages/testpage/versions будет работать нормально для вас без каких-либо новых странныхлогика.

UPD 2

Представьте, что вы получили этот маршрут:

match "/:model/:id/versions", :to => "versions#index", :as => :versions

И это объекты:

@page = Page.last
@hotel = Hotel.find(123)
@comment = @page.comments.first

Как мы будем создавать ссылки для версий:

<%= link_to "Versions of this page", versions_path(:model => @page.class.to_s, :id => @page.id) %>
<%= link_to "Versions of this hotel", versions_path(:model => @hotel.class.to_s, :id => @hotel.id) %>
<%= link_to "Versions of this comment", versions_path(:model => @comment.class.to_s, :id => @comment.id) %>
0 голосов
/ 20 апреля 2011

Я бы предложил передать параметр, такой как 'type', и указать там название модели. Тогда в вашем контроллере вы можете сделать:

class VersionsController < ApplicationController
  def index
    model = params[:type].classify.constantize
    @obj = model.find(params[:id])
  end
end

По вашим ссылкам вы можете передавать запросы помощнику link_to

<%= link_to versions_path(@model, :type => @model.class) %>

Или что-то в этом роде.

...