2010-10-22 2 views
0

Я использую Rails 2.3.2, но я уверен, что это относится и к более новым версиям. Я хотел бы определить пользовательское действие в ApplicationController. Однако я не хочу добавлять настраиваемый маршрут к каждому подклассу контроллера, который использует это действие. Есть простой способ сделать это?Наследование и маршрутизация пользовательского действия от ApplicationController в Rails

Моим первым наклонением было просто направить непосредственно на ApplicationController, так как этот метод не должен быть переопределен никакими подклассами. Но я не думаю, что Rails позволяет вам больше перейти на ApplicationController.

Кто-то предложил что-то вроде этого:

map.connect ":controller/:action", :controller => my_regex, :action => my_regex 

Но мне интересно, если это имеет потенциал конфликтует с или главенствующими другие маршруты? Или, если вообще лучший способ? Благодаря!

ответ

0

В конце концов я решил рассмотреть свой собственный js_form_builder собственный ресурс, поэтому у меня есть контроллер, который будет его доставлять. Контроллер принимает дополнительные параметры resource_name и id. Если при условии, что я могу создать экземпляр объекта, как так:

@object = params[:resource_name].classify.constantize.find(params[:id]) 

Тогда я просто ниспослать js.erb шаблон, который имеет все мои js_form_builder благость, содержащиеся внутри. Если экземпляр @object был создан, я могу создать form_for @object, затем пропустить его атрибуты и создать методы в объекте builder javascript, который будет возвращать входы для каждого атрибута, используя теги Rails FormBuilder для их создания.

Например:

window.FormBuilder = function() { 
    var builder = {}; 

    builder.form = function() { 
    var js = ""; 
    js += '<%= form_for @object do |f| %>'; 
    <% @object.attributes.each do |name, val| %> 
     var methodName = '<%= name.camelize(:lower) %>'; 
     <% if val.class == String %> 
     builder[methodName] = $('<%= f.text_field name.to_sym %>'); 
     <% end %> 
     <% if val.class == TrueClass || val.class == FalseClass %> 
     builder[methodName] = $('<%= f.check_box name.to_sym %> <%= f.label name.to_sym %>'); 
     <% end %>  
    <% end %> 
    js += '<% end %>'; 
    return $(js); 
    }; 

    builder.newForm = function() { 
    var js = ""; 
    js += '<%= form_for @object.class.new do |f| %>'; 
    js += '<% end %>'; 
    } 

    return builder; 
} 

Я не уверен, что в настоящее время, насколько полезны эти входы будут, так как я не могу думать о сценарии, где я бы не просто использовать html.erb для них. Но это было уверенно, что это заставило его работать! :)

0

Я не думаю, что это случай изменения ApplicationController, но для обезьяны-исправления кода в ActionDispatch::Routing включить новые действия, которые вы хотите. Это похоже на сумасшедшую вещь, которую можно сделать в схеме вещей, поскольку нет стандартного способа увеличения или расширения обычных действий REST. Надеюсь, у вас есть все основания для этого.

При просмотре кода вы можете увидеть, где определены действия по умолчанию, и вы можете ввести новый. Rails 3 имеет немного другую структуру, но идея та же:

class ActionDispatch::Routing::Mapper::Resources::Resource 
     ENHANCED_DEFAULT_ACTIONS = DEFAULT_ACTIONS + [ :myaction ] 

     def self.default_actions 
     ENHANCED_DEFAULT_ACTIONS 
     end 
    end 

Вы должны изменить ActionDispatch::Routing::Mapper::Resources#resources вести себя по-другому, тоже, но вы не указали, если вы говорите о коллекции, новый или тип действия члена, поэтому вам придется просто скопировать и изменить процедуру, чтобы вести себя так, как вы хотите.

+0

Причина, по которой я делаю это, - это то, что я хочу, чтобы мое приложение application.js могло выплюнуть теги формы Rails. Мое приложение тяжело в AJAX и js, и мне нужны централизованные методы, которые дают мне Rails-формы, входы и т. Д. В принципе, я пытаюсь создать JavaScript FormBuilder. Итак, в моем приложении application.js я сделаю вызов AJAX для своего пользовательского действия, которое отправит файл js.erb. Этот файл будет иметь класс FormBuilder с методами, которые дают мне html, сгенерированный с помощью меток builder. Поэтому, когда приложение application.js вызывает deleteWithAjax(), я могу создать форму Rails с тегом Rails. – Samo

+0

Это звучит довольно интересная идея, и это может сработать хорошо, но вопрос в том, почему это требует от таких стандартных действий REST расхождения. Вам действительно нужно определить JavaScript-респондентов для ваших методов, которые будут обрабатывать формы должным образом. Вероятно, вы могли бы сделать это намного проще, перехватывая и автоматически обрабатывая генерацию ответа .js, если шаблон не найден, чем путем введения новых действий. – tadman

+0

Это интересная мысль. Не могли бы вы указать мне пример этого? Во всех случаях до сих пор мой ответ на вызов ajax был либо шаблоном js.erb, либо json-объектом. Я хотел бы как возвращенные шаблоны js.erb, так и обработчики для ответов json иметь доступ к моему js form builder. Таким образом, сценарий без шаблонов может оказаться недостаточным. Возможно, другой альтернативой было бы сделать js_form_builder ресурсом, который реагирует только на get, и мой файл application.js может вызвать этот контроллер для загрузки компоновщика форм. – Samo

0

Если вы объявляете этот контроллер как ресурс, такой как map.resource, то вам придется использовать действия по умолчанию или создать свой собственный, добавив member или collection к этому ресурсу.

map.resources :post, :member => {:update_live_boolean => :post }, :collection => {:get_all_live_posts => :get} 

В противном случае, если у вас есть старый формат маршрутизации и не используется Rest

map.connect ':controller/:action/:id' 
    map.connect ':controller/:action/:id.:format' 

Тогда все, что вам нужно сделать, чтобы ссылки пользовательского контроллера обеспечивают :controller' and: Действие /: id` переменные при необходимости

<%= link_to "New Custom Controller", {:controller => "new_custom_controller", :action => "index"%> 
0

Это часть вашего поста, что меня беспокоит:

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

Сообщество рельсов справедливо становится все более осторожным в отношении чрезмерного определения ненужных маршрутов. Это становится все более распространенным, чтобы увидеть что-то вроде этого:

map.resources :comments, :only => [:new, :create] 

В приведенном выше примере, только new и create маршруты генерируются. Это лучшая безопасность и более чистая маршрутизация.Хотя я не отвечаю непосредственно на ваш вопрос о том, как сделать новый маршрут доступным для каждого ресурса, я говорю, что лучшие методы рельсов будут препятствовать этому. Добавьте настраиваемый маршрут только к ресурсам, которые будут его использовать.

+0

Я понимаю вашу озабоченность, но если я хочу, чтобы каждый контроллер использовал это настраиваемое действие, то кажется, что он излишне явно направлять его для каждого контроллера, нет? – Samo

+0

Честно говоря, я так не думаю. Потому что я не могу придумать ни одно приложение реального мира, где это необходимо * каждому * ресурсу. Кроме того, в приложении есть конечное количество маршрутов, обычно всего пара десятков. Поверьте, я действительно понимаю ваше желание сохранить ваш код СУХОЙ - я такой же. И я бы не ответил «без ответа», если бы не почувствовал себя сильным. Я понимаю раздражение чего-то, и люди говорят «просто не делай этого» :) –

Смежные вопросы