DRY Javascript Degredation

Hi,

It seems there must be a better way to do this than what I am
currently doing.

I have a simple app that collects a users thoughts along with their
email address and their first an last name. On a page that lists all
the users thoughts they can click on a link to “add a thought” which
then displays a form with ajax. My current methodology for this is
not very dry. If js is not working it simply redirects to a “new”
page that displays the same form as would have been displayed with ajax.

The problem is i have the entire code for this ajaxed form is in the
view (rather than the non js “new” page which has the form code in
“_form”) I have it this way so I can do form_remote_for. I tried
modifying “_page” to only have the form setup code, but then it
complains about nil objects because i am setting up the form_for or
form_remote_for in the view rather than in “_page”. Is there some way
to DRY this up easily or am I just destined to have my form code in
two places.

~Jamie

Hi Jamie,

If the form is exactly the same in both cases then you should be able
to have the form in only one place. Do you use the rjs templates? Do
you know about respond_to? I think these two together can dehydrate
your app.

Peter

I’m using RJS templates yes,

my problem is i need form_for for the regular requests and
form_remote_for for the ajax requests, thus the form is not the same
for both cases.

~jamie

Can you post a very simplified stripped down version of your wet code?

Sure…

in list.rhtml

<%= link_to_remote 'Add A Signature', :url => { :action => 'show_signature_form' } %>

<%= error_messages_for :signature %>
<% remote_form_for :signature, @signature, :url => {:action => 'create'} do |form| %>

Email:
<%= form.text_field :email %>

		.....more form setup here....

	  <%= submit_tag "Create" %>
	  <%= link_to_remote 'Cancel', :url => {:action =>

‘hide_signature_form’}%>
<% end %>

in new.rhtml (this file exists for javascript degredation purposes)

<% form_for :signature, @signature, :url => {:action => 'create'} do |form| %>

Email:
<%= form.text_field :email %>

		...more form setup here...

	  <%= submit_tag "Create" %>
	<% end %>
</div>

What I was attempting to say (may not have expressed it clearly) is
that i tried to abstract everything between “form_for” and “end” into
a partial, however this doesn’t work because when the code is
compiled it whines about nil stuff when it hits form.text_field.

Notice the remote_form_for in the first one and just form_for in the
second one. This is where the problem lies, if i could just use one
or the other i could throw the whole mess in a partial.

~Jamie

Hi Jamie,

Jamie Q. wrote:

my problem is i need form_for for the regular requests and form_remote_for
for the ajax requests

Don’t mean to seem like a smart ass, but…

Why?

You can use an RJS template pretty much anywhere you can use an .rhtml.
What have you tried WRT using “form_remote_for” for the “regular”
requests?

Best regards,
Bill

Well I guess I should have thought of that, I assumed that it would
call create.rjs when in fact I wanted new.rhtml, however the proper
controller method handled that fact, and now I have DRYed off.

Thanks!

On 7/13/06, Jamie Q. [email protected] wrote:

What I was attempting to say (may not have expressed it clearly) is
that i tried to abstract everything between “form_for” and “end” into
a partial, however this doesn’t work because when the code is
compiled it whines about nil stuff when it hits form.text_field.

Notice the remote_form_for in the first one and just form_for in the
second one. This is where the problem lies, if i could just use one
or the other i could throw the whole mess in a partial.

You know that remote_form_for can take an :html option to specify a
“fallback” url for non-JavaScript browsers?

http://api.rubyonrails.com/classes/ActionView/Helpers/PrototypeHelper.html#M000414

I’ve been specifying this fallback url for a situation I think is
similar to yours.

Peter

What I ended up doing was using remote_form_for inside a partial
called “_form”

	<% remote_form_for :signature, @signature, :url => {:action =>

‘create’} do |form| %>
… form stuff…
<%= submit_tag “Create” %>
<% end %>

Then in the controller doing this…

def create
@signature = Signature.new(params[:signature])
return if request.xhr?
if @signature.save
flash[:notice] = ‘Signature was successfully created.’
redirect_to :action => ‘list’
else
render :action => ‘new’
end
end

so if it is a rjs request it returns and goes to create.rjs
otherwise…well you can see.

voila! one controller action to handle both situations, nice and DRY.

~Jamie

Jamie, you are a genius!

I was having the same problem, after following the example from O’Reilly
RJS pdf. The example they gave was for creating a new object, and does
not work for editing an existing object, but the solution you provided
works perfectly, thanks again!

Jamie Q. wrote:

What I ended up doing was using remote_form_for inside a partial
called “_form”

<% remote_form_for :signature, @signature, :url => {:action =>

‘create’} do |form| %>
… form stuff…
<%= submit_tag “Create” %>
<% end %>

Then in the controller doing this…

def create
@signature = Signature.new(params[:signature])
return if request.xhr?
if @signature.save
flash[:notice] = ‘Signature was successfully created.’
redirect_to :action => ‘list’
else
render :action => ‘new’
end
end

so if it is a rjs request it returns and goes to create.rjs
otherwise…well you can see.

voila! one controller action to handle both situations, nice and DRY.

~Jamie