AjaxScaffold has been deprecated in favor of ActiveScaffold
It’s finally here…

Lets get right to it, here are the major changes:
- Generated scaffold uses RJS templates. This should make adding and changing behavior much easier, but this also means that Rails 1.1+ is now required.
- Sorting & Pagination support.
And some of the minutae:
- controller/list now shows the scaffold in a layout and the component’ized version has been moved to controller/component. This is more in keeping with the standard scaffold URLs.
- Wrapped rescues around all CRUD database calls and output the error message using flash[:error] (see below)
- The default render_component call now passes along any parameters
- Scaffolds can be passed a parameter of :scaffold_id. Useful for when you want multiple scaffolds of the same type on one page (eg You are doing scaffolds inside scaffolds for parent-child associations).
- Backend fields (created_at, created_on, updated_at, updated_on) excluded from generated forms by default. Changing the generator to modify this exclusion list is pretty straightforward (I’ll explain this later), however it currently cannot be done at generation time with an argument.
- Default formatting for date and time fields in the list view that isn’t so verbose. They currently default to a more terse US-centric formatting, but its very easily modified (explained later as well).
- Indicator now goes clockwise
- No longer generating migration files which were oftent causing conflicts.
And one feature regression:
- Fade and highlight effects have been removed temporarily. If you saw the awful workaround code I had in the last version for getting the highlighting working correctly you know why. I decided to cut bait on this feature for now since the amount of work to get an elegant solution was more than I was willing to invest at this point. Someone forwarded me the Fade Anything Technique that looks dated but promising, if anyone wants to tackle this issue please by all means be my guest
You’ll still want to have perused the original howto article for how to install and run the generator and probably a good idea to just play around with the demo before proceeding. I’ll update you on changes to a few key things you might need to get you started on customizing your generated scaffolds.
System Messages
Previously messaging support was very limited. You could only render an error message and only in certian methods. Let’s just pretend that was all just a bad dream and move on. Sending a warning message to the display now is as easy as:
def create
begin
@widget = Widget.new(params[:widget])
@successful = @widget.save
rescue
flash[:error], @successful = $!.to_s, false
end
<strong>flash[:warning] = "Watch your back, they're everywhere!"</strong>
...
Thats it! Now that message will be inserted at the top of the scaffold after a new widget is created.

There are three supported message types :error,:warning and :info. Had @successful been false in the last example then the message would have been inserted into the form instead.

