root/trunk/lib/better_nested_set_helper.rb

Revision 11, 5.0 kB (checked in by jcm, 2 years ago)

#16 some more corrs

Line 
1 module SymetrieCom
2   module Acts #:nodoc:
3    
4     # This module provides some helpers for the model classes using acts_as_nested_set.
5     # It is included by default in all views. If you need to remove it, edit the last line
6     # of init.rb.
7     #
8     module BetterNestedSetHelper
9      
10       # Prints a line of ancestors with links, on the form
11       #    root > parent > item
12       #
13       # == Usage
14       # Default is to use links to {your_cotroller}/show with the first string column of your model.
15       # You can tweak this by passing your parameters, or better, pass a block that will receive
16       # an item from your nested set tree and a boolean flag (true for current item) and that
17       # should return the line with the link.
18       #
19       # == Examples
20       #
21       #   nested_set_full_outline(category)
22       #
23       #   # non standard actions and separators
24       #   nested_set_full_outline(category, :action => :search, :separator => ' | ')
25       #
26       #   # with a block that will return the link to the item
27       #   # note that the current item will lead to another action
28       #   nested_set_full_outline(category) { |item, current?|
29       #       if current?
30       #         link_to "#{item.name} (#{item.})", product_url(:action => :show_category, :category => item.whole_url)
31       #       else
32       #         link_to "#{item.name} (#{item.})", category_url(:action => :browse, :criteria => item.whole_url)
33       #       end
34       #     }
35       #
36       # == Params are:
37       # +item+ - the object to display
38       # +hash+ - containing :
39       #  * +text_column+ - the title column, defaults to the first string column of the model
40       #  * +:action+ - the action to be called (defaults to :show)
41       #  * +:controller+ - the controller name (defaults to the model name)
42       #  * +:separator+ - the separator (defaults to >)
43       #  * +&block+ - a block { |item, current?| ... item.name }
44       #
45       def nested_set_full_outline(item, options={})
46         return if item.nil?
47         raise 'Not a nested set model !' if !item.respond_to? :acts_as_nested_set_options
48        
49         options = {
50           :text_column => options[:text_column] || item.acts_as_nested_set_options[:text_column],
51           :action => options[:action] || :show,
52           :controller => options[:controller] || item.class.to_s.underscore,
53           :separator => options[:separator] || ' > ' }
54        
55         s = ''
56         for it in item.ancestors
57           if block_given?
58             s += yield(it) + options[:separator]
59           else
60             s += link_to( it[options[:text_column]], { :controller => options[:controller], :action => options[:action], :id => it }) + options[:separator]
61           end
62         end
63         if block_given?
64           s + yield(item)
65         else
66           s + h(item[options[:text_column]])
67         end
68       end
69  
70       # Returns options for select.
71       # You can exclude some items from the tree.
72       # You can pass a block receiving an item and returning the string displayed in the select.
73       #
74       # == Usage
75       # Default is to use the whole tree and to print the first string column of your model.
76       # You can tweak this by passing your parameters, or better, pass a block that will receive
77       # an item from your nested set tree and that should return the line with the link.
78       #
79       # == Examples
80       #
81       #   nested_set_options_for_select(Category)
82       #
83       #   # show only a part of the tree, and exclude a category and its subtree
84       #   nested_set_options_for_select(selected_category, :exclude => category)
85       #
86       #   # add a custom string
87       #   nested_set_options_for_select(Category, :exclude => category) { |item| "#{' ' * item.level}#{item.name} (#{item.url})" }
88       #
89       # == Params
90       #  * +class_or_item+ - Class name or item to start the display with
91       #  * +text_column+ - the title column, defaults to the first string column of the model
92       #  * +&block+ - a block { |item| ... item.name }
93       #    If no block passed, uses {|item| "#{'··' * item.level}#{item[text_column]}"}
94       def nested_set_options_for_select(class_or_item, options=nil)
95         # find class
96         if class_or_item.is_a? Class
97           first_item = class_or_item.root
98         else
99           first_item = class_or_item
100         end
101         raise 'Not a nested set model !' if !first_item.respond_to? :acts_as_nested_set_options
102        
103         # exclude some items and all their children
104         if options.is_a? Hash
105           text_column = options[:text_column]
106           options.delete_if { |key, value| key != :exclude }
107         else
108           options = nil
109         end
110         text_column ||= first_item.acts_as_nested_set_options[:text_column]
111        
112         tree = first_item.full_set(options)
113         if block_given?
114           tree.map{|item| [yield(item), item.id] }
115         else 
116           tree.map{|item| [ "#{'··' * item.level}#{item[text_column]}", item.id]}
117         end
118       end 
119     end
120   end 
121 end
122
Note: See TracBrowser for help on using the browser.