Changeset 902
- Timestamp:
- 11/07/07 23:56:41 (1 year ago)
- Files:
-
- trunk/README (modified) (7 diffs)
- trunk/lib/merb/mixins/render.rb (modified) (2 diffs)
- trunk/lib/merb/template/erubis.rb (modified) (1 diff)
- trunk/spec/fixtures/views/examples/template_catch_content_from_partial.html.erb (modified) (1 diff)
- trunk/spec/fixtures/views/partials/_haml.html.haml (modified) (1 diff)
- trunk/spec/fixtures/views/partials/_haml_new.html.haml (modified) (1 diff)
- trunk/spec/merb/render_spec.rb (modified) (4 diffs)
- trunk/tools/allison/cache/BODY (modified) (3 diffs)
- trunk/tools/allison/cache/INDEX (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/README
r801 r902 1 1 = Merb 2 <em>Lightweight MVC Ruby app server. For high performance dynamic pages.</em>3 2 4 ==== Dependencies 3 ==== FrameWork Development Dependencies 4 5 5 Install these gems first: 6 6 … … 17 17 * markaby 18 18 * mailfactory 19 * activerecord (if you want to store sessions in a database)19 * Ruby2Ruby 20 20 21 21 Then you can build the merb gem from svn trunk like so: 22 22 23 $ sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory -y23 $ sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory Ruby2Ruby -y 24 24 $ svn co http://svn.devjavu.com/merb/trunk merb 25 25 $ cd merb … … 28 28 To generate a new merb app after the gem is installed: 29 29 30 $ merb -gmyapp30 $ merb myapp 31 31 32 To run your application, simply type +merb+ in the project directory. 32 === The +merb+ server 33 33 34 == Features 34 right now you add your routes in 35 the appdir/config/router.rb file. So by default it runs on port 4000 35 36 36 === Mongrel handler 37 Merb has a Mongrel handler built in that parses incoming requests 38 including multipart uploads and post as well as <tt>?query=strings</tt>. Puts the 39 params into params and the cookies into cookies when it instantiates your 40 controller class. 37 $ cd /path/to/your/merb/app 38 $ merb 41 39 42 === RouteMatcher and route compiler 40 Or to start merb on a different port: 43 41 44 Reads your route definition and compiles 45 a method on the fly that will match the request path against each route and do the right thing. 42 $ merb -p 3500 46 43 47 === _NEW_ RESTful Routes 44 To start a cluster of merb servers you specify the first port and then how many 45 servers you want spawned. SO this command will start a merb instance on ports 46 3000, 3001, 3002 48 47 49 Note the <tt>r.resource :posts</tt> macro. That makes it possible to use a RESTful CRUD style controller for the posts resource 48 $ merb -p 3000 -c 3 50 49 51 Merb::Router.prepare do |r| 52 r.resources :posts 53 r.default_routes 54 r.add '/', :controller => 'files', :action => 'index' 55 end 50 To start a Merb IRB console where all your models and other classes are pre loaded 51 use the -i flag 56 52 57 The <tt>r.default_routes</tt> routes adds the standard routes: 58 59 /controller/action/id.xml 60 /controller/action/id 61 /controller/action.xml 62 /controller/action 63 /controller.xml # index action 64 /controller # index action 53 $ merb -i 54 55 To see all the available command loine flags use: 56 57 $ merb -h 65 58 66 59 === Controllers … … 97 90 mongrel handles calling it in a thread safe manner. 98 91 99 100 class Test < Merb::Controller101 def hello102 # params, headers and cookies are available here.103 @name = params[:name]104 render105 end106 end107 108 You can also render partials like so:109 110 <%= partial(:comments) %>111 112 This assumes a <tt>_comments.rhtml</tt> file in the same view dir as the current113 controller/view.114 115 Partials compile the template ands returns a string. So you can also call116 them and assign them to a var if you want:117 118 def someaction119 @one = partial(:one)120 @two = partial(:two)121 end122 123 Partials can also render views from other controllers by specifying the path:124 125 partial('/shared/foo')126 127 Merb also allows for returning JavaScript instead of html for ajax actions128 You have to use the render_js instead of normal render:129 130 def ajax_action131 @posts = Post.find :all132 render_js133 end134 135 # ajax_action.jerb136 $('comments').update('<%=js partial(:posts) %>');137 138 # _posts.herb139 <ul>140 <% @posts.each do |p| %>141 <li>142 <%= p.title %><br />143 <%= p.body %>144 </li>145 <% end %>146 </ul>147 148 The .jerb template is used for this purpose.149 150 ==== RESTful Controllers151 152 RESTful controllers use a different dispatch system based on the request method verbs. Merb153 supports multi return values based on the accept header via +respond_to+.154 155 class Posts < Merb::Controller156 # GET /posts157 # GET /posts.xml158 def index159 @posts = Post.find :all160 respond_to {|format|161 format.html { render }162 format.js { render :js => :index }163 format.xml { render :xml => @posts.to_xml }164 }165 end166 167 # GET /posts/1168 # GET /posts/1.xml169 def show170 end171 172 # GET /posts/new173 def new174 end175 176 # GET /posts/1;edit177 def edit178 end179 180 # POST /posts181 # POST /posts.xml182 def create183 end184 185 # PUT /posts/1186 # PUT /posts/1.xml187 def update188 end189 190 # DELETE /posts/1191 # DELETE /posts/1.xml192 def destroy193 end194 end195 196 Learn more about this in the controller documentation.197 92 198 93 ==== Before and after filters … … 247 142 after Proc.new {|c| Tidy.new(c.body) }, :only => :index 248 143 249 === Sessions250 251 Sessions are available when you start merb with the sql_session set to true or the252 memory_session set to true. See generated app for migration too add session table.253 254 144 === Helpers 255 145 … … 258 148 for that controller only. 259 149 260 === The +merb+ server261 262 right now you add your routes in263 the appdir/config/router.rb file. So by default it runs on port 4000264 265 $ cd /path/to/your/merb/app266 $ merb267 268 Or to start merb on a different port:269 270 $ merb -p 3500271 272 To start a cluster of merb servers you specify the first port and then how many273 servers you want spawned. SO this command will start a merb instance on ports274 3000, 3001, 3002275 276 $ merb -p 3000 -c 3277 278 To start a Merb IRB console where all your models and other classes are pre loaded279 use the -i flag280 281 $merb -i282 283 150 === File uploads 284 This is one of the things that Merb was written for. Rails doesn't allow285 multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once.286 151 When a file is uploaded with Merb, it gets put in a Tempfile. So 287 152 you just want to copy it to the right place on the filesystem. … … 289 154 def upload 290 155 puts params[:file].inspect 291 292 156 FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}" 293 294 157 render 295 158 end trunk/lib/merb/mixins/render.rb
r807 r902 150 150 when status = opts[:nothing] 151 151 return render_nothing(status) 152 153 when partial = opts[:partial]154 opts[:format] ||= :html155 template = find_partial(partial, opts)156 opts[:layout] = :none157 158 # Add an instance variable that can be used to create the locals in the159 # partial160 if opts[:locals]161 @_merb_partial_locals = opts[:locals]162 end163 opts[:clean_context] = true164 165 152 when opts[:inline] 166 153 text = opts.delete(:inline) … … 282 269 # partials that live there like partial('shared/foo') 283 270 def partial(template, locals={}) 284 options = {:partial => template, :locals => locals} 285 options.merge!(:format => @_template_format) if @_template_format 286 render options 287 end 271 choose_template_format(Merb.available_mime_types, {}) unless @_template_format 272 template = find_partial(template) 273 @_merb_partial_locals = locals 274 unless template 275 raise TemplateNotFound, "No template matched at #{unmatched}" 276 end 277 278 engine = Template.engine_for(template) 279 options = { 280 :file => template, 281 :view_context => clean_view_context(engine), 282 :opts => {:locals => locals} 283 } 284 engine.transform(options) 285 end 288 286 289 287 # +catch_content+ catches the thrown content from another template trunk/lib/merb/template/erubis.rb
r654 r902 36 36 # Creates a new Erubis object to parse the template given in +path+. 37 37 def new_eruby_obj(path) 38 if @@erbs[path] && !cache_template?(path)38 if @@erbs[path] && MERB_ENV ==' production' 39 39 return @@erbs[path] 40 40 else trunk/spec/fixtures/views/examples/template_catch_content_from_partial.html.erb
r795 r902 1 <% render :partial =>"examples/throw_content" %>1 <% partial "examples/throw_content" %> 2 2 3 3 <%= catch_content :from_partial %> 4 <% render :partial =>"examples/throw_content" %>4 <% partial "examples/throw_content" %> 5 5 6 6 <%= catch_content :from_partial %> trunk/spec/fixtures/views/partials/_haml.html.haml
r795 r902 1 = defined?(yo) && yo? yo : "No Locals!"1 = respond_to?(:yo) ? yo : "No Locals!" trunk/spec/fixtures/views/partials/_haml_new.html.haml
r761 r902 1 = defined?(yo) && yo? yo : "No Locals!"1 = respond_to?(:yo) ? yo : "No Locals!" trunk/spec/merb/render_spec.rb
r795 r902 12 12 it "should render a partial" do 13 13 c = new_controller 14 content = c. render :partial =>"partials/#{@engine}"14 content = c.partial "partials/#{@engine}" 15 15 content.clean.should == "No Locals!" 16 16 end … … 18 18 it "should render a partial with locals" do 19 19 c = new_controller 20 content = c. render :partial => "partials/#{@engine}", :locals => { :yo => "Locals!" }20 content = c.partial "partials/#{@engine}", :yo => "Locals!" 21 21 content.clean.should == "Locals!" 22 22 end … … 36 36 it "should render a partial using the .format.engine convention" do 37 37 c = new_controller 38 content = c. render :partial =>"partials/#{@engine}_new"38 content = c.partial "partials/#{@engine}_new" 39 39 content.clean.should == "No Locals!" 40 40 end … … 86 86 it "should render #{@engine} partial using .format.engine convention#{" (caching on)" if defined?(cache) && cache}" do 87 87 c = new_controller 88 content = c. render :partial =>"partials/#{@engine}_new"88 content = c.partial "partials/#{@engine}_new" 89 89 content.clean.should == "No Locals!" 90 90 end trunk/tools/allison/cache/BODY
r798 r902 1 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><title>%title%</title><link type="text/css" href="%style_url%" rel="stylesheet" media="screen"/><script type="text/javascript">1 <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><title>%title%</title><link type="text/css" rel="stylesheet" href="%style_url%" media="screen"/><script type="text/javascript"> 2 2 // Javascript for Allison RDoc template 3 3 // Copyright 2006 Cloudburst LLC … … 402 402 </div> 403 403 ENDIF:methods 404 <div id="spacer"></div><div class="navigation dark index" id="class_wrapper"><div class="list_header"><h3>All classes</h3></div><div class="list_header_link"><a href="#" onclick="toggle('class'); toggleText('class_link'); return false;" id="class_link">Hide...</a></div><div class="clear"></div><div id="class"><form><label for="filter_class">Filter: </label><input type="text" onKeyPress="return disableSubmit(event);" id="filter_class" onKeyUp="return filterList('class', this.value, event);"></input></form></div></div><div class="navigation dark index" id="file_wrapper"><div class="list_header"><h3>All files</h3></div><div class="list_header_link"><a href="#" onclick="toggle('file'); toggleText('file_link'); return false;" id="file_link">Hide...</a></div><div class="clear"></div><div id="file"><form><label for="filter_file">Filter: </label><input type="text" onKeyPress="return disableSubmit(event);" id="filter_file" onKeyUp="return filterList('file', this.value, event);"></input></form></div></div><div class="navigation dark index" id="method_wrapper"><div class="list_header"><h3>All methods</h3></div><div class="list_header_link"><a href="#" onclick="toggle('method'); toggleText('method_link'); return false;" id="method_link">Show...</a></div><div class="clear"></div><div id="method"><form><label for="filter_method">Filter: </label><input type="text" onKeyPress="return disableSubmit(event);" id="filter_method" onKeyUp="return filterList('method', this.value, event);"></input></form></div></div><div class="curve" id="left_curve_0"></div><div class="curve" id="left_curve_1"></div><div class="curve" id="left_curve_2"></div><div class="curve" id="left_curve_3"></div><div class="curve" id="left_curve_4"></div><div class="curve" id="left_curve_5"></div><div class="curve" id="left_curve_6"></div><div class="curve" id="left_curve_7"></div><div class="curve" id="left_curve_8"></div><div class="curve" id="left_curve_9"></div></div><div id="content">404 <div id="spacer"></div><div class="navigation dark index" id="class_wrapper"><div class="list_header"><h3>All classes</h3></div><div class="list_header_link"><a onclick="toggle('class'); toggleText('class_link'); return false;" id="class_link" href="#">Hide...</a></div><div class="clear"></div><div id="class"><form><label for="filter_class">Filter: </label><input type="text" onKeyPress="return disableSubmit(event);" id="filter_class" onKeyUp="return filterList('class', this.value, event);"></input></form></div></div><div class="navigation dark index" id="file_wrapper"><div class="list_header"><h3>All files</h3></div><div class="list_header_link"><a onclick="toggle('file'); toggleText('file_link'); return false;" id="file_link" href="#">Hide...</a></div><div class="clear"></div><div id="file"><form><label for="filter_file">Filter: </label><input type="text" onKeyPress="return disableSubmit(event);" id="filter_file" onKeyUp="return filterList('file', this.value, event);"></input></form></div></div><div class="navigation dark index" id="method_wrapper"><div class="list_header"><h3>All methods</h3></div><div class="list_header_link"><a onclick="toggle('method'); toggleText('method_link'); return false;" id="method_link" href="#">Show...</a></div><div class="clear"></div><div id="method"><form><label for="filter_method">Filter: </label><input type="text" onKeyPress="return disableSubmit(event);" id="filter_method" onKeyUp="return filterList('method', this.value, event);"></input></form></div></div><div class="curve" id="left_curve_0"></div><div class="curve" id="left_curve_1"></div><div class="curve" id="left_curve_2"></div><div class="curve" id="left_curve_3"></div><div class="curve" id="left_curve_4"></div><div class="curve" id="left_curve_5"></div><div class="curve" id="left_curve_6"></div><div class="curve" id="left_curve_7"></div><div class="curve" id="left_curve_8"></div><div class="curve" id="left_curve_9"></div></div><div id="content"> 405 405 IF:title 406 406 <h1 id="item_name">%title%</h1> … … 572 572 573 573 IF:sourcecode 574 <p class="source_link" id="%aref%-show-link"><a href="#" onclick="toggle('%aref%-source'); toggleText('%aref%-link'); return false;" id="%aref%-link">Show source...</a></p><div class="source" id="%aref%-source"><pre>%sourcecode%</pre></div>574 <p class="source_link" id="%aref%-show-link"><a onclick="toggle('%aref%-source'); toggleText('%aref%-link'); return false;" id="%aref%-link" href="#">Show source...</a></p><div class="source" id="%aref%-source"><pre>%sourcecode%</pre></div> 575 575 ENDIF:sourcecode 576 576 </div></div> trunk/tools/allison/cache/INDEX
r798 r902 1 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><title>%title%</title><link type="text/css" href="rdoc-style.css" rel="stylesheet" media="screen"/><meta content="0;url=%initial_page%" http-equiv="refresh"/></head><body><div id="container"><div class="curve" id="preheader_curve_0"></div><div class="curve" id="preheader_curve_1"></div><div class="curve" id="preheader_curve_2"></div><div class="curve" id="preheader_curve_3"></div><div class="curve" id="preheader_curve_4"></div><div class="curve" id="preheader_curve_5"></div><div class="curve" id="preheader_curve_6"></div><div class="curve" id="preheader_curve_7"></div><div class="curve" id="preheader_curve_8"></div><div class="curve" id="preheader_curve_9"></div><div id="header"><span id="title"><p> </p><h1>Ruby Documentation</h1></span></div><div class="clear"></div><div id="redirect"><a href="%initial_page%"><h1>Redirect</h1></a></div></div></body></html>1 <html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"><head><meta content="text/html; charset=utf-8" http-equiv="Content-Type"/><title>%title%</title><link type="text/css" rel="stylesheet" href="rdoc-style.css" media="screen"/><meta content="0;url=%initial_page%" http-equiv="refresh"/></head><body><div id="container"><div class="curve" id="preheader_curve_0"></div><div class="curve" id="preheader_curve_1"></div><div class="curve" id="preheader_curve_2"></div><div class="curve" id="preheader_curve_3"></div><div class="curve" id="preheader_curve_4"></div><div class="curve" id="preheader_curve_5"></div><div class="curve" id="preheader_curve_6"></div><div class="curve" id="preheader_curve_7"></div><div class="curve" id="preheader_curve_8"></div><div class="curve" id="preheader_curve_9"></div><div id="header"><span id="title"><p> </p><h1>Ruby Documentation</h1></span></div><div class="clear"></div><div id="redirect"><a href="%initial_page%"><h1>Redirect</h1></a></div></div></body></html>
