removing log dir from .gitignore
[monkeycharger.git] / vendor / rails / actionpack / lib / action_controller / scaffolding.rb
blob327e8b09126072cfe7ae2638a4627863b98fac8b
1 module ActionController
2   module Scaffolding # :nodoc:
3     def self.included(base)
4       base.extend(ClassMethods)
5     end
7     # Scaffolding is a way to quickly put an Active Record class online by providing a series of standardized actions
8     # for listing, showing, creating, updating, and destroying objects of the class. These standardized actions come
9     # with both controller logic and default templates that through introspection already know which fields to display
10     # and which input types to use. Example:
11     #
12     #  class WeblogController < ActionController::Base
13     #    scaffold :entry
14     #  end
15     #
16     # This tiny piece of code will add all of the following methods to the controller:
17     #
18     #  class WeblogController < ActionController::Base
19     #    verify :method => :post, :only => [ :destroy, :create, :update ],
20     #           :redirect_to => { :action => :list }
21     #
22     #    def index
23     #      list
24     #    end
25     #
26     #    def list
27     #      @entries = Entry.find(:all)
28     #      render_scaffold "list"
29     #    end
30     #
31     #    def show
32     #      @entry = Entry.find(params[:id])
33     #      render_scaffold
34     #    end
35     #
36     #    def destroy
37     #      Entry.find(params[:id]).destroy
38     #      redirect_to :action => "list"
39     #    end
40     #
41     #    def new
42     #      @entry = Entry.new
43     #      render_scaffold
44     #    end
45     #
46     #    def create
47     #      @entry = Entry.new(params[:entry])
48     #      if @entry.save
49     #        flash[:notice] = "Entry was successfully created"
50     #        redirect_to :action => "list"
51     #      else
52     #        render_scaffold('new')
53     #      end
54     #    end
55     #
56     #    def edit
57     #      @entry = Entry.find(params[:id])
58     #      render_scaffold
59     #    end
60     #
61     #    def update
62     #      @entry = Entry.find(params[:id])
63     #      @entry.attributes = params[:entry]
64     #
65     #      if @entry.save
66     #        flash[:notice] = "Entry was successfully updated"
67     #        redirect_to :action => "show", :id => @entry
68     #      else
69     #        render_scaffold('edit')
70     #      end
71     #    end
72     #  end
73     #
74     # The <tt>render_scaffold</tt> method will first check to see if you've made your own template (like "weblog/show.erb" for
75     # the show action) and if not, then render the generic template for that action. This gives you the possibility of using the
76     # scaffold while you're building your specific application. Start out with a totally generic setup, then replace one template
77     # and one action at a time while relying on the rest of the scaffolded templates and actions.
78     module ClassMethods
79       # Adds a swath of generic CRUD actions to the controller. The +model_id+ is automatically converted into a class name unless
80       # one is specifically provide through <tt>options[:class_name]</tt>. So <tt>scaffold :post</tt> would use Post as the class
81       # and @post/@posts for the instance variables.
82       #
83       # It's possible to use more than one scaffold in a single controller by specifying <tt>options[:suffix] = true</tt>. This will
84       # make <tt>scaffold :post, :suffix => true</tt> use method names like list_post, show_post, and create_post
85       # instead of just list, show, and post. If suffix is used, then no index method is added.
86       def scaffold(model_id, options = {})
87         options.assert_valid_keys(:class_name, :suffix)
89         singular_name = model_id.to_s
90         class_name    = options[:class_name] || singular_name.camelize
91         plural_name   = singular_name.pluralize
92         suffix        = options[:suffix] ? "_#{singular_name}" : ""
94         unless options[:suffix]
95           module_eval <<-"end_eval", __FILE__, __LINE__
96             def index
97               list
98             end
99           end_eval
100         end
102         module_eval <<-"end_eval", __FILE__, __LINE__
104           verify :method => :post, :only => [ :destroy#{suffix}, :create#{suffix}, :update#{suffix} ],
105                  :redirect_to => { :action => :list#{suffix} }
108           def list#{suffix}
109             @#{singular_name}_pages, @#{plural_name} = paginate :#{plural_name}, :per_page => 10
110             render#{suffix}_scaffold "list#{suffix}"
111           end
113           def show#{suffix}
114             @#{singular_name} = #{class_name}.find(params[:id])
115             render#{suffix}_scaffold
116           end
118           def destroy#{suffix}
119             #{class_name}.find(params[:id]).destroy
120             redirect_to :action => "list#{suffix}"
121           end
123           def new#{suffix}
124             @#{singular_name} = #{class_name}.new
125             render#{suffix}_scaffold
126           end
128           def create#{suffix}
129             @#{singular_name} = #{class_name}.new(params[:#{singular_name}])
130             if @#{singular_name}.save
131               flash[:notice] = "#{class_name} was successfully created"
132               redirect_to :action => "list#{suffix}"
133             else
134               render#{suffix}_scaffold('new')
135             end
136           end
138           def edit#{suffix}
139             @#{singular_name} = #{class_name}.find(params[:id])
140             render#{suffix}_scaffold
141           end
143           def update#{suffix}
144             @#{singular_name} = #{class_name}.find(params[:id])
145             @#{singular_name}.attributes = params[:#{singular_name}]
147             if @#{singular_name}.save
148               flash[:notice] = "#{class_name} was successfully updated"
149               redirect_to :action => "show#{suffix}", :id => @#{singular_name}
150             else
151               render#{suffix}_scaffold('edit')
152             end
153           end
155           private
156             def render#{suffix}_scaffold(action=nil)
157               action ||= caller_method_name(caller)
158               # logger.info ("testing template:" + "\#{self.class.controller_path}/\#{action}") if logger
160               if template_exists?("\#{self.class.controller_path}/\#{action}")
161                 render :action => action
162               else
163                 @scaffold_class = #{class_name}
164                 @scaffold_singular_name, @scaffold_plural_name = "#{singular_name}", "#{plural_name}"
165                 @scaffold_suffix = "#{suffix}"
166                 add_instance_variables_to_assigns
168                 @template.instance_variable_set("@content_for_layout", @template.render_file(scaffold_path(action.sub(/#{suffix}$/, "")), false))
170                 if !active_layout.nil?
171                   render :file => active_layout, :use_full_path => true
172                 else
173                   render :file => scaffold_path('layout')
174                 end
175               end
176             end
178             def scaffold_path(template_name)
179               File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".erb"
180             end
182             def caller_method_name(caller)
183               caller.first.scan(/`(.*)'/).first.first # ' ruby-mode
184             end
185         end_eval
186       end
188       deprecate :scaffold => 'Controller scaffolding will be moved to a plugin in Rails 2.0. Switch to the generator or `script/plugin install scaffolding`'
189     end
190   end