742d290ad6c8b8ee0f3c2fb82ed80d3e0403e574
[depot.git] / record_identifier.rb
1 module ActionController
2 # The record identifier encapsulates a number of naming conventions for dealing with records, like Active Records or
3 # Active Resources or pretty much any other model type that has an id. These patterns are then used to try elevate
4 # the view actions to a higher logical level. Example:
5 #
6 # # routes
7 # map.resources :posts
8 #
9 # # view
10 # <% div_for(post) do %> <div id="post_45" class="post">
11 # <%= post.body %> What a wonderful world!
12 # <% end %> </div>
13 #
14 # # controller
15 # def destroy
16 # post = Post.find(params[:id])
17 # post.destroy
18 #
19 # respond_to do |format|
20 # format.html { redirect_to(post) } # Calls polymorphic_url(post) which in turn calls post_url(post)
21 # format.js do
22 # # Calls: new Effect.fade('post_45');
23 # render(:update) { |page| page[post].visual_effect(:fade) }
24 # end
25 # end
26 # end
27 #
28 # As the example above shows, you can stop caring to a large extent what the actual id of the post is. You just know
29 # that one is being assigned and that the subsequent calls in redirect_to and the RJS expect that same naming
30 # convention and allows you to write less code if you follow it.
31 module RecordIdentifier
32 extend self
33
34 JOIN = '_'.freeze
35 NEW = 'new'.freeze
36
37 # Returns plural/singular for a record or class. Example:
38 #
39 # partial_path(post) # => "posts/post"
40 # partial_path(Person) # => "people/person"
41 # partial_path(Person, "admin/games") # => "admin/people/person"
42 def partial_path(record_or_class, controller_path = nil)
43 name = model_name_from_record_or_class(record_or_class)
44
45 if controller_path && controller_path.include?("/")
46 "#{File.dirname(controller_path)}/#{name.partial_path}"
47 else
48 name.partial_path
49 end
50 end
51
52 # The DOM class convention is to use the singular form of an object or class. Examples:
53 #
54 # dom_class(post) # => "post"
55 # dom_class(Person) # => "person"
56 #
57 # If you need to address multiple instances of the same class in the same view, you can prefix the dom_class:
58 #
59 # dom_class(post, :edit) # => "edit_post"
60 # dom_class(Person, :edit) # => "edit_person"
61 def dom_class(record_or_class, prefix = nil)
62 singular = singular_class_name(record_or_class)
63 prefix ? "#{prefix}#{JOIN}#{singular}" : singular
64 end
65
66 # The DOM id convention is to use the singular form of an object or class with the id following an underscore.
67 # If no id is found, prefix with "new_" instead. Examples:
68 #
69 # dom_id(Post.find(45)) # => "post_45"
70 # dom_id(Post.new) # => "new_post"
71 #
72 # If you need to address multiple instances of the same class in the same view, you can prefix the dom_id:
73 #
74 # dom_id(Post.find(45), :edit) # => "edit_post_45"
75 def dom_id(record, prefix = nil)
76 if record_id = record.id
77 "#{dom_class(record, prefix)}#{JOIN}#{record_id}"
78 else
79 dom_class(record, prefix || NEW)
80 end
81 end
82
83 # Returns the plural class name of a record or class. Examples:
84 #
85 # plural_class_name(post) # => "posts"
86 # plural_class_name(Highrise::Person) # => "highrise_people"
87 def plural_class_name(record_or_class)
88 model_name_from_record_or_class(record_or_class).plural
89 end
90
91 # Returns the singular class name of a record or class. Examples:
92 #
93 # singular_class_name(post) # => "post"
94 # singular_class_name(Highrise::Person) # => "highrise_person"
95 def singular_class_name(record_or_class)
96 model_name_from_record_or_class(record_or_class).singular
97 end
98
99 private
100 def model_name_from_record_or_class(record_or_class)
101 (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
102 end
103 end
104 end