Components and AJAX

It's pretty accepted that components are more bad than good. One area
where I think they really are useful - and ought to remain, perhaps in
a different form - is for AJAX. Especially AHAH.

Imagine a simple live search form. One of the divs is updated via AJAX
with action searchresults. But, we still want to be able to generate
the page without AJAX, both for older browsers and for the initial page
load (why wait for AJAX to update it). Isn't the simplest, DRYest way
to simply use a component to do the exact same thing that the AJAX
request will do - retreive the HTML (via controller/action) and fill
the div with it.

Imagine a simple live search form. One of the divs is updated via AJAX
with action searchresults. But, we still want to be able to generate
the page without AJAX, both for older browsers and for the initial page
load (why wait for AJAX to update it). Isn't the simplest, DRYest way
to simply use a component to do the exact same thing that the AJAX
request will do - retreive the HTML (via controller/action) and fill
the div with it.

This question belongs on rubyonrails-talk, but the answer is:

respond_to do |format|
  format.js { #ajax results }
  format.html { #show html page }
end

Thanks. I think you may have misunderstood my point. I'm not asking
how to do AJAX DRYly, but rather pointing out how components are the
best way to do it.

The searchresults div needs to be accessible directly as a URL, for
AJAX, but it also needs to be incorporated as a piece of the larger
search page. Doing this with a component is clean and dry - more than
any other way of incorporating the results in.

Partials do this job nicely.

What you’re describing is exactly what partials are made for.

Say you need to fill a set of search results. In your normal view.

<%= render :partial => 'search_result', :collection => @results %.

Now when you need to respond with AJAX search results:

def action
@results = find_results_somehow
render(:update) { |page| page.replace_html :partial => ‘search_result’, :collection => @results }

end

Hope that helps,
-Martin

Whoops. More like this, sorry:

render(:update) { |page| page.replace_html :search_results, :partial => ‘search_result’, :collection => @results }

(I forgot to specify the div you’re updating with the RJS)

-Martin

Doing this with partials still forces me to have the finder code in
both methods.

Components keep it clean and simple:

def searchpage
  # No need to put any finder logic here
end

def searchresults
  @results = Model.find(...)
end

Doing this with partials still forces me to have the finder code in
both methods.

Components keep it clean and simple:

def searchpage
  # No need to put any finder logic here
end

def searchresults
  @results = Model.find(...)
end

But putting that logic into your model, where it belongs, keeps it
similarly clean

def searchpage
  @results = Model.search params[:q]
end

Without the complication and (considerable) performance overhead of components.

I’m also not convinced that components should be shunned as much as they are. The example of having logic/content that is used by both an ajax request and also exists as part of a full page request seems a perfect fit for components.

I agree that if only a line or two of controller code are involved that components are overkill, but that isn’t always the case. I have used components in a couple of places and they have been very useful.

0.02c
-Jonathan.

I'm also not convinced that components should be shunned as much as they
are. The example of having logic/content that is used by both an ajax
request and also exists as part of a full page request seems a perfect fit
for components.

I agree that if only a line or two of controller code are involved that
components are overkill, but that isn't always the case. I have used
components in a couple of places and they have been very useful.

So far the cases people cite (myself included) are essentially
"partials with some kind of before_filter like thing".

Are there any other situations people use them for? The current
implementation is *way* too much software for that one usecase.

The Bosses don't like them. That's an excuse big enough.

They don’t need an excuse, it’s opinionated software :slight_smile:

So (to make this discussion more on-topic for this forum), when are they going to be thrown out? I haven’t seen 1.2 branch dealing with this (or I missed the changeset)

Michael Koziarski wrote:

But putting that logic into your model, where it belongs, keeps it
similarly clean

def searchpage
  @results = Model.search params[:q]
end

Have to disagree here. Searches can have a lot of UI stuff that should
stay out of the model. (Same with similar ajaxian examples.)

Mislav Marohnić wrote:

>
> The Bosses don't like them. That's an excuse big enough.

They don't need an excuse, it's opinionated software :slight_smile:

"opinionated," not "dogmatic". Core developers gear Rails to what they
see is best; but - at least as far as my experience has been - they're
open to ideas on what that best is. They don't claim to be omniscient,
only that its better to gear Rails to do one thing very well than try
to do anything poorly.

(Okay, maybe on databases the word "dogmatic" is appropriate, but not
anything else :-/)

Yes, but the process of actually doing the search should be separate
from any UI stuff (such as displaying the search form or results) and
as such should be in the model layer. As to whether it should be tied
directly into the model you are searching is a different matter however.

Cheers
Luke

Luke Redpath <contact@lukeredpath.co.uk> writes:

Yes, but the process of actually doing the search should be separate
from any UI stuff (such as displaying the search form or results) and
as such should be in the model layer. As to whether it should be tied
directly into the model you are searching is a different matter
however.

Presumably, the trick with an AJAXy search system where the
layout includes a search box and a target for updating with search
results (a la typo, but we're not doing it quite like this yet) is to
put a helper method into application_helpers.rb and have that set up
anything that needs setting up before rendering an appropriately
targetted search box, and the search controller can respond to an AJAX
request appropriately.