Mange-field_helpers 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +7 -0
- data/README.rdoc +240 -0
- data/VERSION.yml +4 -0
- data/lib/field_helpers.rb +50 -0
- data/lib/field_helpers/base.rb +179 -0
- data/lib/field_helpers/helper.rb +203 -0
- data/lib/field_helpers/kinds.rb +255 -0
- data/spec/field_helpers/base_spec.rb +202 -0
- data/spec/field_helpers/helper_spec.rb +92 -0
- data/spec/field_helpers/kinds_spec.rb +336 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +51 -0
- metadata +67 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
# Copyright (c) 2008
|
2
|
+
# * Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
# The methods defined here will be included in all views as helpers. Read the documentation
|
25
|
+
# for each of them to get a good understanding of how everything works.
|
26
|
+
module FieldHelpers::Helper
|
27
|
+
|
28
|
+
#
|
29
|
+
# Returns a rendering of a specific field from a given record.
|
30
|
+
#
|
31
|
+
# == Features
|
32
|
+
# * Display translated field name
|
33
|
+
# * Display view-friendly variants of values
|
34
|
+
# * Email adresses as <tt>mail_to</tt> links
|
35
|
+
# * Money as <tt>number_to_currency</tt> dictates
|
36
|
+
# * nil and blank values behave differently, but safely
|
37
|
+
# * And more!
|
38
|
+
# * Consistent markup
|
39
|
+
#
|
40
|
+
# == Value
|
41
|
+
# The logic behind the value being displayed is passed off to <tt>field_value</tt>. See documentation for
|
42
|
+
# <tt>field_value</tt> for more information about that.
|
43
|
+
#
|
44
|
+
# Before being used, the resulting value will also be passed through <tt>simple_format</tt>, which will
|
45
|
+
# convert newlines and paragraph breaks into their proper html elements.
|
46
|
+
#
|
47
|
+
# == Title / Label / Field name
|
48
|
+
# By default, the field name will be whatever the record says it should be through <tt>human_attribute_name</tt>,
|
49
|
+
# but you can customize this by giving a translation key to the <tt>:title</tt> option.
|
50
|
+
#
|
51
|
+
# == Visibility
|
52
|
+
# When the value is blank and <tt>:no_blanks</tt> option is set to true, nothing will be returned from this helper.
|
53
|
+
# This is useful for displaying a huge bunch of optional fields where most of them will not be entered,
|
54
|
+
# since only those with actual values will take space on the view.
|
55
|
+
#
|
56
|
+
# The <tt>:no_blanks</tt> option will be passed on to the <tt>field_value</tt> helper, so the fallback translation values
|
57
|
+
# will not be used.
|
58
|
+
#
|
59
|
+
def field(record, field, options = {})
|
60
|
+
no_blanks = options[:no_blanks]
|
61
|
+
title = options.delete(:title)
|
62
|
+
|
63
|
+
label = I18n.translate(title) if title
|
64
|
+
label ||= record.class.human_attribute_name(field.to_s)
|
65
|
+
|
66
|
+
value = field_value(record, field, options)
|
67
|
+
|
68
|
+
# If no_blanks is set, we should not output anything if the value is empty
|
69
|
+
return "" if no_blanks and value.blank?
|
70
|
+
|
71
|
+
formatted_value = simple_format(value)
|
72
|
+
content_tag(:div, "#{content_tag(:strong, label)}#{formatted_value}", :class => 'field')
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# Returns a view-friendly representation of a record's field value.
|
77
|
+
#
|
78
|
+
# == Friendly representation
|
79
|
+
# Sometimes you want to display an optional value on a page, so you need to think about the event of
|
80
|
+
# the value being nil. Now, if you want to display a placholder for the nil value, you'll have to place
|
81
|
+
# a conditional in your view, which clutters and adds complexity. By using this helper, you can avoid
|
82
|
+
# situations like these.
|
83
|
+
#
|
84
|
+
# If the field you specify is nil or empty the first working variant of a placeholder will be displayed
|
85
|
+
# instead:
|
86
|
+
# * Model.human_attribute_name("no_field_name")
|
87
|
+
# * I18n.translate(:"activerecord.attributes.blank_field_value")
|
88
|
+
# * "" (Empty string)
|
89
|
+
#
|
90
|
+
# Now, this is a lot easier to handle on a per-case basis. If you want to always display an empty value
|
91
|
+
# instead of looking for the translations, you can do so by passing the <tt>:no_blanks</tt> option.
|
92
|
+
#
|
93
|
+
# == Special value kinds
|
94
|
+
# Some fields need special treatment. It could be a field containing money values which you want to be
|
95
|
+
# formatted correctly. It could be that you want the date component from a DateTime. You could want a
|
96
|
+
# simple "Yes" or "No" for a boolean.
|
97
|
+
#
|
98
|
+
# You can do this be specifying the <tt>:kind</tt> parameter (or relying on the auto-detection). The following
|
99
|
+
# kinds are supported:
|
100
|
+
# [<tt>:money</tt>] Value is passed through number_to_currency. Auto-discovered when field name contains
|
101
|
+
# "price" or "amount".
|
102
|
+
#
|
103
|
+
# [<tt>:email</tt>] Value is passed through mail_to. Auto-discovered when field name is "email".
|
104
|
+
#
|
105
|
+
# [<tt>:date</tt>] Value is casted to date and then to string. Effectivly displaying only the date component
|
106
|
+
# of any date-like value. Autodiscovered when field name ends with "_on" or value is a
|
107
|
+
# Date object.
|
108
|
+
#
|
109
|
+
# [<tt>:time</tt>] Value is casted to time and then to a formatted string following the template <tt>:time</tt>.
|
110
|
+
# This removes anything but the hour, minute and second from the value. Never auto-
|
111
|
+
# discovered.
|
112
|
+
#
|
113
|
+
# [<tt>:datetime</tt>] Value is being casted to a time and then directly to a string. Auto-discovered when field
|
114
|
+
# name ends with "_at" or value is a Time or TimeWithZone object.
|
115
|
+
#
|
116
|
+
# [<tt>:bool</tt>] Value will be a translation of the key <tt>:yes</tt> or <tt>:no</tt> depending on whether or not the
|
117
|
+
# value evaluates to true. Auto-discovered when the field name ends with a question mark or
|
118
|
+
# if the value is an explicit <tt>true</tt> or <tt>false</tt>.
|
119
|
+
#
|
120
|
+
# [<tt>:link</tt>] This is pretty special. See section about it below. Auto-discovered when value is a kind
|
121
|
+
# of ActiveRecord::Base.
|
122
|
+
#
|
123
|
+
# == Links
|
124
|
+
# You can get actual links from using this helper. This is very useful for displaying associations that can
|
125
|
+
# be nil. If you set the kind to <tt>:link</tt> this specific logic will kick in. If there is an active association
|
126
|
+
# in the specified field (e.g. <tt>record.field</tt> is not <tt>nil</tt>) a link to the value will be generated.
|
127
|
+
#
|
128
|
+
# field_value(@order_item, :order, :kind => :link) # => "<a href=\"/orders/1\">Order One</a>"
|
129
|
+
#
|
130
|
+
# === Self-links
|
131
|
+
# You can also use this to get a link to the object itself. If the field does not contain an ActiveRecord it
|
132
|
+
# is assumed that you want a self-link. The text of the link will then be assigned to the field specified and
|
133
|
+
# the target to the object itself.
|
134
|
+
#
|
135
|
+
# field_value(@user, :full_name, :kind => :link) # => "<a href=\"/users/532\">Kevin Bacon</a>"
|
136
|
+
#
|
137
|
+
# In the case above, the following could be seen as equivalent if @order has a user attribute:
|
138
|
+
#
|
139
|
+
# field_value(@order, :user, :link_field => :full_name)
|
140
|
+
# # => "<a href=\"/users/532\">Kevin Bacon</a>"
|
141
|
+
#
|
142
|
+
# === Link text
|
143
|
+
# The link text will be genrated from the first option that is not evaluated to false:
|
144
|
+
# * Text of the <tt>:link_text</tt> option
|
145
|
+
# * The field name specified in <tt>:link_field</tt> of the linked to object (or the specified field name if it's a
|
146
|
+
# self-link)
|
147
|
+
# * The value of the first field that the target responds to:
|
148
|
+
# * <tt>name</tt>
|
149
|
+
# * <tt>title</tt>
|
150
|
+
# * <tt>label</tt>
|
151
|
+
# * The linked to object turned to a string (e.g. <tt>to_s</tt>)
|
152
|
+
#
|
153
|
+
# As you can see, in most cases you might not need to specify the text at all, but everything will be handled
|
154
|
+
# for you.
|
155
|
+
#
|
156
|
+
# === Custom path
|
157
|
+
# You might want to be able to link to a custom path, for example in the case of nested resources. You can specify
|
158
|
+
# a custom path via the <tt>:link_path</tt>.
|
159
|
+
#
|
160
|
+
# field_value(@customer, :user, :link_path => customer_user_path(@customer, @customer.user))
|
161
|
+
# # => "<a href=\"customers/10/users/23\">John Doe</a>"
|
162
|
+
#
|
163
|
+
# The method above have a large disadvantage, though. If +@customer.user+ is <tt>nil</tt>, you will get an excaption while
|
164
|
+
# generating the URL with <tt>customer_user_path</tt>. You can avoid this by specifying a lambda as the path:
|
165
|
+
#
|
166
|
+
# field_value(@customer, :user, :link_path => lambda { customer_user_path(@customer, @customer.user) })
|
167
|
+
# # => "<a href=\"customers/10/users/23\">John Doe</a>"
|
168
|
+
#
|
169
|
+
# As an added bonus, you could also get the target into the block via the first argument. Here is a full example:
|
170
|
+
#
|
171
|
+
# field_value(@customer, :user, :link_path => lambda { |c| customer_user_path(c, c.user) })
|
172
|
+
# # => "<a href=\"customers/10/users/23\">John Doe</a>"
|
173
|
+
#
|
174
|
+
# field_value(@customer, :user,
|
175
|
+
# :link_text => "Search Google for this user's name",
|
176
|
+
# :link_path => lambda { |cust| "http://www.google.com/search?q=#{cust.full_name}" })
|
177
|
+
# # => "<a href=\"http://www.google.com/search?q=Kevin Bacon\">Search Google for this user's name</a>"
|
178
|
+
#
|
179
|
+
# === Additional options
|
180
|
+
# Any extra options to the link_to method (like class attributes) can be passed to <tt>:link_options</tt>. They will be
|
181
|
+
# forwarded correctly.
|
182
|
+
#
|
183
|
+
# == Custom format
|
184
|
+
# You can do your own small custom formatting on top of all this by passing the <tt>:format</tt> option. The
|
185
|
+
# first instance of "%s" will be replaced by the value. Say that you want to display a normal number
|
186
|
+
# as a percent by appending a % to the end of it, just pass
|
187
|
+
# :format => "%s%%"
|
188
|
+
# The double percent sign is to quote it from substitution.
|
189
|
+
#
|
190
|
+
#
|
191
|
+
# == Example
|
192
|
+
# field_value(@user, :name) # => "John"
|
193
|
+
# field_value(@user, :name, :format => "Mr. %s") # => "Mr. John"
|
194
|
+
# field_value(@user, :pay, :kind => :money) # => "$1,000.00"
|
195
|
+
# field_value(@user, :active?) # => "Yes"
|
196
|
+
# field_value(@user, :group) # => "<a href=\"/groups/14\">Administrators</a>"
|
197
|
+
# field_value(@user, :created_at, :kind => :time) # => "13:45:02"
|
198
|
+
#
|
199
|
+
def field_value(record, field, options = {})
|
200
|
+
FieldHelpers::Base.new(self, record, field, options).value_for_view
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
# Copyright (c) 2008
|
2
|
+
# * Magnus Bergmark
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#
|
23
|
+
|
24
|
+
# This class handles the auto-discovery and formatting of the built-in kinds.
|
25
|
+
# It will be loaded and registered by FieldHelpers module.
|
26
|
+
#
|
27
|
+
# == Kind discovery
|
28
|
+
# Kind discovery works around two things: Field name and field value.
|
29
|
+
#
|
30
|
+
# The field name is pretty straightforward; it's stuff like "name", "created_at"
|
31
|
+
# and similar names. Value is also pretty easy since it's just the raw value for
|
32
|
+
# the specified field name, which could be instances of other classes, <tt>nil</tt>, etc.
|
33
|
+
#
|
34
|
+
# A method that takes care of discovering types is called "discoverer". If a method
|
35
|
+
# returns <tt>true</tt> (explicit!) the discovery will be concluded positive and the kind
|
36
|
+
# be assumed from there. No more discoverers will be called.
|
37
|
+
#
|
38
|
+
# Here is an example discovery method:
|
39
|
+
# def discover_dog(field, value)
|
40
|
+
# true if value =~ /dog/i or field == :pet
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# == Kind conversion
|
44
|
+
# Before being returned, the *value* (not default value) will always be converted to
|
45
|
+
# the proper kind. This involves calling a "helper method" as they are called. A helper
|
46
|
+
# method should take one argument: An instance of the "base" (FieldHelpers::Base).
|
47
|
+
#
|
48
|
+
# You most probably want to get a hold of the actual value in question, which you can
|
49
|
+
# do by calling <tt>original_value</tt> on the base. Avoid calling <tt>value</tt> since you might
|
50
|
+
# end up in an infinite loop in which <tt>value</tt> will call your helper and your helper will
|
51
|
+
# call <tt>value</tt> again.
|
52
|
+
#
|
53
|
+
# If you want to access any options given to the field helpers, you can do so through
|
54
|
+
# the base object. You can actually access about anything, even call discoverers and
|
55
|
+
# other helpers if you so wish.
|
56
|
+
#
|
57
|
+
# A conversion helper should always return a string, else the behavior is undefined.
|
58
|
+
#
|
59
|
+
# Here is a couple of example helper methods:
|
60
|
+
#
|
61
|
+
# def convert_title(base)
|
62
|
+
# base.original_value.to_s.titleize
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# def convert_password(base)
|
66
|
+
# if base.options[:password_full]
|
67
|
+
# base.original_value.gsub(/./, '*')
|
68
|
+
# else
|
69
|
+
# "************"
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
class FieldHelpers::Kinds
|
74
|
+
class << self
|
75
|
+
|
76
|
+
# Returns a hash of <tt>kind</tt> => <tt>method proc</tt> for every kind with a helper
|
77
|
+
# method. This is done through metaprogamming so you only need to add methods
|
78
|
+
# here if you want to add new methods to the FieldHelpers core.
|
79
|
+
def available_kinds_with_helpers
|
80
|
+
flat = self.methods.collect do |m|
|
81
|
+
if m.to_s =~ /convert_to_(.*)/
|
82
|
+
[$1.to_sym, self.method(m.to_sym)]
|
83
|
+
else
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Hash[*flat.compact.flatten]
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a hash of <tt>kind</tt> => <tt>method proc</tt> for every kind with a
|
92
|
+
# discoverer. This is done through metaprogamming so you only need to add methods
|
93
|
+
# here if you want to add new methods to the FieldHelpers core.
|
94
|
+
def available_kinds_with_discoverers
|
95
|
+
flat = self.methods.collect do |m|
|
96
|
+
if m.to_s =~ /discover_(.*)/
|
97
|
+
[$1.to_sym, self.method(m.to_sym)]
|
98
|
+
else
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
Hash[*flat.compact.flatten]
|
104
|
+
end
|
105
|
+
|
106
|
+
#### Discovery methods
|
107
|
+
|
108
|
+
# Discovers dates by looking at the following:
|
109
|
+
# * Field name ends with "_on"
|
110
|
+
# * Value is a <tt>Date</tt> instance
|
111
|
+
# If any of these are true, the discovery will be positive.
|
112
|
+
def discover_date(name, value)
|
113
|
+
true if name =~ /_on$/ or value.is_a?(Date)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Discovers datetimes by looking at the following:
|
117
|
+
# * Field name ends with "_at"
|
118
|
+
# * Value is a <tt>DateTime</tt> instance
|
119
|
+
# * Value is a <tt>Time</tt> instance
|
120
|
+
# * Value is a <tt>TimeWithZone</tt> instance
|
121
|
+
# If any of these are true, the discovery will be positive.
|
122
|
+
def discover_datetime(name, value)
|
123
|
+
true if name =~ /_at$/ or value.is_a?(DateTime) or value.is_a?(Time) or value.is_a?(::ActiveSupport::TimeWithZone)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Discovers booleans by looking at the following:
|
127
|
+
# * Field name ends with "?"
|
128
|
+
# * Value is <tt>true</tt>
|
129
|
+
# * Value is <tt>false</tt>
|
130
|
+
# If any of these are true, the discovery will be positive.
|
131
|
+
def discover_bool(name, value)
|
132
|
+
true if name =~ /\?$/ or value === true or value === false
|
133
|
+
end
|
134
|
+
|
135
|
+
# Discovers money by looking at the following:
|
136
|
+
# * Field name contains "cost"
|
137
|
+
# * Field name contains "price"
|
138
|
+
# If any of these are true, the discovery will be positive.
|
139
|
+
def discover_money(name, value)
|
140
|
+
true if name =~ /cost|price/
|
141
|
+
end
|
142
|
+
|
143
|
+
# Discovers email by looking at the following:
|
144
|
+
# * Field name contains "email"
|
145
|
+
# * Field name contains "e-mail"
|
146
|
+
# * Field name contains "e_mail"
|
147
|
+
# If any of these are true, the discovery will be positive.
|
148
|
+
def discover_email(name, value)
|
149
|
+
true if name =~ /e[-_]?mail/
|
150
|
+
end
|
151
|
+
|
152
|
+
# Discovers links by looking at value and seeing if it is an <tt>ActiveRecord::Base</tt>
|
153
|
+
# instance
|
154
|
+
def discover_link(name, value)
|
155
|
+
true if value.kind_of?(::ActiveRecord::Base)
|
156
|
+
end
|
157
|
+
|
158
|
+
### Conversion methods
|
159
|
+
|
160
|
+
# Just calls to_s on the value
|
161
|
+
def convert_to_string(base)
|
162
|
+
base.original_value.to_s
|
163
|
+
end
|
164
|
+
|
165
|
+
# Converts to a <tt>Date</tt> instace by calling <tt>to_date</tt> and then calls <tt>to_s</tt> on it
|
166
|
+
def convert_to_date(base)
|
167
|
+
base.original_value.to_date.to_s
|
168
|
+
end
|
169
|
+
|
170
|
+
# Converts to a <tt>Time</tt> instance through <tt>to_time</tt> and then calls <tt>to_s</tt> with the
|
171
|
+
# <tt>:time</tt> formatting.
|
172
|
+
# This converts full <tt>Time</tt> objects like "2009-02-06 12:34:55 +0100" into just "12:34:55"
|
173
|
+
def convert_to_time(base)
|
174
|
+
base.original_value.to_time.to_s(:time)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Converts to <tt>Time</tt> with <tt>to_time</tt> and then calls <tt>to_s</tt>. This will display dates
|
178
|
+
# in their full form.
|
179
|
+
def convert_to_datetime(base)
|
180
|
+
base.original_value.to_time.to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
# If value evaluates to true, returns a translation of "yes" from <tt>I18n</tt>. Else, will return
|
184
|
+
# a translation of "no".
|
185
|
+
def convert_to_bool(base)
|
186
|
+
return I18n.translate(:yes) if base.original_value
|
187
|
+
I18n.translate(:no)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Passes the value through <tt>number_to_currency</tt>.
|
191
|
+
def convert_to_money(base)
|
192
|
+
base.template.number_to_currency(base.original_value)
|
193
|
+
end
|
194
|
+
|
195
|
+
# Passes the value through <tt>mail_to</tt>.
|
196
|
+
def convert_to_email(base)
|
197
|
+
base.template.mail_to(base.original_value)
|
198
|
+
end
|
199
|
+
|
200
|
+
# This is a complex one. Please see FieldHelpers::Base for information about how this works. It is written
|
201
|
+
# in the class documentation.
|
202
|
+
#
|
203
|
+
# In summary: Passes the value through <tt>link_to</tt> if the value is a model instance, else passes the
|
204
|
+
# <tt>record</tt> through <tt>link_to</tt> with the value of the field as the text for the link. Accepts
|
205
|
+
# a few options, too.
|
206
|
+
def convert_to_link(base)
|
207
|
+
if base.original_value.kind_of? ActiveRecord::Base
|
208
|
+
target = base.original_value # Not a self-link
|
209
|
+
else
|
210
|
+
target = base.record # Self-link
|
211
|
+
base.options[:link_field] = base.field
|
212
|
+
end
|
213
|
+
|
214
|
+
text = get_link_text(target, base)
|
215
|
+
path = get_link_path(target, base)
|
216
|
+
|
217
|
+
base.template.link_to(text, path, base.options[:link_options])
|
218
|
+
end
|
219
|
+
|
220
|
+
# Handles the link text logic for <tt>convert_to_link</tt>. This is an internal method but public
|
221
|
+
# in case you want to use it for your own helpers.
|
222
|
+
#
|
223
|
+
# It takes the target record and then the base in which the options are stored.
|
224
|
+
def get_link_text(target, base)
|
225
|
+
options = base.options
|
226
|
+
if options[:link_text]
|
227
|
+
return options[:link_text]
|
228
|
+
elsif options[:link_field]
|
229
|
+
return target.send(options[:link_field])
|
230
|
+
end
|
231
|
+
|
232
|
+
%w{name title label}.each do |field|
|
233
|
+
return target.send(field.to_sym) if target.respond_to?(field.to_sym)
|
234
|
+
end
|
235
|
+
|
236
|
+
target.to_s
|
237
|
+
end
|
238
|
+
|
239
|
+
# Handles the link path logic for <tt>convert_to_link</tt>. This is an internal method but public
|
240
|
+
# in case you want to use it for yout own helpers.
|
241
|
+
#
|
242
|
+
# It takes the target record and then the base in which the options are stored.
|
243
|
+
def get_link_path(target, base)
|
244
|
+
path = base.options[:link_path]
|
245
|
+
if path.kind_of? Proc
|
246
|
+
path = path.call(target)
|
247
|
+
elsif path.nil?
|
248
|
+
path = target
|
249
|
+
end
|
250
|
+
path
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|