custom-attributes 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +86 -0
- data/VERSION +1 -1
- data/lib/formtastic/custom_attributes.rb +173 -0
- metadata +5 -4
data/README.markdown
CHANGED
@@ -7,3 +7,89 @@ or weight and size measurements to products.
|
|
7
7
|
Most of these fields can be used purely dynamic and objects could have multiples of them (think telephone numbers, or email
|
8
8
|
addresses)
|
9
9
|
|
10
|
+
Contents of the package
|
11
|
+
=======================
|
12
|
+
|
13
|
+
* Extension for ActiveRecord
|
14
|
+
* Extension for Formtastic (including jQuery widget)
|
15
|
+
* Extension for Cucumber
|
16
|
+
|
17
|
+
Usage
|
18
|
+
=====
|
19
|
+
ActiveRecord will be extended automatically
|
20
|
+
|
21
|
+
Formtastic needs to be extended manually, like:
|
22
|
+
|
23
|
+
Formtastic::SemanticFormBuilder.send(:include, Formtastic::CustomAttributes)
|
24
|
+
|
25
|
+
Or when using a custom Form builder, just
|
26
|
+
|
27
|
+
include ::Formtastic::CustomAttributes
|
28
|
+
|
29
|
+
in your custom form builder
|
30
|
+
|
31
|
+
In the public folder are CSS and jQuery files for building a user interface
|
32
|
+
|
33
|
+
Example
|
34
|
+
=======
|
35
|
+
|
36
|
+
# model
|
37
|
+
class Location < ActiveRecord::Base
|
38
|
+
|
39
|
+
has_custom_attributes :url => :string, :telephone => :string, :email => :string, :custom => :string do |fields|
|
40
|
+
fields.telephone :common, :help_desk, :sales, :fax
|
41
|
+
fields.email :common, :sales, :help_desk
|
42
|
+
fields.url :website
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
# view (haml)
|
48
|
+
|
49
|
+
= semantic_form_for resource do |form|
|
50
|
+
= form.inputs "General", :name
|
51
|
+
= form.custom_attribute_inputs
|
52
|
+
= form.buttons
|
53
|
+
|
54
|
+
I18n
|
55
|
+
====
|
56
|
+
|
57
|
+
nl:
|
58
|
+
activerecord:
|
59
|
+
custom_attributes:
|
60
|
+
location:
|
61
|
+
attribute_names:
|
62
|
+
telephone:
|
63
|
+
one: "telefoonnummer"
|
64
|
+
other: "telefoonnummers"
|
65
|
+
url:
|
66
|
+
one: "website"
|
67
|
+
other: "websites"
|
68
|
+
email:
|
69
|
+
one: "e-mail adres"
|
70
|
+
other: "e-mail adressen"
|
71
|
+
custom:
|
72
|
+
one: "ander attribuut"
|
73
|
+
other: "andere attributen"
|
74
|
+
|
75
|
+
telephone:
|
76
|
+
common: "Algemeen"
|
77
|
+
help_desk: "Helpdesk"
|
78
|
+
sales: "Verkoop afdeling"
|
79
|
+
fax: "Fax"
|
80
|
+
|
81
|
+
email:
|
82
|
+
common: "Algemeen"
|
83
|
+
help_desk: "Helpdesk"
|
84
|
+
sales: "Verkoop afdeling"
|
85
|
+
|
86
|
+
formtastic:
|
87
|
+
actions:
|
88
|
+
add_custom_attribute: "Attribuut toevoegen"
|
89
|
+
create_custom_attribute: "%{attribute} toevoegen"
|
90
|
+
destroy_custom_attribute: "%{attribute} verwijderen"
|
91
|
+
|
92
|
+
hints:
|
93
|
+
location:
|
94
|
+
telephone: "+31 (0) 12 3456 789"
|
95
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Formtastic
|
2
|
+
module CustomAttributes
|
3
|
+
|
4
|
+
def custom_attribute_inputs(include_associations = {})
|
5
|
+
@supported_attribute_types ||= {}
|
6
|
+
@supported_attribute_templates ||= []
|
7
|
+
|
8
|
+
has_custom = false
|
9
|
+
if @object.respond_to? :custom_attributes
|
10
|
+
@object.custom_attributes.defined_attribute_types.each do |attribute_type|
|
11
|
+
if attribute_type == :custom_attributes
|
12
|
+
has_custom = true
|
13
|
+
else
|
14
|
+
add_custom_attribute_template_for attribute_type
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add other custom fields like addresses
|
20
|
+
include_associations.each do |association, association_options|
|
21
|
+
add_custom_association_attribute_template_for association, association_options
|
22
|
+
end
|
23
|
+
|
24
|
+
add_custom_attribute_template_for :custom if @object.respond_to? :custom_attributes and has_custom
|
25
|
+
|
26
|
+
content_tag(:div, Formtastic::Util.html_safe(
|
27
|
+
@supported_attribute_templates.join +
|
28
|
+
add_custom_attribute_input
|
29
|
+
|
30
|
+
), :class => "custom-attributes")
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def add_custom_attribute_template_for(attribute_type)
|
36
|
+
storage_type = @object.custom_attributes.supported_attribute_types[attribute_type]
|
37
|
+
i18n_scope = [:activerecord, :custom_attributes, @object.class.model_name.underscore.to_sym]
|
38
|
+
|
39
|
+
value_fields = @object.custom_attributes.attributes_of_type(attribute_type).collect do |attribute|
|
40
|
+
custom_field_input(attribute_type, [attribute_type, storage_type], attribute.label, attribute.value)
|
41
|
+
end
|
42
|
+
field_template = custom_field_input(attribute_type, [attribute_type, storage_type], "", nil, :template => true)
|
43
|
+
|
44
|
+
attribute_human_name = ::I18n.t(attribute_type,
|
45
|
+
:count => 1,
|
46
|
+
:scope => i18n_scope + [:attribute_names]).capitalize
|
47
|
+
|
48
|
+
value_fields << content_tag(:li,
|
49
|
+
template.link_to(Formtastic::Util.html_safe(attribute_human_name),
|
50
|
+
"#add-#{attribute_type}",
|
51
|
+
:class => "add-link",
|
52
|
+
:title => ::I18n.t(:add, :scope => :default_actions, :model => attribute_human_name),
|
53
|
+
:'data-attribute-type' => attribute_type
|
54
|
+
) << field_template << label_data_list_for(attribute_type, @object.custom_attributes.defined_labels_for(attribute_type)),
|
55
|
+
:class => "field-addition"
|
56
|
+
)
|
57
|
+
|
58
|
+
@supported_attribute_types[attribute_type] = attribute_human_name
|
59
|
+
@supported_attribute_templates << content_tag(
|
60
|
+
:fieldset, content_tag(
|
61
|
+
:legend, self.label(:custom_attributes, :label => ::I18n.t(attribute_type, :count => 2,
|
62
|
+
:scope => i18n_scope + [:attribute_names]).capitalize), :class => 'label'
|
63
|
+
) << content_tag(:ol, Formtastic::Util.html_safe(value_fields.join)),
|
64
|
+
:'data-attribute-type' => attribute_type
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_custom_association_attribute_template_for(association_name, options)
|
69
|
+
association = @object.class.reflect_on_association(association_name)
|
70
|
+
storage_type = association.klass.model_name.underscore.to_sym
|
71
|
+
|
72
|
+
value_fields = @object.send(association_name).collect do |item|
|
73
|
+
custom_field_input(storage_type, [storage_type], item.name, item)
|
74
|
+
end
|
75
|
+
field_template = custom_field_input(storage_type, [storage_type], "", nil, :template => true)
|
76
|
+
|
77
|
+
attribute_human_name = association.klass.model_name.human
|
78
|
+
value_fields << content_tag(:li,
|
79
|
+
template.link_to(Formtastic::Util.html_safe(attribute_human_name),
|
80
|
+
"#add-#{storage_type}",
|
81
|
+
:class => "add-link",
|
82
|
+
:title => ::I18n.t(:create_custom_attribute, :scope => [:formtastic, :actions], :attribute => attribute_human_name),
|
83
|
+
:'data-attribute-type' => storage_type
|
84
|
+
) << field_template << label_data_list_for(storage_type, options[:labels]),
|
85
|
+
:class => "field-addition"
|
86
|
+
)
|
87
|
+
|
88
|
+
@supported_attribute_types[storage_type] = attribute_human_name
|
89
|
+
@supported_attribute_templates << content_tag(
|
90
|
+
:fieldset, content_tag(
|
91
|
+
:legend, self.label(:custom_attributes, :label => association.klass.model_name.human(:count => 2)), :class => 'label'
|
92
|
+
) << content_tag(:ol, Formtastic::Util.html_safe(value_fields.join)),
|
93
|
+
:'data-attribute-type' => storage_type
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
def label_data_list_for(attribute_type, labels)
|
98
|
+
options = labels.collect do |label|
|
99
|
+
content_tag(:option, "", :value => label)
|
100
|
+
end
|
101
|
+
|
102
|
+
content_tag(:datalist,
|
103
|
+
Formtastic::Util.html_safe(
|
104
|
+
"<!--[if !IE]><!--><select><!--<![endif]-->" +
|
105
|
+
options.join +
|
106
|
+
"<!--[if !IE]><!--></select><!--<![endif]-->"),
|
107
|
+
:id => "#{attribute_type}-label-suggestions"
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_custom_attribute_input
|
112
|
+
label_name = ::I18n.t(:add_custom_attribute, :scope => [:formtastic, :actions])
|
113
|
+
field_set_and_list_wrapping_for_method(
|
114
|
+
:custom_attributes,
|
115
|
+
{:label => false},
|
116
|
+
content_tag(:li,
|
117
|
+
template.label_tag("add_custom_attribute_type", label_name) <<
|
118
|
+
template.select_tag("add_custom_attribute_type", template.options_for_select(
|
119
|
+
[[label_name, "_choose"]] + @supported_attribute_types.collect { |key, value| [value, key] }
|
120
|
+
)), :class => "add-custom-attribute")
|
121
|
+
)
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
def field_name_for(attribute_type, field_type)
|
126
|
+
"#{@object.class.model_name.underscore}[custom_attributes][#{attribute_type}][#{field_type}][]"
|
127
|
+
end
|
128
|
+
|
129
|
+
def custom_field_input(attribute_type, field_method_priority, label, value, options = {})
|
130
|
+
label_name = field_name_for attribute_type, "label"
|
131
|
+
label_field = template.text_field_tag(label_name, label, :list => "#{attribute_type}-label-suggestions", :autocomplete => "off")
|
132
|
+
|
133
|
+
input_field_method = field_method_priority.collect { |m| "custom_#{m}_input".to_sym }.find { |m| self.respond_to? m, true }
|
134
|
+
input_field = send(input_field_method, attribute_type, value, options)
|
135
|
+
|
136
|
+
content_tag(options[:template] ? :div : :li,
|
137
|
+
Formtastic::Util.html_safe(content_tag(:div, label_field, :class => "label") <<
|
138
|
+
input_field) << inline_hints_for(field_method_priority.first, options),
|
139
|
+
:class => options[:template] ? "template" : "value optional #{attribute_type}"
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
def custom_attribute_delete_link(attribute_human_name)
|
144
|
+
label = ::I18n.t(:destroy_custom_attribute, :scope => [:formtastic, :actions], :attribute => attribute_human_name)
|
145
|
+
escape_html_entities(" ") + template.link_to(escape_html_entities(label), "#remove", :class => "delete-link")
|
146
|
+
end
|
147
|
+
|
148
|
+
## Field addition support
|
149
|
+
|
150
|
+
def custom_string_input(attribute_type, value, options = {})
|
151
|
+
default_custom_field_handler(:text_field_tag, attribute_type, value)
|
152
|
+
end
|
153
|
+
|
154
|
+
def custom_email_input(attribute_type, value, options = {})
|
155
|
+
default_custom_field_handler(:email_field_tag, attribute_type, value)
|
156
|
+
end
|
157
|
+
|
158
|
+
def custom_url_input(attribute_type, value, options = {})
|
159
|
+
default_custom_field_handler(:url_field_tag, attribute_type, value)
|
160
|
+
end
|
161
|
+
|
162
|
+
def default_custom_field_handler(method, attribute_type, value)
|
163
|
+
i18n_scope = [:activerecord, :custom_attributes, @object.class.model_name.underscore.to_sym]
|
164
|
+
attribute_human_name = ::I18n.t(attribute_type, :count => 1, :scope => i18n_scope + [:attribute_names]).capitalize
|
165
|
+
template.send(method, field_name_for(attribute_type, "value"), value) <<
|
166
|
+
custom_attribute_delete_link(attribute_human_name)
|
167
|
+
end
|
168
|
+
|
169
|
+
delegate :content_tag, :to => :template
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: custom-attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matthijs Groen
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-12 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- lib/active_record/custom_attributes/custom_attribute_list.rb
|
42
42
|
- lib/active_record/custom_attributes/custom_attribute_model.rb
|
43
43
|
- lib/custom-attributes.rb
|
44
|
+
- lib/formtastic/custom_attributes.rb
|
44
45
|
- rails/init.rb
|
45
46
|
- spec/custom_attributes/has_custom_attributes_spec.rb
|
46
47
|
- spec/database.yml
|