Nathan Roling
2006-Feb-14 07:59 UTC
[Rails] Teaching Models to Render Themselves in the Controller
I am trying to teach my models how to render themselves, i.e. <%= my_model_object.render() %> Let me explain my reasoning and proposed method before this gets shot down as anti-MVC. Let''s say I am writing a contact-management application. I have a class Contact. I will need to display this class all over the application. My first choice is to use a partial. Now I can render my Contact with: <% render_partial ''contact_view'', :contact => my_contact %> However, I start doing some ajax things, where I need to render a contact and return it with an AJAX call. So, I simply render the partial from my controller. Not too bad, as long as I can keep straight what partial to call and what locals I need to pass where. However, to make things a little easier on myself, I can create a helper method in the controller like this: helper_method :render_contact def render_contact(contact) render_partial(''contact_view'', :contact => my_contact) end I can now call this same function from my view to render the page initially, and from my controller to render new contacts for AJAX calls. The next step is where I''ve run into trouble. Instead of having all of these methods in the controller and calling out to them whenever I need a Contact rendered, how about sticking the methods right onto the model itself? Of course this breaks MVC if I put it on the model in the contact.rb file, the contact is no longer reusable in other places. But with ruby I''m supposed to be able to dynamically extend objects. So why not extend my contact in my controller, teaching it to render itself? In this way, different controllers could have different rendering code for a Contact, and the Contact class itself is never altered, but the code on my page goes from: <%= render_contact contact %> to <%= contact.render() %> and the controller AJAX code is likewise simplified. So that''s the what and why, but for the life of me, I cannot figure out the how. I am fairly new to ruby, and I think I''m supposed to be able to do something like def Contact def render() # render code goes here end end inside of the controller, but I cannot for the life of me to get it to work. If anyone call tell me how to do something like this, or if there''s some alternative method that''s just as clean, I''m all ears. Sorry for the longwinded message, but I felt that I should try to explain myself as clearly as possibly with something that looks on the surface to be a blatant breach of MVC. In case I haven''t been clear, or maybe just because it''s in my head and it''s late, here''s a metaphor I came up with: Imagine paratroopers getting ready to jump out of a plane. As they file towards the front of the plane, the officer hands them a parachute, which they then put on and jump out. On the way down they pull their own cord and parachute to safety. This is what I am trying to do, with the model objects being the soldiers, the officer being the controller, and the sky being the view. The method which I am trying to avoid is that of pushing the soldiers out of the plane, and then sending a parachute down after them. Thanks for even reading this far, if you have, Ozzi
Gregory Seidman
2006-Feb-14 13:31 UTC
[Rails] Teaching Models to Render Themselves in the Controller
On Tue, Feb 14, 2006 at 01:59:10AM -0600, Nathan Roling wrote: } I am trying to teach my models how to render themselves, i.e. } } <%= my_model_object.render() %> } } Let me explain my reasoning and proposed method before this gets shot } down as anti-MVC. [...] Having a model render itself would be anti-MVC in most languages, but... } The next step is where I''ve run into trouble. Instead of having all } of these methods in the controller and calling out to them whenever I } need a Contact rendered, how about sticking the methods right onto } the model itself? Of course this breaks MVC if I put it on the model } in the contact.rb file, the contact is no longer reusable in other } places. But with ruby I''m supposed to be able to dynamically extend } objects. So why not extend my contact in my controller, teaching it } to render itself? In this way, different controllers could have } different rendering code for a Contact, and the Contact class itself } is never altered, but the code on my page goes from: [...] ...you''re on the right track. } So that''s the what and why, but for the life of me, I cannot figure } out the how. I am fairly new to ruby, and I think I''m supposed to be } able to do something like } } def Contact } def render() } # render code goes here } end } end } } inside of the controller, but I cannot for the life of me to get it } to work. If anyone call tell me how to do something like this, or if } there''s some alternative method that''s just as clean, I''m all ears. [...] I''d say you should put them in your helper files, rather than your controller files. The helper files are part of the view layer. } Thanks for even reading this far, if you have, } Ozzi --Greg
Jay Levitt
2006-Feb-14 16:52 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
On Tue, 14 Feb 2006 08:31:08 -0500, Gregory Seidman wrote:> I''d say you should put them in your helper files, rather than your > controller files. The helper files are part of the view layer.Maybe the OP is saying something I was thinking last night - it''d be nice if helpers could provide methods to a model, so that you COULD create a helper for contact.render() instead of render_contact(contact). Just some syntactic sugar. Jay Levitt
Nick Stuart
2006-Feb-14 17:02 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
There''s nothing stopping you from doing this currently. All objects in ruby are open for modifacations, even instances of objects, not just the class definitions. You can add a method to one instance of an object and only that object will have it, -Nick On 2/14/06, Jay Levitt <jay+news@jay.fm> wrote:> On Tue, 14 Feb 2006 08:31:08 -0500, Gregory Seidman wrote: > > > I''d say you should put them in your helper files, rather than your > > controller files. The helper files are part of the view layer. > > Maybe the OP is saying something I was thinking last night - it''d be nice > if helpers could provide methods to a model, so that you COULD create a > helper for contact.render() instead of render_contact(contact). Just some > syntactic sugar. > > Jay Levitt > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Gregory Seidman
2006-Feb-14 17:20 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
On Tue, Feb 14, 2006 at 11:40:40AM -0500, Jay Levitt wrote: } On Tue, 14 Feb 2006 08:31:08 -0500, Gregory Seidman wrote: } } > I''d say you should put them in your helper files, rather than your } > controller files. The helper files are part of the view layer. } } Maybe the OP is saying something I was thinking last night - it''d be nice } if helpers could provide methods to a model, so that you COULD create a } helper for contact.render() instead of render_contact(contact). Just some } syntactic sugar. It certainly can. Suppose you have controllers/foo_controller.rb, helpers/foo_helper.rb, and models/foo.rb in your app directory. You don''t want to put the render method in the models/foo.rb or controllers/foo_controller.rb files because it belongs in the view rather than the model or controller, respectively. But if you put it in the FooHelper module in the helpers/foo_helper.rb then it winds up in the foo_controller class, and that''s not what you want either. Instead, your helpers/foo_helper.rb file looks like this: module FooHelper end class Foo def render #... end end When you are in views/foo/*.rhtml the helpers/foo_helper.rb file has clearly been loaded, right? So the Foo class (i.e. the model) will have the render method added to it. I''m not 100% certain of whether you need to specify the ActiveRecord::Base subclass in the helper file, but I suspect not. You may also want to add a require "foo" or "models/foo" or whatever to make sure the model has already been loaded. Play with it and see. Let me know how it turns out. } Jay Levitt --Greg
Tom Mornini
2006-Feb-14 17:28 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
On Feb 14, 2006, at 8:40 AM, Jay Levitt wrote:> On Tue, 14 Feb 2006 08:31:08 -0500, Gregory Seidman wrote: > >> I''d say you should put them in your helper files, rather than your >> controller files. The helper files are part of the view layer. > > Maybe the OP is saying something I was thinking last night - it''d > be nice > if helpers could provide methods to a model, so that you COULD > create a > helper for contact.render() instead of render_contact(contact). > Just some > syntactic sugar.Why not make a dispatcher method in helper, render() that cases object type, and either executes the valid code directly or as part of a specific render helper for the object type? def show(object) case object.class when User # render code for User # or show_user(object) when Blah # render code for Blah # or show_blah(object) else raise :YourVoiceStridently end end Then it''s just a syntax issue: contact.render -vs- show contact -- -- Tom Mornini
Ben Munat
2006-Feb-14 17:45 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
Tom, I enjoy your posts a lot, but I have to respectfully disagree here... I think adding behavior to the object to which it belongs is always the better choice over starting a never-ending case statement. I hope Ozzi will try the model-extending approach that Greg suggested and let us know how it goes! b Tom Mornini wrote:> On Feb 14, 2006, at 8:40 AM, Jay Levitt wrote: > >> On Tue, 14 Feb 2006 08:31:08 -0500, Gregory Seidman wrote: >> >>> I''d say you should put them in your helper files, rather than your >>> controller files. The helper files are part of the view layer. >> >> >> Maybe the OP is saying something I was thinking last night - it''d be >> nice >> if helpers could provide methods to a model, so that you COULD create a >> helper for contact.render() instead of render_contact(contact). Just >> some >> syntactic sugar. > > > Why not make a dispatcher method in helper, render() that cases object > type, and either executes the valid code directly or as part of a specific > render helper for the object type? > > def show(object) > case object.class > when User > # render code for User > # or show_user(object) > when Blah > # render code for Blah > # or show_blah(object) > else > raise :YourVoiceStridently > end > end > > Then it''s just a syntax issue: > > contact.render > > -vs- > > show contact >
Tony Collen
2006-Feb-14 17:53 UTC
[Rails] Teaching Models to Render Themselves in the Controller
On 2/14/06, Nathan Roling <ozzilee@gmail.com> wrote: Imagine paratroopers getting ready to jump out of a plane. As they> file towards the front of the plane, the officer hands them a > parachute, which they then put on and jump out. On the way down they > pull their own cord and parachute to safety. This is what I am trying > to do, with the model objects being the soldiers, the officer being > the controller, and the sky being the view. The method which I am > trying to avoid is that of pushing the soldiers out of the plane, and > then sending a parachute down after them. >This is a good metaphor but MVC webapps is nothing like parachuting :) Tony -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060214/b3d0c960/attachment.html
Tom Mornini
2006-Feb-14 19:18 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
On Feb 14, 2006, at 9:47 AM, Ben Munat wrote:> Tom, I enjoy your posts a lot, but I have to respectfully disagree > here... I think adding behavior to the object to which it belongs > is always the better choice over starting a never-ending case > statement. > > I hope Ozzi will try the model-extending approach that Greg > suggested and let us know how it goes!Hey, I largely agree with you Ben, so don''t sweat the disagreement! It''s like the choosing the worst of two evils. :-( If the case just distributes to helper methods, then it''s not such an ugly thing... P.S. I think Greg''s extension was to be handled in application.rb. If that''s the case, I just ran into an issue with such things, in that those modifications WILL NOT be available to the models when firing up a console, and unit tests likely won''t be able to hit them either. -- -- Tom Mornini
Gregory Seidman
2006-Feb-14 19:55 UTC
Rails improvements (was Re: [Rails] Re: Teaching Models to Render Themselves in the Controller)
On Tue, Feb 14, 2006 at 11:18:29AM -0800, Tom Mornini wrote: [...] } P.S. I think Greg''s extension was to be handled in application.rb. If } that''s the case, I just ran into an issue with such things, in that those } modifications WILL NOT be available to the models when firing up a } console, and unit tests likely won''t be able to hit them either. I was suggesting putting them in helpers/<controller>_helper.rb, actually. I''m not sure how that affects the console or unit tests, but the point is to make the methods available in views and nowhere else. Now that Rails 1.0 is out and solid, it might be time to start thinking about what should go into 1.1 (or 2.0). I''d suggest that the directories under app should be split up more. The helpers directory should be renamed something clearer (controller_render_helpers, or something more concise) and that there should be another directory of "helpers" for models, which would suit this need perfectly. Okay, I''m on a roll now. Consider the following directory structure within app: controllers controllers/render models models/validation models/render views views/layouts The models/render, controllers/render, and models/validation directories contain modules which are automatically included in the associated model or controller as appropriate for the context. The controllers/render directory is essentially identical to the existing helpers directory. Of course, this may not make sense. Please comment. } -- Tom Mornini --Greg
Nathan Roling
2006-Feb-14 22:01 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
First of all, thanks for all the replies. Sorry I haven''t been able to get back until now. Greg, I like your idea, I think it''ll work great. Unfortunately, being the newbie I am, I''ve run into a problem I haven''t quite figured a way around. First of all my helper class (foo.rb): class Foo < Foo.superclass def render "Test." end end This seems to work great -- I can call the method in my view for normal page rendering, and in my controller for AJAX rendering. (I needed to add the "< Foo.superclass" because i was getting a parent class mismatch or some such. "< ActiveRecord::Base" would work the same, I just think this is cleaner.) However, if I try to do: class Foo < Foo.superclass def render render_partial ''foo_partial'' end end I get a method not found error. Of course this makes sense, but what is the cleanest way of including the render_partial method there? I suspect it has something to do with blocks or closures. Could I somehow define the render() method inside the helper method where render_partial is available and then attach it back to the class? Or is there a simpler way? Like I said, I''m new at ruby, and I''m coming off doing mostly java, so I''m not really sure about how some of these things work. I appreciate all of the help though, thanks :-) Ozzi On Feb 14, 2006, at 11:20 AM, Gregory Seidman wrote:> On Tue, Feb 14, 2006 at 11:40:40AM -0500, Jay Levitt wrote: > } On Tue, 14 Feb 2006 08:31:08 -0500, Gregory Seidman wrote: > } > } > I''d say you should put them in your helper files, rather than your > } > controller files. The helper files are part of the view layer. > } > } Maybe the OP is saying something I was thinking last night - it''d > be nice > } if helpers could provide methods to a model, so that you COULD > create a > } helper for contact.render() instead of render_contact(contact). > Just some > } syntactic sugar. > > It certainly can. Suppose you have controllers/foo_controller.rb, > helpers/foo_helper.rb, and models/foo.rb in your app directory. You > don''t > want to put the render method in the models/foo.rb or > controllers/foo_controller.rb files because it belongs in the view > rather > than the model or controller, respectively. But if you put it in the > FooHelper module in the helpers/foo_helper.rb then it winds up in the > foo_controller class, and that''s not what you want either. Instead, > your > helpers/foo_helper.rb file looks like this: > > module FooHelper > end > > class Foo > def render > #... > end > end > > When you are in views/foo/*.rhtml the helpers/foo_helper.rb file has > clearly been loaded, right? So the Foo class (i.e. the model) will > have the > render method added to it. I''m not 100% certain of whether you > need to > specify the ActiveRecord::Base subclass in the helper file, but I > suspect > not. You may also want to add a require "foo" or "models/foo" or > whatever > to make sure the model has already been loaded. Play with it and > see. Let > me know how it turns out. > > } Jay Levitt > --Greg > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Gregory Seidman
2006-Feb-14 22:55 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
On Tue, Feb 14, 2006 at 04:00:06PM -0600, Nathan Roling wrote: [...] } First of all my helper class (foo.rb): } } class Foo < Foo.superclass } def render } "Test." } end } end } } This seems to work great -- I can call the method in my view for } normal page rendering, and in my controller for AJAX rendering. } } (I needed to add the "< Foo.superclass" because i was getting a } parent class mismatch or some such. "< ActiveRecord::Base" would work } the same, I just think this is cleaner.) Excellent! I thought it would work and I''m glad it did. Also, I like the elegance of using Foo.superclass. } However, if I try to do: } } class Foo < Foo.superclass } def render } render_partial ''foo_partial'' } end } end } } I get a method not found error. Of course this makes sense, but what } is the cleanest way of including the render_partial method there? I } suspect it has something to do with blocks or closures. Could I } somehow define the render() method inside the helper method where } render_partial is available and then attach it back to the class? Or } is there a simpler way? [...] Well, render_partial is a method of the ActionController::Base class (i.e. the base class of all controllers). What you might try doing is making render take an argument, and calling render with self, e.g.: <%= @foo.render(self) %> ...and define render as: class Foo < Foo.superclass def render(controller) controller.render_partial ''foo_partial'' end end No guarantees that this will work, but it''s worth a try. } Ozzi --Greg
Jim Nicholson
2006-Feb-14 23:31 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
Tony Collen wrote:> On 2/14/06, Nathan Roling <ozzilee@gmail.com> wrote: > > Imagine paratroopers getting ready to jump out of a plane. As they >> file towards the front of the plane, the officer hands them a >> parachute, which they then put on and jump out. On the way down they >> pull their own cord and parachute to safety. This is what I am trying >> to do, with the model objects being the soldiers, the officer being >> the controller, and the sky being the view. The method which I am >> trying to avoid is that of pushing the soldiers out of the plane, and >> then sending a parachute down after them. >> > > This is a good metaphor but MVC webapps is nothing like parachuting :) > > TonyI think the metaphor might work with some tweaking. Let''s say that rather than the officer, the *pilot* is the controller. How MVC works is this: The pilot calls back to the soldiers and tells them to jump, then - without checking to see if they''ve left the plane - he flys in a loop back around to where he *thinks* they will be falling, and throws open parachutes out of the plane to catch them. :) -- Posted via http://www.ruby-forum.com/.
Nathan Roling
2006-Feb-14 23:33 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
I''ll try that, unfortunately I think it kind of defeats the elegance I''m going for in the page, i.e. <=% foo.render() %> as opposed to <% foo.render(@controller) %> or whatever it would work out to. I won''t get a chance to play with it until tomorrow sometime, so maybe I can build off of that into something more elegant. But if anyone has any ideas, please, keep them coming. As always, thanks for the help. I''ll let you know what I come up with when I get a chance to play with it. On Feb 14, 2006, at 4:55 PM, Gregory Seidman wrote:> On Tue, Feb 14, 2006 at 04:00:06PM -0600, Nathan Roling wrote: > [...] > } First of all my helper class (foo.rb): > } > } class Foo < Foo.superclass > } def render > } "Test." > } end > } end > } > } This seems to work great -- I can call the method in my view for > } normal page rendering, and in my controller for AJAX rendering. > } > } (I needed to add the "< Foo.superclass" because i was getting a > } parent class mismatch or some such. "< ActiveRecord::Base" would > work > } the same, I just think this is cleaner.) > > Excellent! I thought it would work and I''m glad it did. Also, I > like the > elegance of using Foo.superclass. > > } However, if I try to do: > } > } class Foo < Foo.superclass > } def render > } render_partial ''foo_partial'' > } end > } end > } > } I get a method not found error. Of course this makes sense, but what > } is the cleanest way of including the render_partial method there? I > } suspect it has something to do with blocks or closures. Could I > } somehow define the render() method inside the helper method where > } render_partial is available and then attach it back to the class? Or > } is there a simpler way? > [...] > > Well, render_partial is a method of the ActionController::Base > class (i.e. > the base class of all controllers). What you might try doing is making > render take an argument, and calling render with self, e.g.: > > <%= @foo.render(self) %> > > ...and define render as: > > class Foo < Foo.superclass > def render(controller) > controller.render_partial ''foo_partial'' > end > end > > No guarantees that this will work, but it''s worth a try. > > } Ozzi > --Greg > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Kevin Olbrich
2006-Feb-14 23:47 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
On Tuesday, February 14, 2006, at 4:00 PM, Nathan Roling wrote:> class Foo < Foo.superclass > def render > render_partial ''foo_partial'' > end > endTry def render render :partial=>''foo_partial'' end make sure you name the file ''_foo_partial'' _Kevin -- Posted with http://DevLists.com. Sign up and save your time!
Nathan Roling
2006-Feb-15 20:14 UTC
[Rails] Re: Teaching Models to Render Themselves in the Controller
> Well, render_partial is a method of the ActionController::Base > class (i.e. > the base class of all controllers). What you might try doing is making > render take an argument, and calling render with self, e.g.: > > <%= @foo.render(self) %> > > ...and define render as: > > class Foo < Foo.superclass > def render(controller) > controller.render_partial ''foo_partial'' > end > endNo dice. First of all, render_partial is a protected method. Trying to get around that, I made a public method in the controller that would call the partial, but then I get an error to the effect of only one render being allowed at a time. So at this point I really seems stuck to doing all of my render calls from the controller or helper. This still leaves me with my base problem, and maybe there''s an easier answer. I want to be able to call the same method in the view and the controller to render a block of HTML. In the view I need it for initial page rendering, and in the controller I need it for AJAX calls. The only way I have found to do this is by defining my method in the controller and using ":helper_method" to export it to the view. It works, but it just seems messy/wrong. I would rather put the code in the helper, but there doesn''t seem to be a way to call it from the controller. Tacking the code onto the model seemed like a good way to go, but I don''t seem to be able to figure out a way to do that either. So for now I''m going to stick with putting my methods in the controller and exporting them with ":helper_method", but if someone came up with a cleaner way I would definitely like to hear it. Thanks everyone for the help, Ozzi
Justin Forder
2006-Feb-18 13:51 UTC
[Rails] Teaching Models to Render Themselves in the Controller
Tony Collen wrote:> > > On 2/14/06, *Nathan Roling* <ozzilee@gmail.com > <mailto:ozzilee@gmail.com>> wrote: > > Imagine paratroopers getting ready to jump out of a plane. As they > file towards the front of the plane, the officer hands them a > parachute, which they then put on and jump out. On the way down they > pull their own cord and parachute to safety. This is what I am trying > to do, with the model objects being the soldiers, the officer being > the controller, and the sky being the view. The method which I am > trying to avoid is that of pushing the soldiers out of the plane, and > then sending a parachute down after them. > > > This is a good metaphor but MVC webapps is nothing like parachuting :)This suggests wrapping the model with a renderer which has an appropriate to_s implementation, and giving the wrapper to the view. regards Justin
Tony Collen
2006-Feb-18 16:13 UTC
[Rails] Teaching Models to Render Themselves in the Controller
On 2/18/06, Justin Forder <justin@justinforder.me.uk> wrote:> Tony Collen wrote: > > This is a good metaphor but MVC webapps is nothing like parachuting :) > > This suggests wrapping the model with a renderer which has an > appropriate to_s implementation, and giving the wrapper to the view.Which brings up the question, is #to_s the appropriate place for something to convert itself to HTML? Perhaps #to_html would be more correct. Tony
Ben Munat
2006-Feb-18 18:20 UTC
[Rails] Teaching Models to Render Themselves in the Controller
Tony Collen wrote:> On 2/18/06, Justin Forder <justin@justinforder.me.uk> wrote: > >>Tony Collen wrote: >> >>>This is a good metaphor but MVC webapps is nothing like parachuting :) >> >>This suggests wrapping the model with a renderer which has an >>appropriate to_s implementation, and giving the wrapper to the view. > > > > Which brings up the question, is #to_s the appropriate place for > something to convert itself to HTML? Perhaps #to_html would be more > correct. >The only problem there is what if you need different html representations of the same model object... like a "view" representation vs. an "edit" representation? Another idea -- something I''ve toyed with in Java -- is to "domify" the model object. I noticed there''s an xml-mapping gem that maps Ruby objects to xml and back. So, you map the object to xml, and then use a variety of xslt''s to create the various html representations you want. The hard part there looks like doing the xslt''s... there don''t appear to be any xslt gems and the only other xslt for ruby I could find is distributed as c source code. :-( b
Justin Forder
2006-Feb-18 21:35 UTC
[Rails] Teaching Models to Render Themselves in the Controller
Tony Collen wrote:> On 2/18/06, Justin Forder <justin@justinforder.me.uk> wrote: >> Tony Collen wrote: >>> This is a good metaphor but MVC webapps is nothing like parachuting :) >> This suggests wrapping the model with a renderer which has an >> appropriate to_s implementation, and giving the wrapper to the view. > > > Which brings up the question, is #to_s the appropriate place for > something to convert itself to HTML? Perhaps #to_html would be more > correct.Sorry if I didn''t understand the context (I''m still catching up on an 800-message backlog), but I assumed that the view was ERB, in which case to_s is what is going to be called. regards Justin
Luke Redpath
2006-Feb-18 22:14 UTC
[Rails] Teaching Models to Render Themselves in the Controller
I''m not sure I see what problem you are having here. Firstly, a model should know nothing about rendering. It is not a models responsibility to render itself. Rendering belongs in the view, even if you use renderer classes to render your models. This is all about good design and loose coupling. If you want to render something in a normal view and in response to an AJAX call, have you considered upgrading to Edge Rails and using RJS templates? They would seem like the perfect solution. Cheer Luke Redpath On 2/18/06, Justin Forder <justin@justinforder.me.uk> wrote:> > Tony Collen wrote: > > On 2/18/06, Justin Forder <justin@justinforder.me.uk> wrote: > >> Tony Collen wrote: > >>> This is a good metaphor but MVC webapps is nothing like parachuting :) > >> This suggests wrapping the model with a renderer which has an > >> appropriate to_s implementation, and giving the wrapper to the view. > > > > > > Which brings up the question, is #to_s the appropriate place for > > something to convert itself to HTML? Perhaps #to_html would be more > > correct. > > Sorry if I didn''t understand the context (I''m still catching up on an > 800-message backlog), but I assumed that the view was ERB, in which case > to_s is what is going to be called. > > regards > > Justin > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Cheers, Luke Redpath www.lukreedpath.co.uk -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060218/6c8c63ea/attachment.html
Eric Hodel
2006-Feb-18 22:55 UTC
[Rails] Teaching Models to Render Themselves in the Controller
On Feb 13, 2006, at 11:59 PM, Nathan Roling wrote:> I am trying to teach my models how to render themselves, i.e. > > <%= my_model_object.render() %>Bad idea. [...]> <% render_partial ''contact_view'', :contact => my_contact %>[why you think this is bad] Agreed, much to clumsy. [...]> <%= render_contact contact %>Good idea, but not generic enough. I had a similar thought, a model should know its URL. I did it this way: http://blog.zenspider.com/archives/2005/12/overriding_url.html Following that approach, it is better to teach controllers how to render models: <%= render :model => contact %> Where you use inheritance (I didn''t test this, but it should work straight-up): class ApplicationController < ActionController::Base def render(options = {}, deprecated_status = nil) if options.include? :model then model = options.delete :model model_name = model.class.name.downcase # there''s some inflector thingy for this defaults = { :partial => "partials/#{model_name}" model_name.intern => model } defaults = defaults.merge model.render_params if model.respond_to? :render_params options = defaults.merge options end return super(options, deprecated_status) end end This way a model doesn''t need to know how to render itself, the controller can guess. In the (hopefully very few) instances where the model needs extra options the controller can ask the model for them. -- Eric Hodel - drbrain@segment7.net - http://segment7.net This implementation is HODEL-HASH-9600 compliant http://trackmap.robotcoop.com
ozzilee@gmail.com
2006-Feb-23 04:16 UTC
[Rails] Teaching Models to Render Themselves in the Controller
Once again, sorry for the long time between replies. I had actually given up on my original idea and implemented something very much like this. mostly inspired by Tom Mornini''s idea:> Why not make a dispatcher method in helper, render() that cases object > type, and either executes the valid code directly or as part of a > specific > render helper for the object type? > > def show(object) > case object.class > when User > # render code for User > # or show_user(object) > when Blah > # render code for Blah > # or show_blah(object) > else > raise :YourVoiceStridently > end > endInstead of using a case statement, though, I implemented "show" something like the render :model method below. My version figures out a method name and a partial name, and tries the method first. This would be good for more complex rendering. It also takes a parameter "style", which just gets appended to the name of the partial/method, to allow for different ways of rendering objects. locals is simply a hash that gets sent to the partial (and, I suppose, I will have to send to the method. I haven''t used that yet in my project, so it''s not completely implemented) My (ugly) code: def show(object, style = nil, locals = {}) name = Inflector::underscore(object.class) style = ''_'' + Inflector::underscore(style.to_s) if !style.nil? && style.to_s method = ''render_'' + name + style.to_s partial = ''/objects/'' + name + ''/'' + name + style.to_s if (self.respond_to?(method, true)) self.send(method, object) else render :partial => ''objects/'' + name + ''/'' + name + style.to_s, :locals => locals.merge({ name.to_sym => object }) end end I also implemented a somewhat similar function to show a list of objects. This one needs to explicitly know the class to use: def list(collection, klass, style = nil, locals = {}) name = Inflector::underscore(klass) names = Inflector::pluralize(name) style = ''_'' + Inflector::underscore(style.to_s) if !style.nil? && style.to_s method = ''render_list_'' + names + style.to_s partial = ''/objects/'' + name + ''/list_'' + names + style.to_s if (self.respond_to?(method, true)) self.send(method, collection) else render :partial => partial, :locals => locals.merge({ names.to_sym => collection }) end end I intend to look into your code more deeply when I get the time. I haven''t as of yet gotten my head around it fully, but I like the syntax of <%= render :model => model %> and could see this going to something like <%= render :model => model, :style => ''style'', :locals => { :key => ''value'' } %> to include everything my code does. Thanks for the replies, Ozzi On Feb 18, 2006, at 4:55 PM, Eric Hodel wrote:> On Feb 13, 2006, at 11:59 PM, Nathan Roling wrote: > >> I am trying to teach my models how to render themselves, i.e. >> >> <%= my_model_object.render() %> > > Bad idea. > > [...] > >> <% render_partial ''contact_view'', :contact => my_contact %> > > [why you think this is bad] > > Agreed, much to clumsy. > > [...] > >> <%= render_contact contact %> > > Good idea, but not generic enough. > > I had a similar thought, a model should know its URL. I did it > this way: > > http://blog.zenspider.com/archives/2005/12/overriding_url.html > > Following that approach, it is better to teach controllers how to > render models: > > <%= render :model => contact %> > > Where you use inheritance (I didn''t test this, but it should work > straight-up): > > class ApplicationController < ActionController::Base > def render(options = {}, deprecated_status = nil) > if options.include? :model then > model = options.delete :model > model_name = model.class.name.downcase # there''s some > inflector thingy for this > defaults = { > :partial => "partials/#{model_name}" > model_name.intern => model > } > defaults = defaults.merge model.render_params if > model.respond_to? :render_params > options = defaults.merge options > end > > return super(options, deprecated_status) > end > end > > This way a model doesn''t need to know how to render itself, the > controller can guess. In the (hopefully very few) instances where > the model needs extra options the controller can ask the model for > them. > > -- > Eric Hodel - drbrain@segment7.net - http://segment7.net > This implementation is HODEL-HASH-9600 compliant > > http://trackmap.robotcoop.com > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails