Changeset 902

Show
Ignore:
Timestamp:
11/07/07 23:56:41 (1 year ago)
Author:
e.@brainspl.at
Message:

new partial() implementation, much faster

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/README

    r801 r902  
    11= Merb 
    2 <em>Lightweight MVC Ruby app server. For high performance dynamic pages.</em> 
    32 
    4 ==== Dependencies 
     3==== FrameWork Development Dependencies 
     4 
    55Install these gems first: 
    66 
     
    1717* markaby 
    1818* mailfactory 
    19 * activerecord (if you want to store sessions in a database) 
     19* Ruby2Ruby 
    2020 
    2121Then you can build the merb gem from svn trunk like so: 
    2222 
    23   $ sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory -y 
     23  $ sudo gem install mongrel json json_pure erubis mime-types rspec hpricot mocha rubigen haml markaby mailfactory Ruby2Ruby -y 
    2424  $ svn co http://svn.devjavu.com/merb/trunk merb 
    2525  $ cd merb 
     
    2828To generate a new merb app after the gem is installed: 
    2929 
    30   $ merb -g myapp 
     30  $ merb myapp 
    3131 
    32 To run your application, simply type +merb+ in the project directory. 
     32=== The +merb+ server 
    3333 
    34 == Features  
     34right now you add your routes in 
     35the appdir/config/router.rb file. So by default it runs on port 4000 
    3536 
    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   
    4139 
    42 === RouteMatcher and route compiler 
     40Or to start merb on a different port: 
    4341 
    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 
    4643 
    47 === _NEW_ RESTful Routes 
     44To start a cluster of merb servers you specify the first port and then how many  
     45servers you want spawned. SO this command will start a merb instance on ports 
     463000, 3001, 3002 
    4847 
    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 
    5049 
    51         Merb::Router.prepare do |r| 
    52           r.resources :posts 
    53           r.default_routes 
    54           r.add '/', :controller => 'files', :action => 'index' 
    55         end 
     50To start a Merb IRB console where all your models and other classes are pre loaded 
     51use the -i flag 
    5652 
    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         
     55To see all the available command loine flags use: 
     56  
     57  $ merb -h      
    6558 
    6659=== Controllers 
     
    9790mongrel handles calling it in a thread safe manner. 
    9891 
    99  
    100         class Test < Merb::Controller  
    101           def hello 
    102             # params, headers and cookies are available here. 
    103             @name = params[:name] 
    104             render  
    105           end  
    106         end 
    107  
    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 current  
    113 controller/view. 
    114  
    115 Partials compile the template ands returns a string. So you can also call 
    116 them and assign them to a var if you want: 
    117  
    118         def someaction 
    119           @one = partial(:one) 
    120           @two = partial(:two) 
    121         end 
    122  
    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 actions 
    128 You have to use the render_js instead of normal render: 
    129  
    130         def ajax_action 
    131           @posts = Post.find :all 
    132           render_js 
    133         end 
    134  
    135         # ajax_action.jerb 
    136         $('comments').update('<%=js partial(:posts) %>'); 
    137  
    138         # _posts.herb 
    139         <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 Controllers 
    151  
    152 RESTful controllers use a different dispatch system based on the request method verbs. Merb 
    153 supports multi return values based on the accept header via +respond_to+. 
    154  
    155         class Posts < Merb::Controller 
    156           # GET /posts 
    157           # GET /posts.xml 
    158           def index 
    159             @posts = Post.find :all 
    160             respond_to {|format| 
    161               format.html { render } 
    162               format.js   { render :js => :index } 
    163               format.xml  { render :xml => @posts.to_xml } 
    164             } 
    165           end 
    166  
    167           # GET /posts/1 
    168           # GET /posts/1.xml 
    169           def show 
    170           end 
    171  
    172           # GET /posts/new 
    173           def new 
    174           end 
    175  
    176           # GET /posts/1;edit 
    177           def edit 
    178           end 
    179  
    180           # POST /posts 
    181           # POST /posts.xml 
    182           def create 
    183           end 
    184  
    185           # PUT /posts/1 
    186           # PUT /posts/1.xml 
    187           def update 
    188           end 
    189  
    190           # DELETE /posts/1 
    191           # DELETE /posts/1.xml 
    192           def destroy 
    193           end 
    194         end 
    195          
    196 Learn more about this in the controller documentation. 
    19792 
    19893==== Before and after filters 
     
    247142        after Proc.new {|c| Tidy.new(c.body) }, :only => :index 
    248143 
    249 === Sessions 
    250  
    251 Sessions are available when you start merb with the sql_session set to true or the  
    252 memory_session set to true. See generated app for migration too add session table. 
    253  
    254144=== Helpers 
    255145 
     
    258148 for that controller only. 
    259149 
    260 === The +merb+ server 
    261  
    262 right now you add your routes in 
    263 the appdir/config/router.rb file. So by default it runs on port 4000 
    264  
    265         $ cd /path/to/your/merb/app 
    266         $ merb   
    267  
    268 Or to start merb on a different port: 
    269  
    270         $ merb -p 3500 
    271  
    272 To start a cluster of merb servers you specify the first port and then how many  
    273 servers you want spawned. SO this command will start a merb instance on ports 
    274 3000, 3001, 3002 
    275  
    276         $ merb -p 3000 -c 3 
    277  
    278 To start a Merb IRB console where all your models and other classes are pre loaded 
    279 use the -i flag 
    280  
    281         $merb -i 
    282  
    283150=== File uploads 
    284 This is one of the things that Merb was written for. Rails doesn't allow  
    285 multiple concurrent file uploads at once without blocking an entire rails backend for each file upload. Merb allows multiple file uploads at once. 
    286151When a file is uploaded with Merb, it gets put in a Tempfile. So  
    287152you just want to copy it to the right place on the filesystem. 
     
    289154        def upload 
    290155          puts params[:file].inspect 
    291    
    292156          FileUtils.mv params[:file][:tempfile].path, MERB_ROOT+"/uploads/#{params[:file][:filename]}" 
    293  
    294157          render 
    295158        end 
  • trunk/lib/merb/mixins/render.rb

    r807 r902  
    150150      when status = opts[:nothing] 
    151151        return render_nothing(status) 
    152          
    153       when partial = opts[:partial] 
    154         opts[:format] ||= :html 
    155         template = find_partial(partial, opts) 
    156         opts[:layout] = :none 
    157          
    158         # Add an instance variable that can be used to create the locals in the 
    159         # partial 
    160         if opts[:locals] 
    161           @_merb_partial_locals = opts[:locals] 
    162         end 
    163         opts[:clean_context] = true 
    164          
    165152      when opts[:inline] 
    166153        text = opts.delete(:inline) 
     
    282269    # partials that live there like partial('shared/foo') 
    283270    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 
    288286 
    289287    # +catch_content+ catches the thrown content from another template 
  • trunk/lib/merb/template/erubis.rb

    r654 r902  
    3636        # Creates a new Erubis object to parse the template given in +path+. 
    3737        def new_eruby_obj(path) 
    38           if @@erbs[path] && !cache_template?(path) 
     38          if @@erbs[path] && MERB_ENV ==' production' 
    3939            return @@erbs[path] 
    4040          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" %> 
    22 
    33<%= catch_content :from_partial %> 
    4 <% render :partial => "examples/throw_content" %> 
     4<% partial "examples/throw_content" %> 
    55 
    66<%= 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  
    1212  it "should render a partial" do 
    1313    c = new_controller 
    14     content = c.render :partial => "partials/#{@engine}" 
     14    content = c.partial "partials/#{@engine}" 
    1515    content.clean.should == "No Locals!" 
    1616  end 
     
    1818  it "should render a partial with locals" do 
    1919    c = new_controller 
    20     content = c.render :partial => "partials/#{@engine}", :locals => { :yo => "Locals!" } 
     20    content = c.partial "partials/#{@engine}", :yo => "Locals!"  
    2121    content.clean.should == "Locals!" 
    2222  end 
     
    3636  it "should render a partial using the .format.engine convention" do 
    3737    c = new_controller 
    38     content = c.render :partial => "partials/#{@engine}_new" 
     38    content = c.partial "partials/#{@engine}_new" 
    3939    content.clean.should == "No Locals!" 
    4040  end 
     
    8686  it "should render #{@engine} partial using .format.engine convention#{" (caching on)" if defined?(cache) && cache}" do 
    8787    c = new_controller 
    88     content = c.render :partial => "partials/#{@engine}_new" 
     88    content = c.partial "partials/#{@engine}_new" 
    8989    content.clean.should == "No Locals!" 
    9090  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"> 
    22// Javascript for Allison RDoc template 
    33// Copyright 2006 Cloudburst LLC 
     
    402402</div> 
    403403ENDIF: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:&nbsp;&nbsp;</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:&nbsp;&nbsp;</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:&nbsp;&nbsp;</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:&nbsp;&nbsp;</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:&nbsp;&nbsp;</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:&nbsp;&nbsp;</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"> 
    405405IF:title 
    406406<h1 id="item_name">%title%</h1> 
     
    572572 
    573573IF: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> 
    575575ENDIF:sourcecode 
    576576</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>&nbsp;</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>&nbsp;</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>