Какой правильный способ запуска одного контроллера действия от другого действия контроллера без перенаправления HTTP? -- ruby-on-rails пол Связанный проблема

What's the correct way to run one controller action from another controller action without an HTTP redirect?


10
vote

проблема

русский

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

Что я имею сейчас, это что-то вроде:

 <код> class OldController < ApplicationController   def old_controller_action     if should_use_new_controller       new_params = params.dup       new_params[:controller] = "new_controller_action"       redirect_to new_params       return     end     # rest of old and busted   end end  class NewController < ApplicationController   def new_controller_action     # new hotness   end end   

Это работает просто хорошо, но он выдает HTTP Redirect, который медленно. Я хотел бы иметь возможность сделать это то же самое, но в том же HTTP-запросе.

Есть ли чистый способ сделать это?

Редактировать: Щебень перейдет на кого-то, кто может показать мне чистый способ сделать это, что оставляет контроллеры и их действия относительно нетронутыми (кроме самого кода перенаправления).

Английский оригинал

I'd like to be able to dispatch from one controller action to another conditionally, based on a combination of query parameters and data in the database.

What I have right now is something like:

class OldController < ApplicationController   def old_controller_action     if should_use_new_controller       new_params = params.dup       new_params[:controller] = "new_controller_action"       redirect_to new_params       return     end     # rest of old and busted   end end  class NewController < ApplicationController   def new_controller_action     # new hotness   end end 

This works just fine, but it issues an HTTP redirect, which is slow. I'd like to be able to do this same thing, but within the same HTTP request.

Is there a clean way to do this?

Edit: The bounty will go to someone who can show me a clean way to do this that leaves the controllers and their actions relatively untouched (other than the redirect code itself).

</div
  

Список ответов

14
 
vote
vote
Лучший ответ
 

вместо вызова кода через действия, извлеките код на lib / или что-то и позвоните в этот код с обоих контроллеров.

 <код> # lib/foo.rb module Foo   def self.bar   # ...   end end  # posts_controller def index   Foo.bar end  # things_controller def index   Foo.bar end   
 

Instead of calling code across actions, extract the code to lib/ or something, and call that code from both controllers.

# lib/foo.rb module Foo   def self.bar   # ...   end end  # posts_controller def index   Foo.bar end  # things_controller def index   Foo.bar end 
</div
 
 
   
   
9
 
vote

Создайте экземпляр класса контроллера:

 <код> @my_other_controller = MyOtherController.new   

Тогда вызовите методы на нем:

 <код> @my_other_controller.some_method(params[:id])   

Я предпочитаю идею модуля, но это должно сделать трюк.

Вы также можете пройти параметры в целом из другого контроллера:

 <код> @my_other_controller.params = params   
 

Create an instance of the controller class:

@my_other_controller = MyOtherController.new 

Then call methods on it:

@my_other_controller.some_method(params[:id]) 

I prefer the module idea, but this should do the trick.

You can also pass parameters as a whole from another controller:

@my_other_controller.params = params 
</div
 
 
   
   
1
 
vote

Я подозреваю, что вы хотите вариант 3, но давайте сначала пройдем несколько альтернатив

Опция 1 - Нажмите логику выбора контроллера в помощник, который вставляет правильную ссылку на ваш взгляд. Бенситы - контроллеры остаются чистыми, минусами - если логика решения в зависимости от представленных ценностей, этот подход не будет работать. Если URL называется внешними веб-сайтами, то это не будет работать.

опция 2 - Нажмите логику обратно в свою модель. Pro's - держит контроллер чистый. Минусы - не работает хорошо, если у вас есть много сеансона, параметров или рендеринга / Redirect_to взаимодействия.

Опция 3 - оставаться в том же контроллере. Я подозреваю, что вы пытаетесь заменить некоторые существующие функциональные возможности с помощью новых функций, но только в некоторых случаях. Pro's - просто и иметь доступ ко всему вам нужно. Минусы - только работает, если имеет смысл использовать тот же контроллер I.e. Вы работаете с тем же объектом, таким как пользователь, место или компания.

Позволяет посмотреть пример для опции 3. Мои ссылки контроллер имеет совершенно отличное отведение для администраторов, чем другие пользователи ...

 <код> class LinksController < ApplicationController   #...    def new     #Check params and db values to make a choice here     admin? ? new_admin : new_user   end    #...  private    def new_admin     #All of the good stuff - can use params, flash, etc      render :action => 'new_admin'       end    def new_user     #All of the good stuff - can use params, flash, etc      render :action => 'new_user'    end  end   
 

