On 8/19/10 11:05 PM, Wes Gamble wrote:
On 8/16/10 10:36 PM, Wes Gamble wrote:
All,

I have some custom models which need to be represented in Radiant views, and I would like to be able to take advantage of standard Rails partials, Rails form helpers, (e.g. all the good things about ActionView).

I have a custom extension which holds all of my model information. I have, in addition, created a Radius tag that is very close to rendering a standard Rails partial using standard form helpers. I can't really see the point in using the forms extension when the field helper tags in it provide less functionality than standard Rails helpers (and there is no support for textarea <input> elements).

Generally speaking, it seems that there are 3 options:

1) Do not use Rails partials at all, enhance the existing forms extension to provide more ActionView helper-like functionality. Basically, stay within the limits of Radiant.

2) Continue down the path I'm on, which is basically wrapping a Rails partial with a Radiant tag (similar to this post from the Radiant list: http://www.ruby-forum.com/topic/133878)

3) Figure out a way to hook into the Site controller and merge content generated via both standard Rails mechanisms and Radiant (I know how to hack around double render issues, etc.). I'm thinking that the SiteController could basically become a mini-dispatcher when necessary to run standard Rails actions, and ultimately render standard Rails views/helpers, which can then be inserted into the HTTP response.
At the risk of being chastised for responding to my own post, I thought I would update everyone on my progress.

Firstly, I forgot that <textarea> is it's own tag, so my assertion that the forms extension was incomplete was of course, incorrect.

As for the three approaches, here's what I discovered - I ended up not doing any of them.

1) Since custom Radius tags are executed only in the context of the Radiant rendering process (which is bound to SiteController), to add all the coolness I wanted would have been prohibitive.

2) I investigated creating a custom tag and learned a great deal, and started looking into how I would initiate a standard Rails request from within a SiteController action. But I ended up not really needing a custom tag after all.

3) I did look into how to hook into the Site controller, thinking that I could basically put a custom tag in a page part which would effectively hold the URL for the action that I needed to run. Then I would just initiate my standard Rails action during the standard SiteController action processing of that page part. However, I ended up trying to construct a valid Rails HTTP request object on the fly (which I had some limited success at), which started to suck up too much time. Truth be told, I would much rather that I be able to do it this way so that I only incur a minimum of overhead (see CONS below).

What I really wanted to do was to execute the action in question as a normal HTTP request and take the results and merge them with the Radiant generated page. That way, all of the standard Rails magic would just work.

So here's what I ended up doing:

* I create a Javascript function (stored in Radiant) to generate my Rails view (this is jQuery):

function generate_objection_form(obj_type_id) {
  $.ajax({async: false,
          url: '/admin/objection_instances/new',
          data: {objection_type_id: obj_type_id},
complete: function(response) {$('script').last().before(response.responseText)}})
}

Note that this Ajax call executes _synchronously_ so that the content is rendered before the page returns.

* In each page that I need this form to appear, I add the following <script> tag:

<script type="text/javascript">generate_objection_form(1)</script>

When the <script> tag is encountered, the Ajax call gets fired, synchronously, and the content is inserted before the script tag that made the call.

PROS:
* This is a standard Rails request, so no additional magic needed
* I can insert content at any point in the page using this scheme (I need to modify the content insertion function to key off of an attribute in the <script> tag - that way I don't have to depend on the positioning of the tag like I'm doing now ($('script').last()).

CONS:
* This approach requires at least one additional request/response for any custom content, granted it is lighter weight, most likely. * My content templates are now split between Radiant (as pages/parts/snippets) and the Rails app (as standard view templates). It would be nice to be able to put the content into a page part and keep it all in Radiant.

Hope this is of use to someone.

Thanks,
Wes

A refinement of sorts:
 * generic target URL and data
* use of Ruby route helpers to generate URLs (I hate having to hard code URLs in Javascript when I have all these Ruby helpers to generate them) * truly location-independent content updating based on tag attributes instead of DOM position

Javascript function:
  function generate_custom_content(url, data) {
  $.ajax({async: false,
          url: url,
          data: data,
complete: function(response) {$('script#replace').replaceWith(response.responseText)}})
}

Snippet named "rails_content" to call Javascript function (haml filter):
%script{:id => "replace", :type => "text/javascript"}
  generate_custom_content(<r:yield/>)

Page code to render snippet (which in turns invokes Javascript and pulls in the content): <r:snippet name="rails_content">'<r:ruby>new_admin_objection_instance_path</r:ruby>', {objection_type_id: 1}</r:snippet>

Wes

Reply via email to