Sebastian Ley
2004-Oct-31 17:17 UTC
Splitting an application into several objects with individual logic
Hello, I am new to rails and got stuck when I wanted to develop some general purpose objects to be reused among several applications. These objects would then allow a programming style similar to GUI widget toolkits programming, by instantiating such a widget, set some of its attributes and then tell it to draw itself at the desired place. I tried the following: ,--[controller/mywidget_controller]-- |require ''abstract_application'' |class MyWidgetController < AbstractApplicationController | def show | render "mywidget/show" | end |end ''-- ,-[controller/mainapp_controller]-- |require ''abstract_application'' |require ''mywidget_controller'' |class MainAppController < AbstractApplicationController | def index | show | end | def show | @widget=MyWidgetController.new() | render "mainapp/show" | end |end ''-- ,--[views/mainapp/show]-- |[html stuff] |<%= @widget.show %> |[more html stuff] ''-- ...and expected views/mywidget/show to be rendered inside teh mainapp body. But that was not the case, I got some errors, pasting the relevant part of the backtrace: Showing /home/show.rhtml where line #9 raised undefined method `file_exists?'' for nil:NilClass [offending line: 9: <%= @widget.show %>] vendor/actionpack/lib/action_controller/base.rb:603:in `template_exists?'' vendor/actionpack/lib/action_controller/base.rb:607:in `assert_existance_of_template_file'' vendor/actionpack/lib/action_controller/base.rb:275:in `render_file'' vendor/actionpack/lib/action_controller/layout.rb:142:in `render'' /../app/controllers/mywidget_controller.rb:7:in `show'' (erb):9:in `render_template'' vendor/actionpack/lib/action_view/erb_template.rb:90:in `render_template'' vendor/actionpack/lib/action_view/abstract_template.rb:34:in `render_file'' vendor/actionpack/lib/action_controller/base.rb:279:in `render_file'' vendor/actionpack/lib/action_controller/layout.rb:142:in `render'' /../app/controllers/mainapp_controller.rb:13:in `show'' /../app/controllers/mainapp_controller.rb:9:in `index'' I suppose I tackled the problem entirely wrong, so can somebody help me on how to achieve my initial goal? Thanks in advance and regards, Sebastian -- PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6
Alexey Verkhovsky
2004-Oct-31 17:29 UTC
Re: Splitting an application into several objects with individual logic
On Sun, 2004-10-31 at 19:17, Sebastian Ley wrote:> Hello, > > I am new to rails and got stuck when I wanted to develop some general > purpose objects to be reused among several applications. These > objects would then allow a programming style similar to GUI widget > toolkits programming, by instantiating such a widget, set some of its > attributes and then tell it to draw itself at the desired place.Try this (untested): 1. Place widget.rhtml in app/views/shared/_widget.rhtml (template with underscore is know as a partial). It should refer to widget variable for any data that it needs. 2. Define widget class in lib/widget.rb (or even app/controllers/widget.rb 3. Somewhere in the MyAppController#show, instantiate a Widget and assign it to @widget. 4. In app/views/my_app/show.rhtml include <%= render_partial ''shared/widget.rhtml'', @widget. You can also look at how NavBar and PostMenu are implemented in RForum - these are exactly the kind of objects that you are asking about. Alex
Sebastian Ley
2004-Oct-31 23:36 UTC
Re: Splitting an application into several objects with individual logic
* Alexey Verkhovsky wrote: [about partials] Thanks, I believe that is what I was looking for ;-) However:> 4. In app/views/my_app/show.rhtml include <%= render_partial > ''shared/widget.rhtml'', @widget....the lookup for shared partial templates seems to be broken: <%= render_partial "listform/show", @personlist %> results in: Showing /home/show.rhtml where line #9 raised No such file or directory - /var/www/rails/public/../config/environments/../../app/views//home/_listform/show.rhtml -> Instead of searching in /views/listform/_show it searches for /view/$originaltemplate/listform/_show. This neither according to API documetation nor to what I would expect. Suppose it is a bug? Regards, Sebastian -- PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6
Tobias Luetke
2004-Oct-31 23:41 UTC
Re: Splitting an application into several objects with individual logic
You might need to have to update your rails, i believe this was fixed On Mon, 01 Nov 2004 00:36:52 +0100, Sebastian Ley <sebastian.ley-uhhZ63b/5Phaq5fyzuukUWfrygkm6VTR@public.gmane.org> wrote:> * Alexey Verkhovsky wrote: > > [about partials] > > Thanks, I believe that is what I was looking for ;-) > However: > > > 4. In app/views/my_app/show.rhtml include <%= render_partial > > ''shared/widget.rhtml'', @widget. > > ...the lookup for shared partial templates seems to be broken: > > <%= render_partial "listform/show", @personlist %> > > results in: > Showing /home/show.rhtml where line #9 raised No such file or directory > - /var/www/rails/public/../config/environments/../../app/views//home/_listform/show.rhtml > > -> Instead of searching in /views/listform/_show it searches > for /view/$originaltemplate/listform/_show. > > This neither according to API documetation nor to what I would expect. Suppose > it is a bug? > > > > Regards, > Sebastian > > -- > PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key > Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6 > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Tobi
Sebastian Ley
2004-Nov-01 13:28 UTC
Re: Splitting an application into several objects with individual logic
* Tobias Luetke wrote:> You might need to have to update your rails, i believe this was fixedActually it was not even implemeted in the version I used before ;-) Thanks. Okay, on my way to enlightenment I stumbled over the next problem: With render_partial I can pass a local variable, which will in my case be the logic object I instantiated in the controller. E.g. @widget=Widget.new() [...] <%= render_partial "widget/_showpartial" @widget %> While this works fine now, there is still a problem: In "widget/_showpartial" I need to know the variable name I passed with render_partial, because I need to access it under that name. I can "work around" that by enforcing that name i.e. the render_partial function of that template needs always to be called with a variable named @widget. However then I would not be able to use the same widget twice or more time in the same context, as all instances need to have the same name. A solution would be that render_partial copied the variable in its argument to a common name for use in the template. Then, the templates could access the passed variable always under the same name. Or am I missing the point...? Regards, Sebastian -- PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6
Tobias Luetke
2004-Nov-01 14:52 UTC
Re: Splitting an application into several objects with individual logic
If you pass in a variable to render_partial you can access it under the same name as the partial base filename. In your case probably _showpartial ( i would suggest not using an underscore if you supply a full path to the partial ). The partials also share the entire instance variables ( e.g. everything starting with @ ) with the main template. On Mon, 01 Nov 2004 14:28:46 +0100, Sebastian Ley <sebastian.ley-uhhZ63b/5Phaq5fyzuukUWfrygkm6VTR@public.gmane.org> wrote:> * Tobias Luetke wrote: > > You might need to have to update your rails, i believe this was fixed > > Actually it was not even implemeted in the version I used before ;-) Thanks. > > Okay, on my way to enlightenment I stumbled over the next problem: > > With render_partial I can pass a local variable, which will in my case be the > logic object I instantiated in the controller. E.g. > > @widget=Widget.new() > [...] > <%= render_partial "widget/_showpartial" @widget %> > > While this works fine now, there is still a problem: In "widget/_showpartial" > I need to know the variable name I passed with render_partial, because I need > to access it under that name. I can "work around" that by enforcing that name > i.e. the render_partial function of that template needs always to be called > with a variable named @widget. > > However then I would not be able to use the same widget twice or more time in > the same context, as all instances need to have the same name. > > A solution would be that render_partial copied the variable in its argument to > a common name for use in the template. Then, the templates could access the > passed variable always under the same name. > > Or am I missing the point...? > > > > Regards, > Sebastian > > -- > PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key > Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6 > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Tobi
Sebastian Ley
2004-Nov-01 15:43 UTC
Re: Splitting an application into several objects with individual logic
* Tobias Luetke wrote:> If you pass in a variable to render_partial you can access it under > the same name as the partial base filename. In your case probably > _showpartialHm, I suppose that would be what I am looking for, but it does not seem to work: Showing /listform/_showpartial.rhtml where line #1 raised undefined local variable or method `_showpartial'' for #<ActionView::Base:0x4067de84> [...] 1: <a href="<%= _showpartial.origuri %>">Original URI</a> In the invoking template I passed a variable named @personlist whose class has a method name origuri and if I put the following in listform/_showpartial it does what is expected: <a href="<%= @personlist.origuri %>">Original URI</a> But this is exactly what I want to avoid: In the shared partial I want to have no assumptions on the passed variable names...> ( i would suggest not using an underscore if you supply a > full path to the partial ).It is still needed, because it will substituted for the lookup: where line #9 raised No rhtml or rxml template found for listform/_showpartial [...] 9: <%= render_partial "listform/showpartial", @personlist %>> The partials also share the entire instance variables ( e.g. > everything starting with @ ) with the main template.Ok, but for my specific case I need to access the passed variables under a name independent from the name that was passed. (Oh man, I barely understand it myself when I read all that, I hope you can make something out of it ;-) ) Regards, Sebastian -- PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6
Tobias Luetke
2004-Nov-01 16:25 UTC
Re: Splitting an application into several objects with individual logic
I did a quick test: file: app/view/test/_test.rhtml : <%= test %> random other view: <%= render_partial ''test/test'', "hello world" %> printed : "hello world" Hope this helps. If you have any other problems you should come to IRC, I can help you there directly ( in german, too ) On Mon, 01 Nov 2004 16:43:55 +0100, Sebastian Ley <sebastian.ley-uhhZ63b/5Phaq5fyzuukUWfrygkm6VTR@public.gmane.org> wrote:> * Tobias Luetke wrote: > > If you pass in a variable to render_partial you can access it under > > the same name as the partial base filename. In your case probably > > _showpartial > > Hm, I suppose that would be what I am looking for, but it does not seem to > work: > > Showing /listform/_showpartial.rhtml where line #1 raised undefined local > variable or method `_showpartial'' for #<ActionView::Base:0x4067de84> > [...] > 1: <a href="<%= _showpartial.origuri %>">Original URI</a> > > In the invoking template I passed a variable named @personlist whose class has > a method name origuri and if I put the following in listform/_showpartial it > does what is expected: > <a href="<%= @personlist.origuri %>">Original URI</a> > > But this is exactly what I want to avoid: In the shared partial I want to have > no assumptions on the passed variable names... > > > ( i would suggest not using an underscore if you supply a > > full path to the partial ). > > It is still needed, because it will substituted for the lookup: > > where line #9 raised No rhtml or rxml template found for listform/_showpartial > [...] > 9: <%= render_partial "listform/showpartial", @personlist %> > > > The partials also share the entire instance variables ( e.g. > > everything starting with @ ) with the main template. > > Ok, but for my specific case I need to access the passed variables under a > name independent from the name that was passed. > > (Oh man, I barely understand it myself when I read all that, I hope you can > make something out of it ;-) ) > > > > Regards, > Sebastian > > -- > PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key > Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6 > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Tobi
Sebastian Ley
2004-Nov-01 16:40 UTC
Re: Splitting an application into several objects with individual logic
* Tobias Luetke wrote:> file: app/view/test/_test.rhtml : > <%= test %>Okay, here was my mistake, I used <%= _test %>. Now i works, thanks for your help!> If you have any other problems you should come to IRC, I can help you > there directly ( in german, too )I am (Wile_E) and will bother you again soon I suppose ;-) Regards, Sebastian -- PGP-Key: http://www.mmweg.rwth-aachen.de/~sebastian.ley/public.key Fingerprint: A46A 753F AEDC 2C01 BE6E F6DB 97E0 3309 9FD6 E3E6