I suspect you want option 3, but lets go through the some alternatives first

Option 1 - Push the controller selection logic into a helper that inserts the right link into your view. Benifits - controllers remain clean, Cons - if decision logic depending on submitted values this approach won't work. If URL is being called by external websites then this won't work.

Option 2 - Push the logic back into your model. Pro's - keeps controller clean. Cons - doesn't work well if you've got lots of sesson, params or render / redirect_to interaction.

Option 3 - Stay within the same controller. I suspect you are trying to replace some existing functionality with some new functionality, but only in some cases. Pro's - Simple and have access to everything you need. Cons - only works if it makes sense to use the same controller i.e. you're working with the same entity such as user, place or company.

Lets look an an example for option 3. My links controller has totally diferent behavour for admins than other users ...

class LinksController < ApplicationController   #...    def new     #Check params and db values to make a choice here     admin? ? new_admin : new_user   end    #...  private    def new_admin     #All of the good stuff - can use params, flash, etc      render :action => 'new_admin'       end    def new_user     #All of the good stuff - can use params, flash, etc      render :action => 'new_user'    end  end 
</div
 
 
0
 
vote

Если два контроллера пытаются сделать то же самое, есть очень хороший шанс, что это должно быть в модели. Хорошо посмотрите на свой дизайн и - извините, я не знаю, что ваш уровень опыта с MVC - читать на техниках тонкого контроллера:

http://weblog.jamisbuck.org/2006 / 10/18 / Skinny-Controller-Fat-модель http: // www. Robbyonrails.com/articles/2007/06/19/put-your-controllers-on-A-Diet-Already . http://andrzejonsoftware.blogspot.com/2008/ 07 / mvc-how-to-to-controllers.html

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

 

If two controllers are trying to do the same thing, there's a very good chance this should be in a model. Take a good look at your design and -- I'm sorry I don't know your experience level with MVC -- read up on thin controller techniques:

http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model http://www.robbyonrails.com/articles/2007/06/19/put-your-controllers-on-a-diet-already http://andrzejonsoftware.blogspot.com/2008/07/mvc-how-to-write-controllers.html

If the problem is that you need the other controller to do the render, then maybe the route should have pointed there to begin with, and still the skinny controller technique should save the day.

</div
 
 
0
 
vote

Если извлечение общего кода между контроллерами в модуль не работает для вас, я бы использовал стойку промежуточного программного обеспечения. Я не видел код, который использует ActiveRecord в пределах промежуточного программного обеспечения, но я не знаю по какой-либо причине, по которой не должно быть возможно, так как люди использовали <код> Redis и тому подобное.

В противном случае я думаю, что ваш единственный вариант будет перезапустить обработку запроса с чем-то вроде (непроверенно, псевдоа примеру):

 <код> env['REQUEST_URI'] = new_controller_uri_with_your_params call(env)   

Это похоже на то, как реализованы тесты в интеграции. Но я не знаю, если все от <Код> call до тех пор, пока вы не ударите контроллер, это Idempotent и безопасен, чтобы повторно повторно. Вы можете проследить через источник и увидеть. Но даже если сейчас это нормально, он может сломаться в любой будущей версии рельсов или стойки.

Использование промежуточного программного обеспечения позволяет избежать этого, позволив вам перехватить запрос до его запуска. Вы все еще должны быть в состоянии поделиться кодом приложению Rails, извлекая его в общие модули, включенные в обоих местах.

Честно говоря, я думаю, что просто простая вещь факторинга, который общий код контроллера, скорее всего, очиститель, но трудно узнать без деталей вашей ситуации, поэтому я подумал, что я пойду вперед и предложил это.

 

If extracting the common code between controllers into a module doesn't work for you, I would use Rack middleware. I haven't seen code that uses ActiveRecord within middleware but I don't know of any reason why it shouldn't be possible since people have used Redis and the like.

Otherwise I think your only option would be to restart processing of the request with something like (untested, pseudo example):

env['REQUEST_URI'] = new_controller_uri_with_your_params call(env) 

This is similar to how integration tests are implemented. But I don't know if everything from call until you hit a controller is idempotent and safe to rerun like this. You could trace through the source and see. But even if it's ok now, it might break in any future version of rails or rack.

Using middleware would avoid this by letting you intercept the request before it's been run. You should still be able to share code with your rails application by extracting it out into common modules included in both places.

Honestly I think just doing the simple thing of factoring the common controller code is likely cleaner, but it's hard to know without the details of your situation so I thought I'd go ahead and suggest this.

</div
 
 
-2
 
vote

