denisa
2008-Feb-28 14:47 UTC
Having a controller action call an action in a different controller
Does anyone know how to go about having a controller action call an action in a completely different controller? The reason for wanting to do this is that my Rails app has several actions that are common across all pages (these actions are part of the page layout, and these pages are produced by several different controllers). These actions modify the database. The app uses Ajax heavily to update the current page rather than performing a complete page refresh. The logic to update the current page is specific to the controller that originated the page. My rjs templates for the common actions currently have lots of conditional logic in them (for handling all the different pages that a common action can be called from), so I''m trying to find a better way of doing this (the current approach is not object oriented and is getting difficult to maintain). So, the pattern I would like to use is to have the common actions handled by a controller that knows how to update the database (but is view agnostic), and then delegating the rendering responsibilities (i.e. generate JavaScript via RJS for updating the current page) to the controller that originated the page. This is where the idea of having one controller call another controller comes into play. Here is a contrived example that demonstrates what I''m trying to accomplish: # Controller that allows a user to view and interact with widgets class WidgetViewController < ApplicationController def all_widgets # action that returns a list of all widgets # logic to set up the all_widgets rjs for displaying list of widgets # save off the controller and action which produced this view session[:current_controller] = "WidgetViewController" session[:current_action] = "all_widgets" end def refresh_all_widgets # logic to set up the refresh_all_widgets rjs for refreshing the current page end def recent_widgets # action that returns a list of widgets recently created # logic to set up the recent_widgets rjs for displaying list of recently created widgets # save off the controller and action which produced this view session[:current_controller] = "WidgetViewController" session[:current_action] = "recent_widgets" end def refresh_recent_widgets # logic to set up the refresh_recent_widgets rjs for refreshing the current page end end # Controller that handles common actions related to creating, editing and deleting widget models class WidgetController < ApplicationController def create # creates a widget in the database widget = Widget.new(params[:widget]) if ( widget.save() ) # delegate rendering responsibility to controller that originated the current page controller_class = eval(session[:current_controller]) controller = controller_class.new controller_refresh_action "refresh_#{session[:current_action]}" controller.send(controller_refresh_action) # call the "refresh" action to delegate rendering responsibilities else # appropriate error handling end end end The code above does end up calling the appropriate "refresh" action in the WidgetViewController, however it crashes down inside of Rails when trying to render that action. After digging into how Rails spins up a controller to service a request, I can see why this isn''t working - after instantiating a controller, Rails performs set up on the controller, and then passes it request and response objects. Thanks in advance, Denis --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Frederick Cheung
2008-Feb-28 14:58 UTC
Re: Having a controller action call an action in a different controller
On 28 Feb 2008, at 14:47, denisa wrote:> > Does anyone know how to go about having a controller action call an > action in a completely different controller? > > The reason for wanting to do this is that my Rails app has several > actions that are common across all pages (these actions are part of > the page layout, and these pages are produced by several different > controllers). These actions modify the database. The app uses Ajax > heavily to update the current page rather than performing a complete > page refresh. The logic to update the current page is specific to the > controller that originated the page. My rjs templates for the common > actions currently have lots of conditional logic in them (for handling > all the different pages that a common action can be called from), so > I''m trying to find a better way of doing this (the current approach is > not object oriented and is getting difficult to maintain). > > So, the pattern I would like to use is to have the common actions > handled by a controller that knows how to update the database (but is > view agnostic), and then delegating the rendering responsibilities > (i.e. generate JavaScript via RJS for updating the current page) to > the controller that originated the page. This is where the idea of > having one controller call another controller comes into play.I very much recommend you don''t do this. The common databasey stuff should be in models, you can share presentation stuff via helpers and shared partials. Fred> > > Here is a contrived example that demonstrates what I''m trying to > accomplish: > > # Controller that allows a user to view and interact with widgets > class WidgetViewController < ApplicationController > def all_widgets # action that returns a list of all widgets > # logic to set up the all_widgets rjs for displaying list of > widgets > > # save off the controller and action which produced this view > session[:current_controller] = "WidgetViewController" > session[:current_action] = "all_widgets" > end > > def refresh_all_widgets > # logic to set up the refresh_all_widgets rjs for refreshing > the current page > end > > def recent_widgets # action that returns a list of widgets > recently created > # logic to set up the recent_widgets rjs for displaying list > of recently created widgets > > # save off the controller and action which produced this view > session[:current_controller] = "WidgetViewController" > session[:current_action] = "recent_widgets" > end > > def refresh_recent_widgets > # logic to set up the refresh_recent_widgets rjs for > refreshing the current page > end > end > > # Controller that handles common actions related to creating, editing > and deleting widget models > class WidgetController < ApplicationController > def create # creates a widget in the database > widget = Widget.new(params[:widget]) > if ( widget.save() ) > # delegate rendering responsibility to controller that > originated the current page > controller_class = eval(session[:current_controller]) > controller = controller_class.new > controller_refresh_action > "refresh_#{session[:current_action]}" > controller.send(controller_refresh_action) # call the > "refresh" action to delegate rendering responsibilities > else > # appropriate error handling > end > end > end > > The code above does end up calling the appropriate "refresh" action in > the WidgetViewController, however it crashes down inside of Rails when > trying to render that action. After digging into how Rails spins up a > controller to service a request, I can see why this isn''t working - > after instantiating a controller, Rails performs set up on the > controller, and then passes it request and response objects. > > Thanks in advance, > Denis > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
AndyV
2008-Feb-28 17:48 UTC
Re: Having a controller action call an action in a different controller
If you want to consolidate the retrieval of data that''s necessary for the widgets to be displayed, it sounds like you want to abstract that into a module that you can include into your controller. From there, as Fred suggests, use partials and helpers to do the rendering. On Feb 28, 9:58 am, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On 28 Feb 2008, at 14:47, denisa wrote: > > > > > > > Does anyone know how to go about having a controller action call an > > action in a completely different controller? > > > The reason for wanting to do this is that my Rails app has several > > actions that are common across all pages (these actions are part of > > the page layout, and these pages are produced by several different > > controllers). These actions modify the database. The app uses Ajax > > heavily to update the current page rather than performing a complete > > page refresh. The logic to update the current page is specific to the > > controller that originated the page. My rjs templates for the common > > actions currently have lots of conditional logic in them (for handling > > all the different pages that a common action can be called from), so > > I''m trying to find a better way of doing this (the current approach is > > not object oriented and is getting difficult to maintain). > > > So, the pattern I would like to use is to have the common actions > > handled by a controller that knows how to update the database (but is > > view agnostic), and then delegating the rendering responsibilities > > (i.e. generate JavaScript via RJS for updating the current page) to > > the controller that originated the page. This is where the idea of > > having one controller call another controller comes into play. > > I very much recommend you don''t do this. The common databasey stuff > should be in models, you can share presentation stuff via helpers and > shared partials. > > Fred > > > > > Here is a contrived example that demonstrates what I''m trying to > > accomplish: > > > # Controller that allows a user to view and interact with widgets > > class WidgetViewController < ApplicationController > > def all_widgets # action that returns a list of all widgets > > # logic to set up the all_widgets rjs for displaying list of > > widgets > > > # save off the controller and action which produced this view > > session[:current_controller] = "WidgetViewController" > > session[:current_action] = "all_widgets" > > end > > > def refresh_all_widgets > > # logic to set up the refresh_all_widgets rjs for refreshing > > the current page > > end > > > def recent_widgets # action that returns a list of widgets > > recently created > > # logic to set up the recent_widgets rjs for displaying list > > of recently created widgets > > > # save off the controller and action which produced this view > > session[:current_controller] = "WidgetViewController" > > session[:current_action] = "recent_widgets" > > end > > > def refresh_recent_widgets > > # logic to set up the refresh_recent_widgets rjs for > > refreshing the current page > > end > > end > > > # Controller that handles common actions related to creating, editing > > and deleting widget models > > class WidgetController < ApplicationController > > def create # creates a widget in the database > > widget = Widget.new(params[:widget]) > > if ( widget.save() ) > > # delegate rendering responsibility to controller that > > originated the current page > > controller_class = eval(session[:current_controller]) > > controller = controller_class.new > > controller_refresh_action > > "refresh_#{session[:current_action]}" > > controller.send(controller_refresh_action) # call the > > "refresh" action to delegate rendering responsibilities > > else > > # appropriate error handling > > end > > end > > end > > > The code above does end up calling the appropriate "refresh" action in > > the WidgetViewController, however it crashes down inside of Rails when > > trying to render that action. After digging into how Rails spins up a > > controller to service a request, I can see why this isn''t working - > > after instantiating a controller, Rails performs set up on the > > controller, and then passes it request and response objects. > > > Thanks in advance, > > Denis--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
David Beckwith
2008-Apr-21 08:09 UTC
Re: Having a controller action call an action in a different controller
Here is a concrete example of how to create a class to help you render the same HTML content in different views, althought it doesn''t access the database. http://railscasts.com/episodes/101 Another thing that helps display *related* models in a different view is the plugin called attribute_fu. http://jamesgolick.com/tags/attribute_fu I guess the million dollar question is: How do you access a totally different unrelated model/data/ controller in a totally different view? For that, I think you would probably create something like the first example, but put it in the /lib directory and have it access the model of interest. Does anybody have a good concrete example of this online? Hope this helps. David :) On Feb 28, 10:48 am, AndyV <a...-HmMyXyqgL2CVc3sceRu5cw@public.gmane.org> wrote:> If you want to consolidate the retrieval of data that''s necessary for > the widgets to be displayed, it sounds like you want to abstract that > into a module that you can include into your controller. From there, > as Fred suggests, use partials and helpers to do the rendering. > > On Feb 28, 9:58 am, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > > > On 28 Feb 2008, at 14:47, denisa wrote: > > > > Does anyone know how to go about having a controller action call an > > > action in a completely different controller? > > > > The reason for wanting to do this is that my Rails app has several > > > actions that are common across all pages (these actions are part of > > > the page layout, and these pages are produced by several different > > > controllers). These actions modify the database. The app uses Ajax > > > heavily to update the current page rather than performing a complete > > > page refresh. The logic to update the current page is specific to the > > > controller that originated the page. My rjs templates for the common > > > actions currently have lots of conditional logic in them (for handling > > > all the different pages that a common action can be called from), so > > > I''m trying to find a better way of doing this (the current approach is > > > not object oriented and is getting difficult to maintain). > > > > So, the pattern I would like to use is to have the common actions > > > handled by a controller that knows how to update the database (but is > > > view agnostic), and then delegating the rendering responsibilities > > > (i.e. generate JavaScript via RJS for updating the current page) to > > > the controller that originated the page. This is where the idea of > > > having one controller call another controller comes into play. > > > I very much recommend you don''t do this. The common databasey stuff > > should be in models, you can share presentation stuff via helpers and > > shared partials. > > > Fred > > > > Here is a contrived example that demonstrates what I''m trying to > > > accomplish: > > > > # Controller that allows a user to view and interact with widgets > > > class WidgetViewController < ApplicationController > > > def all_widgets # action that returns a list of all widgets > > > # logic to set up the all_widgets rjs for displaying list of > > > widgets > > > > # save off the controller and action which produced this view > > > session[:current_controller] = "WidgetViewController" > > > session[:current_action] = "all_widgets" > > > end > > > > def refresh_all_widgets > > > # logic to set up the refresh_all_widgets rjs for refreshing > > > the current page > > > end > > > > def recent_widgets # action that returns a list of widgets > > > recently created > > > # logic to set up the recent_widgets rjs for displaying list > > > of recently created widgets > > > > # save off the controller and action which produced this view > > > session[:current_controller] = "WidgetViewController" > > > session[:current_action] = "recent_widgets" > > > end > > > > def refresh_recent_widgets > > > # logic to set up the refresh_recent_widgets rjs for > > > refreshing the current page > > > end > > > end > > > > # Controller that handles common actions related to creating, editing > > > and deleting widget models > > > class WidgetController < ApplicationController > > > def create # creates a widget in the database > > > widget = Widget.new(params[:widget]) > > > if ( widget.save() ) > > > # delegate rendering responsibility to controller that > > > originated the current page > > > controller_class = eval(session[:current_controller]) > > > controller = controller_class.new > > > controller_refresh_action > > > "refresh_#{session[:current_action]}" > > > controller.send(controller_refresh_action) # call the > > > "refresh" action to delegate rendering responsibilities > > > else > > > # appropriate error handling > > > end > > > end > > > end > > > > The code above does end up calling the appropriate "refresh" action in > > > the WidgetViewController, however it crashes down inside of Rails when > > > trying to render that action. After digging into how Rails spins up a > > > controller to service a request, I can see why this isn''t working - > > > after instantiating a controller, Rails performs set up on the > > > controller, and then passes it request and response objects. > > > > Thanks in advance, > > > Denis--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---