Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 3078

Show
Ignore:
Timestamp:
11/17/05 21:28:59 (3 years ago)
Author:
marcel
Message:

Add support for new rjs templates which wrap an update_page block.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/actionpack/CHANGELOG

    r3065 r3078  
    11*SVN* 
     2 
     3* Add support for new rjs templates which wrap an update_page block. [Marcel Molina Jr.] 
    24 
    35* Rename Version constant to VERSION. #2802 [Marcel Molina Jr.] 
  • trunk/actionpack/lib/action_view/base.rb

    r3057 r3078  
    66  end 
    77 
    8   # Action View templates can be written in two ways. If the template file has a +.rhtml+ extension then it uses a mixture of ERb  
    9   # (included in Ruby) and HTML. If the template file has a +.rxml+ extension then Jim Weirich's Builder::XmlMarkup library is used.   
     8  # Action View templates can be written in three ways. If the template file has a +.rhtml+ extension then it uses a mixture of ERb  
     9  # (included in Ruby) and HTML. If the template file has a +.rxml+ extension then Jim Weirich's Builder::XmlMarkup library is used.  
     10  # If the template file has a +.rjs+ extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator. 
    1011  #  
    1112  # = ERb 
     
    7475  #   xml.em { xml.b("emp & bold") }                    # => <em><b>emph &amp; bold</b></em> 
    7576  #   xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a> 
    76   #   xm.target("name"=>"compile", "option"=>"fast")    # => <target option="fast" name="compile"\> 
     77  #   xml.target("name"=>"compile", "option"=>"fast")   # => <target option="fast" name="compile"\> 
    7778  #                                                     # NOTE: order of attributes is not specified. 
    7879  #  
     
    116117  # 
    117118  # More builder documentation can be found at http://builder.rubyforge.org. 
     119  # 
     120  # == JavaScriptGenerator 
     121  # 
     122  # JavaScriptGenerator templates end in +.rjs+. Unlike conventional templates which are used to  
     123  # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to  
     124  # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax  
     125  # and make updates to the page where the request originated from. 
     126  #  
     127  # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block.  
     128  # 
     129  # When an .rjs action is called with +link_to_remote+, the generated JavaScript is automatically evaluated.  Example: 
     130  # 
     131  #   link_to_remote :url => {:action => 'delete'} 
     132  # 
     133  # The subsequently rendered +delete.rjs+ might look like: 
     134  # 
     135  #   page.replace_html  'sidebar', :partial => 'sidebar' 
     136  #   page.remove        "person-#{@person.id}" 
     137  #   page.visual_effect :highlight, 'user-list'  
     138  # 
     139  # This refreshes the sidebar, removes a person element and highlights the user list. 
     140  #  
     141  # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details. 
    118142  class Base 
    119143    include ERB::Util 
     
    274298      if match = delegate_template_exists?(template_path) 
    275299        match.first 
    276       elsif template_exists?(template_path, :rhtml) 
    277         'rhtml' 
    278       elsif template_exists?(template_path, :rxml) 
    279         'rxml' 
     300      elsif erb_template_exists?(template_path):        'rhtml' 
     301      elsif builder_template_exists?(template_path):    'rxml' 
     302      elsif javascript_template_exists?(template_path): 'rjs' 
    280303      else 
    281         raise ActionViewError, "No rhtml, rxml, or delegate template found for #{template_path}" 
     304        raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path}" 
    282305      end 
    283306    end 
     
    294317      template_exists?(template_path, :rxml) 
    295318    end 
     319     
     320    def javascript_template_exists?(template_path)#:nodoc: 
     321      template_exists?(template_path, :rjs) 
     322    end 
    296323 
    297324    def file_exists?(template_path)#:nodoc: 
    298       erb_template_exists?(template_path) || builder_template_exists?(template_path) || delegate_template_exists?(template_path) 
     325      %w(erb builder javascript delegate).any? do |template_type|  
     326        send("#{template_type}_template_exists?", template_path) 
     327      end 
    299328    end 
    300329 
     
    346375      # Or if the file has changed on disk and checking file mods hasn't been disabled.  
    347376      def compile_template?(template, file_name, local_assigns) 
    348         method_key = file_name || template 
     377        method_key    = file_name || template 
    349378        render_symbol = @@method_names[method_key] 
    350379 
     
    360389      # Create source code for given template 
    361390      def create_template_source(extension, template, render_symbol, locals) 
    362         if extension && (extension.to_sym == :rxml) 
    363           body = "xml = Builder::XmlMarkup.new(:indent => 2)\n" + 
    364                  "@controller.headers['Content-Type'] ||= 'text/xml'\n" + 
    365                  template 
     391        if template_requires_setup?(extension) 
     392          body = case extension.to_sym 
     393            when :rxml 
     394              "xml = Builder::XmlMarkup.new(:indent => 2)\n" + 
     395              "@controller.headers['Content-Type'] ||= 'text/xml'\n" + 
     396              template 
     397            when :rjs 
     398              "@controller.headers['Content-Type'] ||= 'text/javascript'\n" + 
     399              "update_page do |page|\n#{template}\nend" 
     400          end 
    366401        else 
    367402          body = ERB.new(template, nil, @@erb_trim_mode).src 
     
    380415      end 
    381416 
     417      def template_requires_setup?(extension) 
     418        templates_requiring_setup.include? extension.to_s 
     419      end 
     420 
     421      def templates_requiring_setup 
     422        %w(rxml rjs) 
     423      end 
     424 
    382425      def assign_method_name(extension, template, file_name) 
    383426        method_name = '_run_' 
    384  
    385         if extension && (extension.to_sym == :rxml) 
    386           method_name << 'xml_' 
    387         else 
    388           method_name << 'html_' 
    389         end 
     427        method_name << "#{extension}_" if extension 
    390428 
    391429        if file_name 
     
    397435 
    398436          method_name_file_part = i ? file_path[i+l+1,file_path.length-l-1] : file_path.clone 
    399           method_name_file_part.sub!(/\.r(ht|x)ml$/,'') 
     437          method_name_file_part.sub!(/\.r(html|xml|js)$/,'') 
    400438          method_name_file_part.tr!('/:-', '_') 
    401439          method_name_file_part.gsub!(/[^a-zA-Z0-9_]/){|s| s[0].to_s} 
     
    417455 
    418456        line_offset = @@template_args[render_symbol].size 
    419         line_offset += 2 if extension && (extension.to_sym == :rxml) 
    420  
     457        if extension 
     458          case extension.to_sym 
     459          when :rxml, :rjs 
     460            line_offset += 2 
     461          end 
     462        end 
     463         
    421464        begin 
    422465          unless file_name.blank? 
  • trunk/actionpack/test/controller/new_render_test.rb

    r2777 r3078  
    153153    def @template.name() nil end 
    154154    render :action => "potential_conflicts" 
     155  end 
     156 
     157  def delete_with_js 
     158    @project_id = 4 
     159  end 
     160 
     161  def render_js_with_explicit_template 
     162    @project_id = 4 
     163    render :template => 'test/delete_with_js' 
     164  end 
     165 
     166  def render_js_with_explicit_action_template 
     167    @project_id = 4 
     168    render :action => 'delete_with_js' 
    155169  end 
    156170 
     
    280294  end 
    281295 
     296  def test_render_rjs_with_default 
     297    get :delete_with_js 
     298    assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight('project-4',{});!, @response.body 
     299  end 
     300 
     301  def test_render_rjs_template_explicitly 
     302    get :render_js_with_explicit_template 
     303    assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight('project-4',{});!, @response.body 
     304  end 
     305 
     306  def test_rendering_rjs_action_explicitly 
     307    get :render_js_with_explicit_action_template 
     308    assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight('project-4',{});!, @response.body 
     309  end 
     310 
    282311  def test_layout_rendering 
    283312    get :layout_test