module Lolita module Controllers # This module is included in all controllers and views. UrlHelper provide methods to generate lolita # resource paths. As all resources goes to one controller (by default), than it is very difficult to # generate url with :controller and :action. # There are four methods for path: # * lolita_resources_path - goes to index action # * lolita_resource_path - goes to create, destroy or show, it depends what kind of method is used # * new_lolita_resource_path - goes to new action # * edit_lolita_resource_path - goes to edit action # All of those methods accept mapping as a first argument and optional options that # will be passed to path gererator. It is possible to pass only options, than current mapping will be used. # ====Example # # lets say, that current mapping is for posts # edit_lolita_resource_path(:id=>4) #=> /lolita/posts/4/edit # edit_lolita_resource_path(comment_mapping,:id=>1,:parent_id=>2) #=> /lolita/comments/1/edit?parent_id=2 # For custom actions there are method #lolita_resource_name that make it easier to generate custom method. # All other methods use that for real resource path method generation. module UrlHelpers def self.included(model_klass) model_klass.class_eval do # Overrides url_for when controller or view uses this helper. # It catches hash options and replaces with lolita named route # Without this method routes always looks like /lolita/rest/[method] # ====Example # # in routes.rb # lolita_for :posts # # GET /lolita/posts # # in view # url_for #=> /lolita/posts # url_for(:controller=>"/posts",:action=>:index) #=> /posts # # GET /posts # url_for #=> /posts def url_for_with_lolita options = {} if options.is_a?(Hash) && !options[:use_route] && self.respond_to?(:lolita_mapping) controller = options[:controller].to_s if Lolita.mappings[lolita_mapping.name].controllers.values.include?(controller) resource_type = { :index => :lolita_resources_path, :new => :new_lolita_resource_path, :edit => :edit_lolita_resource_path, :create => :lolita_resources_path } action = (options[:action] || params[:action]).to_sym options = self.send(resource_type[action] || :lolita_resource_path,options) end end url_for_without_lolita(options) end alias_method_chain :url_for, :lolita end end protected # Path for index. def lolita_resources_path(*args) options=args.extract_options! mapping=args[0] send(lolita_resource_name(:mapping=>mapping,:plural=>true),options) end # Path for show, create and destroy def lolita_resource_path(*args) options=args.extract_options! mapping=args[0] send(lolita_resource_name(:mapping=>mapping),options) end # Path for new. def new_lolita_resource_path(*args) options=args.extract_options! mapping=args[0] send(lolita_resource_name(:mapping=>mapping,:action=>:new),options) end # Path for edit. def edit_lolita_resource_path(*args) options=args.extract_options! options[:id]||=resource.id if resource #raise "Can edit resource without id." unless options[:id] mapping=args[0] send(lolita_resource_name(:mapping=>mapping,:action=>:edit),options) end # It return symbol, that represents named route method for path, like lolita_posts_path and so on. # It accepts those options: # * :mapping - Lolita::Mapping object, that is used to detect name of named route. # by default it uses Lolita::InternalHelpers#lolita_mapping. # * :plural - What kind of named route should use, plural or singular. # * :action - Action is used to put before named route like :edit. # ====Example # # current mapping is for posts # lolita_resource_name(:action=>:edit) #=> :edit_lolita_post_path # lolita_resource_name(:plural=>true,:action=>:list) #=> :list_lolita_posts_path # # for different mapping # lolita_resource_name(:mapping=>comments_mapping) #=> :lolita_comment_path # This methods is very useful to create your own paths in views. def lolita_resource_name(options={}) #TODO test if path is right options.assert_valid_keys(:mapping,:plural,:action) mapping=(options[:mapping]||lolita_mapping) name=!options[:plural] ? mapping.name : mapping.plural name="#{mapping.path}_#{name}" :"#{options[:action]}#{options[:action] ? "_" : ""}#{name}_path" end end end end