Делай это:

 <код> class OldController < ApplicationController   def old_controller_action     if should_use_new_controller       new_controller_action     end     # rest of old and busted   end end   

и новый контроллер

 <код> class NewController < OldController   def new_controller_action     # new hotness   end end   
 

Do this:

class OldController < ApplicationController   def old_controller_action     if should_use_new_controller       new_controller_action     end     # rest of old and busted   end end 

and the new controller

class NewController < OldController   def new_controller_action     # new hotness   end end 
</div
 
 

Связанный проблема

6  Модели Activerecord кэшированы в заставленных граблях?  ( Activerecord models cached in rake tasks ) 
Я знаю, что в Rails 2.3.2 QuickeRecord запросы кэшированы, то есть вы можете увидеть что-то в журнале разработки / производства: <код> CACHE (0.0ms) SELEC...

3  Разделите данные сеанса между сайтами?  ( Share session data between sites ) 
Я работаю над многосемы, и я хотел бы разделить данные сеанса между двумя или более сайтами. У меня есть идентификатор сеанса, но какой лучший способ получить...

1  Логические ценности не "читают" в рельсах  ( Boolean values not being read in rails ) 
Я импортировал некоторые значения из Excel, используя ROO на логические поля в моем приложении Rails. В консоль рельсов Похоже, что все работает нормально, ...

0  Rails find_by_sql Не возвращая результаты  ( Rails find by sql not returning results ) 
Так что мой запрос, который я бегу, возвращает массив с идентификатором и ничего больше. Но когда я бегу один и тот же запрос в PSQL, он возвращает правильные...

1  Изучение Руби на рельсы "РПСПЕК"  ( Learning ruby on rails rspec ) 
Я подписан на примеру Рубиной книги Michael Hart, книга говорит вам, чтобы установить Bundle, а затем генерировать RSPEC: установить. Я бегу 3.0.4 Rails и 1.9...

3  Подавить ошибку при сохранении записи в рельсах  ( Suppress an error when saving a record in rails ) 
Я сохраняю данные в таблицу. <код> Question title:string author_id:integer description:text upvotes:integer Если значение «question.upvotes» сос...

11  Используйте PaperClip для сохранения изображений Base64, полученные из API  ( Use paperclip for saving base64 images obtained from an api ) 
У меня есть фото модель с атрибутом изображения. Изображение содержит строку Base64, полученную из API. Мне нужно запустить обратный вызов после_create, и я д...

0  WYSIWYG Веб-страница Редактор страницы  ( Wysiwyg web page editor ) 
Привет, я хочу использовать WYSIWYG Web Editor (редактор должен иметь вариант для добавления видео, изображений, PowerPoint и т. Д. ..) В моем приложении Rail...

0  Маршрутизация поддоменов в рельсах и главном участке  ( Subdomain routing in rails and main site ) 
Я пытаюсь установить следующее: www.domain.com идет на главный сайт (пользователь может зарегистрироваться, информацию о приложении) foo.domain.com отправ...

1  Rails link_to запрос params - выбор в элементе на следующей странице  ( Rails link to query params selecting in item on the next page ) 
прямо сейчас у меня <код> link_to . Похоже на кнопку пользователю. Это кнопка обновления, поэтому он направляет пользователь на страницу планов. Я не только...

23  Почему не приятно иметь первичный ключ на таблице присоединения?  ( Why is it not good to have a primary key on a join table ) 
Я смотрел на скринкаст, где автор сказал, что нехорошо, чтобы иметь первичный ключ на таблице присоединения, но не объяснил, почему. Таблица соединения в пр...

0  Как я могу переместить новую форму записи в связанные записи Show Page?  ( How can i move a new record form into a related records show page ) 
У меня есть 2 столы: местами и отзывы, где 1 место проведения могут иметь много отзывов, а отзыв принадлежит проведению. В настоящее время я добавляю отзывы о...

2  Можно #to_s когда-либо неудачу?  ( Can to s ever fail ) 
Я строю простую фабрику в Ruby, который возвращает <код> Callable (<код> Lambda в этом случае), который знает, как отличить имя прошедшего типа (например, к...

1  Включая метод помощника в тесте контроллера  ( Including helper method in controller test ) 
Как мне включить некоторого помощника в мой код ControlLer_Spec? У меня есть метод под названием «A_TITLE (ADS)» в Dates_ads_Helper и возвращает себя. Как исп...

4  JSON и CARIONWAVE IPHONE проблема [закрыто]  ( Json and carrierwave iphone problem ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> <Путь d = "M15 6.38A6.48 6.48 0 007.78. 04H-.02A6.49 6.49 0 002.05 ...