Skip to content
cntrytwist edited this page Sep 14, 2010 · 26 revisions

Embedding scaffolds allow you to reuse your scaffold and insert it into other views as a widget. You can specify constraints for your scaffold to limit the records it works with.

Rendering

To embed a scaffold in another controller, or on a page somewhere, use render :active_scaffold => "controller_id" (it’s a special call that will turn around and call render_component). You may pass ANY combination of parameters you would like: label, sort, sort_direction, search, and even constraints (covered later).


#render UsersController 
render :active_scaffold => 'users'

#the same, but this time change the heading to “Active Users”
render :active_scaffold => ‘users’, :label => ‘Active Users’

#sorting by `name`, ascending
render :active_scaffold => ‘users’, :sort => “name”, :sort_direction => “ASC

Constraints

Constraints are simple field/value pairs used as search conditions for the scaffold’s list. Because constrained columns become rather boring to look at, they are automatically removed from column sets so they don’t appear in List, Create, Update, etc. Furthermore, records created through a constrained embedded scaffold will automatically receive the values it is constrained to (a user can not create a record with a value outside of the constraint). Constraints may be the name of a database field (e.g. user_id) or the name of a attribute or association column. If the constraint is the name of an association, then the constraint value will be assumed an ID.


#render all entries for a user
render :active_scaffold => 'entries', :constraints => { :user_id => @user.id }

#render all active users
render :active_scaffold => 'users', :constraints => { :status => "active" }

Important: Constraints are stored in the session. You should therefore only use simple
values, e.g. @record.id instead of @record.


render :active_scaffold => 'users', :constraints => {:active => 1, :user_group => 15},
       :params => {:hello => 'world'}, :label => 'Active Editors'

Advanced: Accessing constraint data in your controller

To access constraint data inside of your controller, use active_scaffold_session_storage[:constraints][:constraint_key].


class Admin::RentalCompsController < ApplicationController
  layout 'default_scaffold'
  before_filter :load_listing
active_scaffold :rental_comps do |config|
end
def load_listing
begin
@listing = Listing.find(active_scaffold_session_storage[:constraints][:listing_id])
rescue
@listing = Listing.new
end
end
def before_create_save(record)
record.listing_id = @listing.id if @listing.id
end

end


At the time of writing, active_scaffold_session is only accessible by the controller, and not by the view.

Conditions v1.1

Constraints are powerful, but only because they’re limited to equality-based conditions, i.e. a equals b. If you want something simpler and more flexible, add :conditions to your embedded scaffold. Unlike constraints, these conditions will affect what is in the list, but will not affect visible columns and will not automatically apply to all new records. But in exchange you can create greater-than, less-than, in-set, etc., conditions.


#note: example hasn't been tested for typos or other obvious problems
render :active_scaffold => 'users', :conditions => ['created_at > ?', Time.now - 5.days],
       :label => 'New Users'

A Real world Example

The following example comes from a real estate site that lists houses (a listing). One page embeds two interfaces on a listing page to add the ability to modify/update comparable properties (right there on the same page).


  1. Here’s everything you need to know about the models/controllers involved
  1. app/models/comp.rb
    class Comp < ActiveRecord::Base
    belongs_to :listing
    end
  1. app/models/rental_comp.rb
    class RentalComp < ActiveRecord::Base
    belongs_to :listing
    end
  1. app/models/listing.rb
    class Listing < ActiveRecord::Base
    has_many :comps
    has_many :rental_comps
    end
  1. app/controllers/admin/comps_controller.rb
    class Admin::CompsController < ApplicationController
    layout ‘default_scaffold’
active_scaffold :comp do |config| config.columns = [ :listing, :mls, :price, :sqft, :year_built, :basement, :basement_percent, :beds, :baths, :layout, :zip, :status, :rank ] columns[:basement].label = “B” columns[:year_built].label =“Year” columns[:basement_percent].label = “FIN” columns[:mls].label = “MLS #” columns[:layout].label = “Style” end

end

  1. app/controllers/admin/rental_comps_controller.rb
    class Admin::RentalCompsController < ApplicationController
    layout ‘default_scaffold’
active_scaffold :rental_comps do |config| config.columns = [ :listing, :monthly_rent_price, :sqft, :zip ] end

end

  1. app/views/listings/_edit_comps.rhtml


Comps



<%= render :active_scaffold => “admin/comps”,
:constraints => { :listing_id => @listing.id } %> <%= render :active_scaffold => “admin/rental_comps”, :constraints => { :listing_id => @listing.id } %>

Restrictions on embedding scaffolds

You can not put the same scaffold more than once on a page, even if the constraints are different. This is because the Dom_IDs for the two scaffolds will be exactly the same.


  1. don’t do this!

    <%= render :active_scaffold => “admin/comps”,
    :constraints => { :status => “active”, :listing_id => @listing.id },
    :label => “Active Comps” %> <%= render :active_scaffold => “admin/comps”, :constraints => { :status => “sold”, :listing_id => @listing.id }, :label => “Sold Comps” %>

Conclusion

Embedding scaffolds is a great way to re-use interfaces! Be creative, have fun!

Clone this wiki locally