Changeset 1079
- Timestamp:
- 12/11/07 05:09:01 (1 year ago)
- Files:
-
- trunk/lib/merb.rb (modified) (1 diff)
- trunk/lib/merb/abstract_controller.rb (modified) (1 diff)
- trunk/lib/merb/controller.rb (modified) (1 diff)
- trunk/lib/merb/mail_controller.rb (modified) (1 diff)
- trunk/lib/merb/mixins/controller.rb (modified) (2 diffs)
- trunk/lib/merb/mixins/general_controller.rb (added)
- trunk/lib/merb/mixins/web_controller.rb (modified) (1 diff)
- trunk/lib/merb/part_controller.rb (modified) (1 diff)
- trunk/spec/merb/controller_spec.rb (modified) (5 diffs)
- trunk/spec/merb/mail_controller_spec.rb (modified) (1 diff)
- trunk/spec/merb/part_controller_spec.rb (modified) (1 diff)
- trunk/spec/spec_helper.rb (modified) (1 diff)
- trunk/spec/spec_helpers (added)
- trunk/spec/spec_helpers/url_shared_behaviour.rb (copied) (copied from trunk/spec/merb/controller_spec.rb) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/lib/merb.rb
r1017 r1079 52 52 autoload :ViewContextMixin, 'merb/mixins/view_context' 53 53 autoload :WebControllerMixin, 'merb/mixins/web_controller' 54 autoload :GeneralControllerMixin, 'merb/mixins/general_controller' 54 55 autoload :Caching, 'merb/caching' 55 56 autoload :AbstractController, 'merb/abstract_controller' trunk/lib/merb/abstract_controller.rb
r1051 r1079 3 3 class AbstractController 4 4 include Merb::RenderMixin 5 include Merb::GeneralControllerMixin 5 6 6 7 class_inheritable_accessor :before_filters trunk/lib/merb/controller.rb
r1056 r1079 206 206 end 207 207 208 private 209 210 # This method is here to overwrite the one in the general_controller mixin 211 # The method ensures that when a url is generated with a hash, it contains a controller 212 def get_controller_for_url_generation(options) 213 controller = options[:controller] || params[:controller] 214 controller = params[:controller] if controller == :current 215 controller 216 end 217 208 218 end 209 219 trunk/lib/merb/mail_controller.rb
r1074 r1079 250 250 end 251 251 252 protected 253 def route 254 @base_controller.route if @base_controller 255 end 256 257 private 258 # This method is here to overwrite the one in the general_controller mixin 259 # The method ensures that when a url is generated with a hash, it contains a controller 260 def get_controller_for_url_generation(opts) 261 puts @base_controller.params[:controller] if @base_controller 262 controller = opts[:controller] || ( @base_controller.params[:controller] if @base_controller) 263 raise "No Controller Specified for url()" unless controller 264 controller 265 end 266 267 252 268 end 253 269 end trunk/lib/merb/mixins/controller.rb
r1073 r1079 3 3 module ControllerMixin 4 4 5 # Returns a URL according to the defined route. Accepts the path and 6 # an options hash. The path specifies the route requested. The options 7 # hash fills in the dynamic parts of the route. 8 # 9 # Merb routes can often be one-way; if they use a regex to define 10 # the route, then knowing the controller & action won't be enough 11 # to reverse-generate the route. However, if you use the default 12 # /controller/action/id?query route, +default_route+ can generate 13 # it for you. 14 # 15 # For easy reverse-routes that use a Regex, be sure to also add 16 # a name to the route, so +url+ can find it. 17 # 18 # Nested resources such as: 19 # 20 # r.resources :blogposts do |post| 21 # post.resources :comments 22 # end 23 # 24 # Provide the following routes: 25 # 26 # [:blogposts, "/blogposts"] 27 # [:blogpost, "/blogposts/:id"] 28 # [:edit_blogpost, "/blogposts/:id/edit"] 29 # [:new_blogpost, "/blogposts/new"] 30 # [:custom_new_blogpost, "/blogposts/new/:action"] 31 # [:comments, "/blogposts/:blogpost_id/comments"] 32 # [:comment, "/blogposts/:blogpost_id/comments/:id"] 33 # [:edit_comment, "/blogposts/:blogpost_id/comments/:id/edit"] 34 # [:new_comment, "/blogposts/:blogpost_id/comments/new"] 35 # [:custom_new_comment, "/blogposts/:blogpost_id/comments/new/:action"] 36 # 37 # 38 # ==== Parameters 39 # 40 # :route_name: - Symbol that represents a named route that you want to use, such as +:edit_post+. 41 # :new_params: - Parameters to be passed to the generated URL, such as the +id+ for a record to edit. 42 # 43 # ==== Examples 44 # 45 # @post = Post.find(1) 46 # @comment = @post.comments.find(1) 47 # 48 # url(:blogposts) # => /blogposts 49 # url(:new_post) # => /blogposts/new 50 # url(:blogpost, @post) # => /blogposts/1 51 # url(:edit_blogpost, @post) # => /blogposts/1/edit 52 # url(:custom_new_blogpost, :action => 'alternate') # => /blogposts/new/alternate 5 # # Returns a URL according to the defined route. Accepts the path and 6 # # an options hash. The path specifies the route requested. The options 7 # # hash fills in the dynamic parts of the route. 8 # # 9 # # Merb routes can often be one-way; if they use a regex to define 10 # # the route, then knowing the controller & action won't be enough 11 # # to reverse-generate the route. However, if you use the default 12 # # /controller/action/id?query route, +default_route+ can generate 13 # # it for you. 14 # # 15 # # For easy reverse-routes that use a Regex, be sure to also add 16 # # a name to the route, so +url+ can find it. 17 # # 18 # # Nested resources such as: 19 # # 20 # # r.resources :blogposts do |post| 21 # # post.resources :comments 22 # # end 23 # # 24 # # Provide the following routes: 25 # # 26 # # [:blogposts, "/blogposts"] 27 # # [:blogpost, "/blogposts/:id"] 28 # # [:edit_blogpost, "/blogposts/:id/edit"] 29 # # [:new_blogpost, "/blogposts/new"] 30 # # [:custom_new_blogpost, "/blogposts/new/:action"] 31 # # [:comments, "/blogposts/:blogpost_id/comments"] 32 # # [:comment, "/blogposts/:blogpost_id/comments/:id"] 33 # # [:edit_comment, "/blogposts/:blogpost_id/comments/:id/edit"] 34 # # [:new_comment, "/blogposts/:blogpost_id/comments/new"] 35 # # [:custom_new_comment, "/blogposts/:blogpost_id/comments/new/:action"] 36 # # 37 # # 38 # # ==== Parameters 39 # # 40 # # :route_name: - Symbol that represents a named route that you want to use, such as +:edit_post+. 41 # # :new_params: - Parameters to be passed to the generated URL, such as the +id+ for a record to edit. 42 # # 43 # # ==== Examples 44 # # 45 # # @post = Post.find(1) 46 # # @comment = @post.comments.find(1) 47 # # 48 # # url(:blogposts) # => /blogposts 49 # # url(:new_post) # => /blogposts/new 50 # # url(:blogpost, @post) # => /blogposts/1 51 # # url(:edit_blogpost, @post) # => /blogposts/1/edit 52 # # url(:custom_new_blogpost, :action => 'alternate') # => /blogposts/new/alternate 53 # # 54 # # url(:comments, :blogpost => @post) # => /blogposts/1/comments 55 # # url(:new_comment, :blogpost => @post) # => /blogposts/1/comments/new 56 # # url(:comment, @comment) # => /blogposts/1/comments/1 57 # # url(:edit_comment, @comment) # => /blogposts/1/comments/1/edit 58 # # url(:custom_new_comment, :blogpost => @post) 59 # # 60 # # url(:page => 2) # => /posts/show/1?page=2 61 # # url(:new_post, :page => 3) # => /posts/new?page=3 62 # # url('/go/here', :page => 3) # => /go/here?page=3 63 # # 64 # # url(:controller => "welcome") # => /welcome 65 # # url(:controller => "welcome", :action => "greet") 66 # # # => /welcome/greet 67 # # 68 # def url(route_name = nil, new_params = {}) 69 # if route_name.is_a?(Hash) 70 # new_params = route_name 71 # route_name = nil 72 # end 53 73 # 54 # url(:comments, :blogpost => @post) # => /blogposts/1/comments 55 # url(:new_comment, :blogpost => @post) # => /blogposts/1/comments/new 56 # url(:comment, @comment) # => /blogposts/1/comments/1 57 # url(:edit_comment, @comment) # => /blogposts/1/comments/1/edit 58 # url(:custom_new_comment, :blogpost => @post) 59 # 60 # url(:page => 2) # => /posts/show/1?page=2 61 # url(:new_post, :page => 3) # => /posts/new?page=3 62 # url('/go/here', :page => 3) # => /go/here?page=3 63 # 64 # url(:controller => "welcome") # => /welcome 65 # url(:controller => "welcome", :action => "greet") 66 # # => /welcome/greet 67 # 68 def url(route_name = nil, new_params = {}) 69 if route_name.is_a?(Hash) 70 new_params = route_name 71 route_name = nil 72 end 73 74 url = if new_params.respond_to?(:keys) && route_name.nil? && 75 !(new_params.keys & [:controller, :action, :id]).empty? 76 url_from_default_route(new_params) 77 elsif route_name.nil? && !route.regexp? 78 url_from_route(route, new_params) 79 elsif route_name.nil? 80 request.path + (new_params.empty? ? "" : "?" + params_to_query_string(new_params)) 81 elsif route_name.is_a?(Symbol) 82 url_from_route(route_name, new_params) 83 elsif route_name.is_a?(String) 84 route_name + (new_params.empty? ? "" : "?" + params_to_query_string(new_params)) 85 else 86 raise "URL not generated: #{route_name.inspect}, #{new_params.inspect}" 87 end 88 url = MerbHandler.path_prefix + url if MerbHandler.path_prefix 89 url 90 end 91 92 def url_from_route(symbol, new_params = {}) 93 if new_params.respond_to?(:new_record?) && new_params.new_record? 94 symbol = "#{symbol}".singularize.to_sym 95 new_params = {} 96 end 97 route = symbol.is_a?(Symbol) ? Merb::Router.named_routes[symbol] : symbol 98 unless route 99 raise InternalServerError, "URL could not be constructed. Route symbol not found: #{symbol.inspect}" 100 end 101 path = route.generate(new_params, params) 102 keys = route.symbol_segments 103 if new_params.is_a? Hash 104 if ext = format_extension(new_params) 105 new_params.delete(:format) 106 path += "." + ext 107 end 108 extras = new_params.reject{ |k, v| keys.include?(k) } 109 path += "?" + params_to_query_string(extras) unless extras.empty? 110 end 111 path 112 end 113 114 # this is pretty ugly, but it works. TODO: make this cleaner 115 def url_from_default_route(new_params) 116 query_params = new_params.reject do |k,v| 117 [:controller, :action, :id, :format].include?(k) 118 end 119 controller = new_params[:controller] || params[:controller] 120 controller = params[:controller] if controller == :current 121 url = "/#{controller}" 122 if new_params[:action] || new_params[:id] || 123 new_params[:format] || !query_params.empty? 124 action = new_params[:action] || params[:action] 125 url += "/#{action}" 126 end 127 if new_params[:id] 128 url += "/#{new_params[:id]}" 129 end 130 if format = new_params[:format] 131 format = params[:format] if format == :current 132 url += ".#{format}" 133 end 134 unless query_params.empty? 135 url += "?" + params_to_query_string(query_params) 136 end 137 url 138 end 139 140 protected 141 142 # Creates query string from params, supporting nested arrays and hashes. 143 # ==== Example 144 # params_to_query_string(:user => {:filter => {:name => "quux*"}, :order => ["name"]}) 145 # # => user[filter][name]=quux%2A&user[order][]=name 146 def params_to_query_string(value, prefix = nil) 147 case value 148 when Array 149 value.map { |v| 150 params_to_query_string(v, "#{prefix}[]") 151 } * "&" 152 when Hash 153 value.map { |k, v| 154 params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) 155 } * "&" 156 else 157 "#{prefix}=#{escape(value)}" 158 end 159 end 160 161 # +format_extension+ dictates when named route URLs generated by the url 162 # method will have a file extension. It will return either false or the format 163 # extension to append. 164 # 165 # ==== Configuration Options 166 # 167 # By default, non-HTML URLs will be given an extension. It is posible 168 # to override this behaviour by setting +:use_format_in_urls+ in your 169 # Merb config (merb.yml) to either true/false. 170 # 171 # +true+ Results in all URLs (even HTML) being given extensions. 172 # This effect is often desirable when you have many formats and dont 173 # wish to treat .html any differently than any other format. 174 # +false+ Results in no URLs being given extensions and +format+ 175 # gets treated just like any other param (default). 176 # 177 # ==== Method parameters 178 # 179 # +new_params+ - New parameters to be appended to the URL 180 # 181 # ==== Examples 182 # 183 # url(:post, :id => post, :format => 'xml') 184 # # => /posts/34.xml 185 # 186 # url(:accounts, :format => 'yml') 187 # # => /accounts.yml 188 # 189 # url(:edit_product, :id => 3, :format => 'html') 190 # # => /products/3 191 # 192 def format_extension(new_params={}) 193 use_format = Merb::Server.config[:use_format_in_urls] 194 if use_format.nil? 195 prms = params.merge(new_params) 196 use_format = prms[:format] != 'html' && prms[:format] 197 end 198 use_format 199 end 74 # url = if new_params.respond_to?(:keys) && route_name.nil? && 75 # !(new_params.keys & [:controller, :action, :id]).empty? 76 # url_from_default_route(new_params) 77 # elsif route_name.nil? && !route.regexp? 78 # url_from_route(route, new_params) 79 # elsif route_name.nil? 80 # request.path + (new_params.empty? ? "" : "?" + params_to_query_string(new_params)) 81 # elsif route_name.is_a?(Symbol) 82 # url_from_route(route_name, new_params) 83 # elsif route_name.is_a?(String) 84 # route_name + (new_params.empty? ? "" : "?" + params_to_query_string(new_params)) 85 # else 86 # raise "URL not generated: #{route_name.inspect}, #{new_params.inspect}" 87 # end 88 # url = MerbHandler.path_prefix + url if MerbHandler.path_prefix 89 # url 90 # end 91 # 92 # def url_from_route(symbol, new_params = {}) 93 # if new_params.respond_to?(:new_record?) && new_params.new_record? 94 # symbol = "#{symbol}".singularize.to_sym 95 # new_params = {} 96 # end 97 # route = symbol.is_a?(Symbol) ? Merb::Router.named_routes[symbol] : symbol 98 # unless route 99 # raise InternalServerError, "URL could not be constructed. Route symbol not found: #{symbol.inspect}" 100 # end 101 # path = route.generate(new_params, params) 102 # keys = route.symbol_segments 103 # if new_params.is_a? Hash 104 # if ext = format_extension(new_params) 105 # new_params.delete(:format) 106 # path += "." + ext 107 # end 108 # extras = new_params.reject{ |k, v| keys.include?(k) } 109 # path += "?" + params_to_query_string(extras) unless extras.empty? 110 # end 111 # path 112 # end 113 # 114 # # this is pretty ugly, but it works. TODO: make this cleaner 115 # def url_from_default_route(new_params) 116 # query_params = new_params.reject do |k,v| 117 # [:controller, :action, :id, :format].include?(k) 118 # end 119 # controller = new_params[:controller] || params[:controller] 120 # controller = params[:controller] if controller == :current 121 # url = "/#{controller}" 122 # if new_params[:action] || new_params[:id] || 123 # new_params[:format] || !query_params.empty? 124 # action = new_params[:action] || params[:action] 125 # url += "/#{action}" 126 # end 127 # if new_params[:id] 128 # url += "/#{new_params[:id]}" 129 # end 130 # if format = new_params[:format] 131 # format = params[:format] if format == :current 132 # url += ".#{format}" 133 # end 134 # unless query_params.empty? 135 # url += "?" + params_to_query_string(query_params) 136 # end 137 # url 138 # end 139 # 140 # protected 141 # 142 # # Creates query string from params, supporting nested arrays and hashes. 143 # # ==== Example 144 # # params_to_query_string(:user => {:filter => {:name => "quux*"}, :order => ["name"]}) 145 # # # => user[filter][name]=quux%2A&user[order][]=name 146 # def params_to_query_string(value, prefix = nil) 147 # case value 148 # when Array 149 # value.map { |v| 150 # params_to_query_string(v, "#{prefix}[]") 151 # } * "&" 152 # when Hash 153 # value.map { |k, v| 154 # params_to_query_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k)) 155 # } * "&" 156 # else 157 # "#{prefix}=#{escape(value)}" 158 # end 159 # end 160 # 161 # # +format_extension+ dictates when named route URLs generated by the url 162 # # method will have a file extension. It will return either false or the format 163 # # extension to append. 164 # # 165 # # ==== Configuration Options 166 # # 167 # # By default, non-HTML URLs will be given an extension. It is posible 168 # # to override this behaviour by setting +:use_format_in_urls+ in your 169 # # Merb config (merb.yml) to either true/false. 170 # # 171 # # +true+ Results in all URLs (even HTML) being given extensions. 172 # # This effect is often desirable when you have many formats and dont 173 # # wish to treat .html any differently than any other format. 174 # # +false+ Results in no URLs being given extensions and +format+ 175 # # gets treated just like any other param (default). 176 # # 177 # # ==== Method parameters 178 # # 179 # # +new_params+ - New parameters to be appended to the URL 180 # # 181 # # ==== Examples 182 # # 183 # # url(:post, :id => post, :format => 'xml') 184 # # # => /posts/34.xml 185 # # 186 # # url(:accounts, :format => 'yml') 187 # # # => /accounts.yml 188 # # 189 # # url(:edit_product, :id => 3, :format => 'html') 190 # # # => /products/3 191 # # 192 # def format_extension(new_params={}) 193 # use_format = Merb::Server.config[:use_format_in_urls] 194 # if use_format.nil? 195 # prms = params.merge(new_params) 196 # use_format = prms[:format] != 'html' && prms[:format] 197 # end 198 # use_format 199 # end 200 200 201 201 # Renders the block given as a parameter using chunked … … 352 352 end 353 353 354 # Creates an MD5 hashed token based on the current time.355 # 356 # ==== Example357 # make_token358 # # => "b9a82e011694cc13a4249731b9e83cea"359 # 360 def make_token361 require 'digest/md5'362 Digest::MD5.hexdigest("#{inspect}#{Time.now}#{rand}")363 end364 365 # Escapes the string representation of +obj+ and escapes366 # it for use in XML.367 # 368 # ==== Parameter369 # 370 # +obj+ - The object to escape for use in XML.371 # 372 def escape_xml(obj)373 obj.to_s.gsub(/[&<>"']/) { |s| Merb::Const::ESCAPE_TABLE[s] }374 end375 alias h escape_xml376 alias html_escape escape_xml377 378 # Escapes +s+ for use in a URL.379 # 380 # ==== Parameter381 # 382 # +s+ - String to URL escape.383 # 384 def escape(s)385 Mongrel::HttpRequest.escape(s)386 end387 388 # Unescapes a string (i.e., reverse URL escaping).389 # 390 # ==== Parameter391 # 392 # +s+ - String to unescape.393 # 394 def unescape(s)395 Mongrel::HttpRequest.unescape(s)396 end354 # # Creates an MD5 hashed token based on the current time. 355 # # 356 # # ==== Example 357 # # make_token 358 # # # => "b9a82e011694cc13a4249731b9e83cea" 359 # # 360 # def make_token 361 # require 'digest/md5' 362 # Digest::MD5.hexdigest("#{inspect}#{Time.now}#{rand}") 363 # end 364 # 365 # # Escapes the string representation of +obj+ and escapes 366 # # it for use in XML. 367 # # 368 # # ==== Parameter 369 # # 370 # # +obj+ - The object to escape for use in XML. 371 # # 372 # def escape_xml(obj) 373 # obj.to_s.gsub(/[&<>"']/) { |s| Merb::Const::ESCAPE_TABLE[s] } 374 # end 375 # alias h escape_xml 376 # alias html_escape escape_xml 377 # 378 # # Escapes +s+ for use in a URL. 379 # # 380 # # ==== Parameter 381 # # 382 # # +s+ - String to URL escape. 383 # # 384 # def escape(s) 385 # Mongrel::HttpRequest.escape(s) 386 # end 387 # 388 # # Unescapes a string (i.e., reverse URL escaping). 389 # # 390 # # ==== Parameter 391 # # 392 # # +s+ - String to unescape. 393 # # 394 # def unescape(s) 395 # Mongrel::HttpRequest.unescape(s) 396 # end 397 397 398 398 end trunk/lib/merb/mixins/web_controller.rb
r1047 r1079 28 28 @web_controller.response 29 29 end 30 31 def route 32 request.route 33 end 30 34 31 35 end trunk/lib/merb/part_controller.rb
r908 r1079 16 16 @_body 17 17 end 18 19 private 20 21 # This method is here to overwrite the one in the general_controller mixin 22 # The method ensures that when a url is generated with a hash, it contains a controller 23 def get_controller_for_url_generation(opts) 24 controller = opts[:controller] || @web_controller.params[:controller] 25 raise "No Controller Specified for url()" unless controller 26 controller 27 end 18 28 end 19 29 end trunk/spec/merb/controller_spec.rb
r895 r1079 17 17 18 18 describe Merb::Controller, "url generator tests" do 19 20 it_should_behave_like "class with general url generation" 21 19 22 def new_url_controller(route, params = {:action => 'show', :controller => 'Test'}) 20 23 request = OpenStruct.new … … 27 30 end 28 31 29 before(:all) do30 Merb::Router.prepare do |r|31 @resource_routes = r.resources(:blogs)32 r.resources(:gardens) do |gardens|33 @nested_resource = gardens.resources :flowers34 end35 @test_route = r.match("/the/:place/:goes/here").to(:controller => "Test", :action => "show").name(:test)36 @default_route = r.default_routes37 end38 end32 # before(:all) do 33 # Merb::Router.prepare do |r| 34 # @resource_routes = r.resources(:blogs) 35 # r.resources(:gardens) do |gardens| 36 # @nested_resource = gardens.resources :flowers 37 # end 38 # @test_route = r.match("/the/:place/:goes/here").to(:controller => "Test", :action => "show").name(:test) 39 # @default_route = r.default_routes 40 # end 41 # end 39 42 40 it "should generate a url from a route using a hash" do41 c = new_url_controller(@test_route, :place => "1")42 c.url_from_route(@test_route, :goes => "g").should == "/the/1/g/here"43 end43 # it "should generate a url from a route using a hash" do 44 # c = new_url_controller(@test_route, :place => "1") 45 # c.url_from_route(@test_route, :goes => "g").should == "/the/1/g/here" 46 # end 44 47 45 it "should generate a url from a route using an object" do46 c = new_url_controller(@test_route, :place => "2")47 obj = OpenStruct.new(:goes => "elsewhere")48 c.url_from_route(@test_route, obj).should == "/the/2/elsewhere/here"49 end48 # it "should generate a url from a route using an object" do 49 # c = new_url_controller(@test_route, :place => "2") 50 # obj = OpenStruct.new(:goes => "elsewhere") 51 # c.url_from_route(@test_route, obj).should == "/the/2/elsewhere/here" 52 # end 50 53 51 it "should generate a url and tack extra params on as a query string" do52 c = new_url_controller(@test_route, :place => "1")53 c.url_from_route(@test_route, :goes => "g", :page => 2).should == "/the/1/g/here?page=2"54 end54 # it "should generate a url and tack extra params on as a query string" do 55 # c = new_url_controller(@test_route, :place => "1") 56 # c.url_from_route(@test_route, :goes => "g", :page => 2).should == "/the/1/g/here?page=2" 57 # end 55 58 56 it "should generate a url directly from a hash using the current route as a default" do57 c = new_url_controller(@test_route, :goes => "swimmingly")58 c.url(:place => "provo").should == "/the/provo/swimmingly/here"59 end59 # it "should generate a url directly from a hash using the current route as a default" do 60 # c = new_url_controller(@test_route, :goes => "swimmingly") 61 # c.url(:place => "provo").should == "/the/provo/swimmingly/here" 62 # end 60 63 61 it "should generate a default route url with just :controller" do62 c = new_url_controller(@default_route)63 c.url(:controller => "welcome").should == "/welcome"64 end64 # it "should generate a default route url with just :controller" do 65 # c = new_url_controller(@default_route) 66 # c.url(:controller => "welcome").should == "/welcome" 67 # end 65 68 66 69 it "should generate a default route url with just :action" do … … 74 77 end 75 78 76 it 'should generate urls from nested resources' do77 c = new_url_controller(@nested_resource, :garden => 5)78 c.url(:flower, :garden_id => 1, :id => 3).should == "/gardens/1/flowers/3"79 end79 # it 'should generate urls from nested resources' do 80 # c = new_url_controller(@nested_resource, :garden => 5) 81 # c.url(:flower, :garden_id => 1, :id => 3).should == "/gardens/1/flowers/3" 82 # end 80 83 81 84 it "should generate a default route url with an extra param" do … … 106 109 end 107 110 108 it "should generate a default route url with all options" do109 c = new_url_controller(@default_route, :controller => "foo", :action => "bar")110 c.url(:controller => "foo", :action => "bar", :id => "baz", :format => :js, :monkey => "quux").should == "/foo/bar/baz.js?monkey=quux"111 end112 111 # it "should generate a default route url with all options" do 112 # c = new_url_controller(@default_route, :controller => "foo", :action => "bar") 113 # c.url(:controller => "foo", :action => "bar", :id => "baz", :format => :js, :monkey => "quux").should == "/foo/bar/baz.js?monkey=quux" 114 # end 115 # 113 116 it "should handle nested nested and more nested hashes and arrays" do 114 117 c = new_url_controller(@default_route, :controller => "foo", :action => "bar") … … 118 121 end 119 122 120 it "should handle an object as the second arg" do121 c = new_url_controller(@resource_routes, :controller => "blogs", :action => "show")122 blog = mock("blog")123 blog.should_receive(:id).once.and_return(7)124 url = c.url(:blog, blog)125 url.should == "/blogs/7"126 end123 # it "should handle an object as the second arg" do 124 # c = new_url_controller(@resource_routes, :controller => "blogs", :action => "show") 125 # blog = mock("blog") 126 # blog.should_receive(:id).once.and_return(7) 127 # url = c.url(:blog, blog) 128 # url.should == "/blogs/7" 129 # end 127 130 128 it "should point to /blogs/:blog_id if @blog is not new_record" do129 c = new_url_controller(@resource_routes, :controller => "blogs", :action => "index")130 blog = mock("blog")131 blog.should_receive(:id).once.and_return(7)132 blog.should_receive(:new_record?).once.and_return(false)133 url = c.url(:blog, blog)134 url.should == "/blogs/7"135 end131 # it "should point to /blogs/:blog_id if @blog is not new_record" do 132 # c = new_url_controller(@resource_routes, :controller => "blogs", :action => "index") 133 # blog = mock("blog") 134 # blog.should_receive(:id).once.and_return(7) 135 # blog.should_receive(:new_record?).once.and_return(false) 136 # url = c.url(:blog, blog) 137 # url.should == "/blogs/7" 138 # end 136 139 137 it "should point to /blogs/ if @blog is new_record" do138 c = new_url_controller(@resource_routes, :controller => "blogs", :action => "index")139 blog = mock("blog")140 blog.should_receive(:new_record?).once.and_return(true)141 url = c.url(:blog, blog)142 url.should == "/blogs/"143 end140 # it "should point to /blogs/ if @blog is new_record" do 141 # c = new_url_controller(@resource_routes, :controller => "blogs", :action => "index") 142 # blog = mock("blog") 143 # blog.should_receive(:new_record?).once.and_return(true) 144 # url = c.url(:blog, blog) 145 # url.should == "/blogs/" 146 # end 144 147 end trunk/spec/merb/mail_controller_spec.rb
r986 r1079 144 144 145 145 end 146 147 describe "Merb::MailController with url generation" do 148 149 it_should_behave_like "class with general url generation" 150 it_should_behave_like "non routeable controller with url mixin" 151 152 def new_url_controller(route, params = {:action => 'show', :controller => 'Test'}) 153 request = OpenStruct.new 154 request.route = route 155 request.params = params 156 response = OpenStruct.new 157 response.read = "" 158 159 @controller = Merb::Controller.build(request, response) 160 TestMailController.new(params, @controller) 161 end 162 163 it "should raise an error if no controller is specified and the base controller is not set" do 164 c = new_url_controller(@default_route, {}) 165 lambda do 166 the_url = c.url(:action => "bar") 167 end.should raise_error 168 end 169 170 it "should use the base controller when it is set to generate a url when no :controller option is specified" do 171 c = new_url_controller(@defualt_route, :controller => "foo") 172 lambda do 173 the_url = c.url(:action => "bar") 174 the_url.should == "/foo/bar" 175 end.should_not raise_error 176 end 177 end trunk/spec/merb/part_controller_spec.rb
r904 r1079 91 91 92 92 end 93 94 describe "A Merb Part Controller with urls" do 95 96 it_should_behave_like "class with general url generation" 97 it_should_behave_like "non routeable controller with url mixin" 98 99 def new_url_controller(route, params = {:action => 'show', :controller => 'Test'}) 100 request = OpenStruct.new 101 request.route = route 102 request.params = params 103 response = OpenStruct.new 104 response.read = "" 105 106 @controller = Merb::Controller.build(request, response) 107 TodoPart.new(@controller) 108 end 109 110 it "should use the web_controllers type if no controller is specified" do 111 c = new_url_controller(@default_route, :controller => "my_controller") 112 the_url = c.url(:action => "bar") 113 the_url.should == "/my_controller/bar" 114 end 115 116 it "should raise an error if the web_controller's params[:controller] is not set" do 117 c = new_url_controller(@default_route, {}) 118 lambda do 119 the_url = c.url(:action => "bar") 120 the_url.should == "/my_controller/bar" 121 end.should raise_error 122 end 123 124 end trunk/spec/spec_helper.rb
r1077 r1079 13 13 14 14 FIXTURES = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures')) 15 16 require File.join(File.dirname(__FILE__), "spec_helpers", "url_shared_behaviour") 15 17 16 18 Spec::Runner.configure do |config| trunk/spec/spec_helpers/url_shared_behaviour.rb
r895 r1079 1 require 'ostruct' 2 require File.dirname(__FILE__) + '/../spec_helper' 3 4 describe "Merb::Controller" do 5 6 # not sure what this tests 7 # it "should instantiate" do 8 # c = new_controller 9 # @request.env.should == c.request.env 10 # end 11 12 it "should have a default layout of application.rhtml" do 13 c = new_controller 14 c._layout.should == :application 15 end 16 end 17 18 describe Merb::Controller, "url generator tests" do 19 def new_url_controller(route, params = {:action => 'show', :controller => 'Test'}) 20 request = OpenStruct.new 21 request.route = route 22 request.params = params 23 response = OpenStruct.new 24 response.read = "" 25 26 Merb::Controller.build(request, response) 27 end 1 describe "class with general url generation", :shared => true do 28 2 29 3 before(:all) do … … 37 11 end 38 12 end 39 13 14 40 15 it "should generate a url from a route using a hash" do 41 16 c = new_url_controller(@test_route, :place => "1") 42 17 c.url_from_route(@test_route, :goes => "g").should == "/the/1/g/here" 43 18 end 44 19 45 20 it "should generate a url from a route using an object" do 46 21 c = new_url_controller(@test_route, :place => "2") … … 48 23 c.url_from_route(@test_route, obj).should == "/the/2/elsewhere/here" 49 24 end 50 25 51 26 it "should generate a url and tack extra params on as a query string" do 52 27 c = new_url_controller(@test_route, :place => "1") … … 63 38 c.url(:controller => "welcome").should == "/welcome" 64 39 end 65 66 it "should generate a default route url with just :action" do67 c = new_url_controller(@default_route, :controller => "foo")68 c.url(:action => "baz").should == "/foo/baz"69 end70 40 71 it "should generate a default route url with just :id" do72 c = new_url_controller(@default_route, :controller => "foo", :action => "bar")73 c.url(:id => "23").should == "/foo/bar/23"74 end75 76 41 it 'should generate urls from nested resources' do 77 42 c = new_url_controller(@nested_resource, :garden => 5) 78 43 c.url(:flower, :garden_id => 1, :id => 3).should == "/gardens/1/flowers/3" 79 44 end 80 81 it "should generate a default route url with an extra param" do82 c = new_url_controller(@default_route, :controller => "foo", :action => "bar")83 c.url(:controller => :current, :monkey => "quux").should == "/foo/bar?monkey=quux"84 end85 86 it "should generate a default route url with extra params" do87 c = new_url_controller(@default_route, :controller => "foo", :action => "bar")88 url = c.url(:controller => :current, :monkey => "quux", :cow => "moo")89 url.should match(%r{/foo/bar?.*monkey=quux})90 url.should match(%r{/foo/bar?.*cow=moo})91 end92 93 it "should generate a default route url with extra params and an array" do94 c = new_url_controller(@default_route, :controller => "foo", :action => "bar")95 c.url(:controller => :current, :monkey => [1,2]).should == "/foo/bar?monkey[]=1&monkey[]=2"96 end97 45 98 it "should generate a default route url with extra params and a hash" do 99 c = new_url_controller(@default_route, :controller => "foo", :action => "bar") 100 c.url(:controller => :current, :animals => {:cow => "moo"}).should == "/foo/bar?animals[cow]=moo" 101 end 102 103 it "should generate a default route url with :action and :format" do 104 c = new_url_controller(@default_route, :controller => "foo", :action => "bar") 105 c.url(:action => :recent, :format => :txt).should == "/foo/recent.txt" 106 end 46 # it "should generate a default route url with an extra param" do 47 # c = new_url_controller(@default_route, :controller => "foo", :action => "bar") 48 # c.url(:controller => :current, :monkey => "quux").should == "/foo/bar?monkey=quux" 49 # end 107 50 108 51 it "should generate a default route url with all options" do 109 52 c = new_url_controller(@default_route, :controller => "foo", :action => "bar") 110 53 c.url(:controller => "foo", :action => "bar", :id => "baz", :format => :js, :monkey => "quux").should == "/foo/bar/baz.js?monkey=quux" 111 end112 113 it "should handle nested nested and more nested hashes and arrays" do114 c = new_url_controller(@default_route, :controller => "foo", :action => "bar")115 url = c.url(:controller => :current, :user => {:filter => {:name => "quux*"}, :order => ["name"]})116 url.should match(%r{/foo/bar?.*user\[filter\]\[name\]=quux%2A})117 url.should match(%r{/foo/bar?.*user\[order\]\[\]=name})118 54 end 119 55 … … 125 61 url.should == "/blogs/7" 126 62 end 127 63 128 64 it "should point to /blogs/:blog_id if @blog is not new_record" do 129 65 c = new_url_controller(@resource_routes, :controller => "blogs", :action => "index") … … 134 70 url.should == "/blogs/7" 135 71 end 136 72 137 73 it "should point to /blogs/ if @blog is new_record" do 138 74 c = new_url_controller(@resource_routes, :controller => "blogs", :action => "index") … … 143 79 end 144 80 end 81 82 describe "non routeable controller with url mixin", :shared => true do 83 84 before(:all) do 85 Merb::Router.prepare do |r| 86 @resource_routes = r.resources(:blogs) 87 r.resources(:gardens) do |gardens| 88 @nested_resource = gardens.resources :flowers 89 end 90 @test_route = r.match("/the/:place/:goes/here").to(:controller => "Test", :action => "show").name(:test) 91 @default_route = r.default_routes 92 end 93 end 94 95 it "should route when given a controller and an action" do 96 c = new_url_controller(@default_route, :controller => "blah") 97 the_url = c.url(:controller => "foo", :action => "bar") 98 the_url.should == "/foo/bar" 99 end 100 101 it "should generate a route when only a controller is given" do 102 c = new_url_controller(@default_route, :controller => "blah") 103 the_url = c.url(:controller => "foo") 104 the_url.should == "/foo" 105 end 106 107 it "should generate a route with controller action and extra options" do 108 c = new_url_controller(@default_route, :controller => "blah") 109 the_url = c.url(:controller => "foo", :action => "bar", :cool => "false") 110 the_url.should == "/foo/bar?cool=false" 111 end 112