If you look in the RJS templates for each of the CRUD methods you can see whether it will post the message to the list or to the form, but its pretty intuitive. If there is a form open after the action is called the messages go there otherwise they are put at the scaffold level. One thing to note is that each request overwrites the existing error messages.
Changing data formatting defaults
The default formatting for certian data types in Ruby was really getting on my nerves, especially those for dates and times. Thus I redirected the display formatting of object values through a method so I could inject my own defaults. You can modify the default formats or add your own special formatting for specific data types by editing the following methods in app/helpers/ajax_scaffold_helper.rb:
...
def column_value(data_object, column)
column_value = data_object.send(column.name)
if column_value.instance_of? Time
column_value = format_time(column_value)
elsif column_value.instance_of? Date
column_value = format_date(column_value)
end
column_value
end
def format_time(time)
time.strftime("%m/%d/%Y %I:%M %p")
end
def format_date(date)
date.strftime("%m/%d/%Y")
end
...
Customizing the table data display
This was a very crappy way to solve this problem. We have a much more robust solution in 3.1.0
By default the data you see in the scaffolded table is exactly the same as the fields in your database table and even in the same order. You can modify data columns by using the lib/content_columns_patch.rb and overriding self.content_columns in each model class. First, add require ‘content_column_patch’ to either the model or to environment.rb. Then add the following to your model:
class Widget < ActiveRecord::Base
def self.content_columns
get_desired_columns %w(version name), @@desired_columns_cache ||= nil
end
...
The second argument in that call simply passes in a class variable to use as a cache for the columns so they don’t have to be refiltered everytime content_columns is called. Now your table data display will be restricted to just the version and name columns and displayed in that order.
Overriding Scaffolding & Modifying globally excluded form fields
Many people have asked how they can modify the generator so that they can tweak the scaffold output on a more global level. A good example is if you wanted to change the list of fields that were ignored by the generator when creating scaffold forms. You’ll find the default list in templates/form_scaffolding.rhtml in the Ajax Scaffold Generator directory:
<%= all_input_tags(@model_instance, @singular_name,
{ :exclude => %w(created_on created_at updated_on updated_at) }) %>
Modifying this file would change all subsequently generated scaffolds, if you wanted your changes localized to a single project you can always copy the generator files (all the files under ajax_scaffold_generator-3.0.0) into lib/generators/ajax_scaffold.
Wrapping Up
Your responses will drive where development goes from here, I’m pretty happy with where it is for a least a little while. Perhaps long enough for me to catch up on other projects. I’ve reluctantly (I say reluctantly because I find 16bugs’ design and usability repulsive, but I don’t know a good free alternative… I miss Mantis) set up an account on 16bugs so submit any bugs there. Feel free to leave any questions or comments you have below. Happy generating.
54 Comments
Thank you very, very, very much for this great plugin!
You’re the man
How can I upgrade 2.x scaffolds?
oomtuinstoel: Good point, I covered that in a previous article but I neglected to address that issue here. Unfortunately so much has changed from the 2.x version that migrating scaffolds really isn’t an option. Your best bet would be to generate a new scaffold based on the same model as an existing scaffold and try and diff your changes (This should be fairly easy if your changes were mainly in the controller or form). Sorry.
For paging in the demo at least, next and prev work, but not the numerical links.
Delete Confirmation: One think I’ve tended to do with my own code is highlight the row that is about to be deleted when the delete confirmation button pops up. A small thing, but it’s quite easy to confirm the wrong row.
Also, as a supplement to asking for donations, you should consider something simple like some adsense ads on the ajax scaffold or other high traffic pages on this site.
Richard,
Demo looks great and the feature list makes me want to cry since I spent a lot of time tweaking 2.x to work for my application, but 3.0 appears to do much of what I need of the bat. I think I will try to “upgrade” to 3.0 in a couple of days. I have a couple of ideas for improvements. If I manage to implement them I will let you know in case you are interested in adding them to the code base.
Hmm… I am having a problem where ‘Name’ works but ‘Admin::Name’ doesn’t work. It seems that the code is putting the model name pluralized into the link_to_remote URL so the link ends up being:
“Names\edit” and “admin\Admin::Names\edit”
Very nice!
Looking forward to putting it to use
YOU R DA MAN! you were just discussing these upgrades last two weks back and you have them in. This is so cool. I am just loving it! And, by the way, we are evangilizing it as well to our colleagues here… Keep up the good work.
Woo Hoo!!! Time to upgrade and test out my first pages this way!
Jon: I actually have something for doing delete confirmation in the pipeline. I’m going development it for SlimTimer first (which I need to get back to) and then work it back into the scaffold code. I did have adsense ads up for a while and didn’t make a dime. Probably because a) I’m a UI snob so I would only accept the smallest banner ads and b) my readers are too smart to click those things
Eden: Feedback and especially code are always welcome. Sorry to bring you to tears
Slain: That just might have to be a known issue for now. Somewhere along the Rails 1.0 -> 1.1 migration path they changed up the basic scaffold variables and so I still haven’t figured out how to handle all these cases. I’ll add it to the bugs list.
rupak ganguly: Thanks, enjoy
Richard,
Is there a way to freeze the 2.x gem along with rails? I would like to freeze 2.x with my current application so that I can test 3.x before attempting to upgrade. When I run rake freeze_gems I just get rails frozen.
Eden: Theres no real reason to “freeze” the 2.x gem using 3.0 won’t automatically overwrite your existing generated scaffolds. You can do what I described in the end of the article and just copy the 3.0 version into the lib/tasks/ajax_scaffold directory so that only that one project gens stuff against 3.0. Or vice versa and copy 2.x into that directory. Does that make sense?
Wow – I thought version 2 was fantastic, but this takes the cake. Pagination and sorting are a huge bonus for me. Thanks for all of the hard work!!! Already marked as dugg – http://digg.com/programming/Ajax_Scaffold_3.0.0_released.
Richard: I may give that a shot. I knew I read something about preserving the 2.x version for individual apps, but lost track of whether that was the mailing list or here and kept searching for “freeze” to no avail.
I installed the 3.x gem and tried regenerating the scaffold for one of my models in an existing app. It seemed to work for a basic model (e.g. contact), but New didn’t work at all (no response). Additionally, for more complex models (e.g. admin::responses), the top level scaffold page just blew up and I couldn’t find the errors. I created a new app and tested 3.x and it seemed to work fine.
This suggests that installing the new gem and running generate for existing models may not be possible even if you overwrite all files when prompted. Thought this might be useful information for others.
Eden: There is some bug with doing Admin::Responses. Its currently on the bugs page and I don’t as yet have any information on it. Did you perhaps generate scaffolds on a project where Rails 1.0 was frozen? Because that would cause it not to work.
Hi Richard: I did freeze 1.1 for a while, but then deleted the whole vendor/rails folder, so I don’t think it is related to that. Perhaps one of the files didn’t get overwritten when I regenerated models originally done in 2.x using 3.x.
At this point I am most interested in getting the namespace (Admin::Something) bug resolved. I will take a look at it tomorrow and see if I can track it down. Any hints you can provide on where to start would be greatly appreciated.
The main problem I saw with a fresh application was that Admin::Responses didn’t respond to “New” or “Edit” clicks. The indicator image loads, but the form never materializes.
BTW – Congratulations on launching all the new features today.
I have also had the namespace type of problem as well. Have done a bit of investigating and left comments on the 16bugs tracker thinger. I think I have it working and have created a diff file of the changes I have made, though not sure where to send it.
Great work on this btw, just been playing with it for a few days and loving it.
Eden: (And others!> If you generate on top of an existing directory that had files, make sure to delete a few that are no longer needed. That messed me up for a bit.
The only major hitch that I saw on my first trial is that i’ve used dFilter javascript for some formatting of strings on input fields, and that doesn’t play nice with new/edit in the new scaffolds… But I could be doing it wrong too so I have to play with it more.
Geoff: The changes you put on 16bugs are 100% for me so far. I will post there if I run into any problems. Thank you for saving me some time tracking that down.
Richard: I am not sure I understand how to exclude columns globally. If I just edit the form_scaffolding file, the columns still show up. If I use the instructions in “Customizing the table display data” section above, then I have to specify every field manually. Is there a way to exclude columns globally, but still include all table columns not explicitly excluded?
It looks like the global exclude is only applying to the edit form, but not to the list or list columns. I will try to look into this in more detail today. For now I am opening a bug on 16bugs.
def self.content_columns
get_desired_columns %w(version name), @@desired_columns_cache ||= nil
end
how does this work with has_many/belongs_to?
Eden: Perhaps this wasn’t clear in the article but the excluded fields were for form generation, which happens at generation time. Defining the columns in the data display happens at runtime which is which is what the other section in the writeup explains.
oomtuinstoel: I haven’t looked into a good way to do that using content_columns. The solution probably involves abstracting out the method called in _item.html to call some other method that then calls content_columns (which are for attributes on a model) and associated_columns (which are for :has_many, and :belongs_to). I’ll see if I can writeup something on that a bit later.
get_desired_columns %w(version foreign_id) prints the correct name of foreign. So I assume (knowing that assumption is the mother of all fuck-ups) that the problem is not in _column_heading.rhtml. Right?
oomtuinstoel: That does work for associations? I never expected it would work nor had I tested that scenario. I don’t think I quite follow the problem.
Richard: I think I understand your explanation. I guess one feature suggestion from this would be to either autogenerate the column definitions including all fields but those excluded, or just change the column code to skip any columns provided in a global config file that is also generated once. Not really critical once you understand what is going on, but I think it would be a nice touch.
Could you provide a simple write-up on how to nest components? I am going to play around with it for the next couple of hours and will post something once I figure it out, but if you have time to explain it, that would save me a bit of trial and error work.
Once again, thank you for this great project. 3.x looks like it could really be a strong foundation for building many types of data driven applications (i.e. internal business apps). Perhaps as the whole Rails development market matures you will find a good business model for ajax_scaffold (consulting, guidebook, etc.).
When I wrote “how to nest components” above, I really meant “nest multiple child components in a parent component”. Information on multiple independent components on a page would also be helpful, but I suspect that is an easier problem to solve.
Eden: I am very tardy on writing an article on how to nest components like for doing parent/child assoications with scaffolds. The answer to the latter question is explained in an earlier post on how to do multiple scaffolds on a page.
Eden: Also in regards to your previous post can you open up feature request ‘bugs’ on the bugs site? Thanks.
Would it be possible for someone to point me in the right direction on using ajax_scafolld with associations? I’m trying to embed one scaffold in another: For example, I have a model Company, that has_many Employees. I want to have the Employee component listed inside the Company Edit form. It would be a nice demo and it’s not obvious (to a Rails newbie, anyway) how it’s done.
Craig: I am working on the same problem right now myself. I can get my child to show up by adding the following to the end of the _child view file:
< %= render_component :controller => ‘Manufacturers’,
:action => ‘component’,
:scaffold_id => supplier.id unless supplier.manufacturers.find_all.empty? %>
However, I don’t think I am using :scaffold_id right and probably need to pass supplier.id (parent id) through in a param or local so that I can restrict my child list (right now all children are shown.
Note that while this embeds one component in the other, it is quite ugly. The table header in the child jumps up to the parent table header and there are other display problems. Wrapping the component call in tr and td html elements helps with many of the problems, but I am not satisfied with the appearance yet. I will post again when I get the parent->child relationship fully worked out.
Craig: When I said “restrict my child list (right now all children are shown.”, I meant that all children for all parents are shown (Child.find_all) instead of just the children for the parent currently rendered (Child.find_all_by_parent_id(parent_id).
Richard: I added the feature request as a bug as requested. Putting multiple components on a page looks easy, but I am still trying to find an elegant way to show child->parent relationships.
Eden: I have some code someone sent me about how to do that very thing. I should post that sometime along with a new CSS that is styled for children. I was going to wait on 3.1.0 for that since it’ll be the release with automagic association generation.
Richard: Wow, you are really hauling on the updates. I would love to see any solutions that are out there for parent->child relationships since that would let me get started updating my app from 2.x to 3.x.
Eden: Email me and I’ll forward you the work Dean sent me on how he did this with 2.x. Perhaps you can glean something from that.
It looks like the code I posted got a litle messed up. That comment can be deleted, as I’ll re-summarize:
I pass parent_id as a param in the parent _form.rhtml file andthen render_component the subcomponent method in the child_controller.
I created a new method in the child controller called “subcomponent”, pretty much the same as the component method except it adds
“:conditions => “supplier_id = #{params[:supplier_id]”
to the paginate call
The parent edit form has the children of the parent listed, but the chile edit/delete and Create New links break with a dialog:
“RJS Error: TypeError: form has no properties”
y the way, I created a google group for discussing issues/ideas on this plugin. Use it or don’t, I thought it would be useful. I’ll hand off ownership to Richard if wanted.
http://groups.google.com/group/ajaxscaffold
Eden/Richard: I got the same idea working for parent/child for 3.x…
Hopefully this will come out:
1) put the following in the parent _parent.rhtml -> < %= link_to 'Child', :controller => ‘child’,:action => ‘list’, :scaffold_id =>’child’, :parent_id => parent %>
2) in the child controller component function if params[:parent_id] add a :conditions =>["parent_id=?",params[:parent_id]] to the paginate section
else load full
For the most part this is way easier in 3.x..
What I’d like to be able to do now is figure out how to selectively override column_value(table,column) just for specfic columns on specific tables, so I could leave the _table.rhtml alone and affect what gets put in for data.
Any ideas other than overriding the entire function would be appreciated!!
Dean: The code basically works, and is cleaner than what I did. However, when adding new children in the Create New link, the correct parent_id is not filled in. This is probably easily fixable.
I’d also like to have the child bit open in the same page as the parent when clicked, but I can probably hack around on this.
Craig,
You are correct in that you’ll also have to add a bit more code to the new method of the child.. Something like @child.parent_id = params[:parent_id] did it in 2.x.. I assume this will work here. I’m working through my conversion as we speak, so I haven’t tested everything yet. — Also some of my pages are links to child from the parent line (i also tweak the page header area to say Children of xxx if a parent was passed in… I have a few pages where I want to be able to see the children in the parent page. I did this in 2.x by working with the edit form. I plan on doing the same with 3.x, but again – I’ll get there soon.
One other note: in 2.x I had to add a hidden field on the form to hold the parent_id so it crossed from the new to the create. Again, I assume the same is true.
Dean & Craig: Can you guys move this discussion to the new forum (http://groups.google.com/group/ajaxscaffold/) I’ll try to chime in sometime tomorrow on the issue.
Dean: Give me a user case for overriding column_value so I understand what you are trying to do.
Richard:
If we could override column_value(child, ‘parent_id’) to display child.parent.name then we would only have to place one little function in a helper to change the displays (or something with multiples columns)… I did this so far by coping column_value into the child helper and making it child_column_value() then changing one line in the _child.rhtml and the new function.
Wow. This looks great. I just started using 2.0 and now I see 3.0. I created a new db to test. The record show up fine in the list, but I am getting the following error when I click ‘Create New’:
ActionView::TemplateError (wrong number of arguments (2 for 1)) on line #29 of app/views/locations/new.rhtml:
Line 29:
< %= loading_indicator_tag 'category', "create-#{@temp_id}" %>
Ted, did you generate a 3.0 scaffold into a 2.0 directory? If so there is 4 files to remove, including new.rhtml
How might I display data in both the form and the list for a habtm relationship. In previous versions I could list out data from a habtm table by editing the _Widget.rhtml:
But now the column listing (for the list at least) is done in the controller using the new method as described earlier. I have tried getting data from other tables to pass throught this method but failed. Am I hitting a syntax problem or is what I am describing no longer possible?
PS — thanks for the great work
I previously installed the scaffolding plugin and then I installed ajax_scaffold gem.
I don’t know if the problem is related to the fact that I have 2 types of scaffolding but I’m getting
“Uninitialized Constant ScaffoldingSandbox” error when I try to run ajax_scaffold
I checked and it seems to have installed properlly in the ruby\gems\1.8\gems\ajax_scaffold_generator-3.1.11
ps: I’m running windows