dynamic_fieldsets 0.0.3 → 0.0.4
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/CHANGELOG +7 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +1 -0
- data/README.rdoc +15 -2
- data/Rakefile +24 -4
- data/VERSION +1 -1
- data/app/controllers/dynamic_fieldsets/fields_controller.rb +25 -0
- data/app/controllers/dynamic_fieldsets/fieldset_children_controller.rb +57 -0
- data/app/controllers/dynamic_fieldsets/fieldsets_controller.rb +91 -5
- data/app/helpers/dynamic_fieldsets/fields_helper.rb +1 -15
- data/app/helpers/dynamic_fieldsets/fieldset_children_helper.rb +5 -0
- data/app/helpers/dynamic_fieldsets/nested_model_helper.rb +18 -0
- data/app/helpers/dynamic_fieldsets_helper.rb +70 -44
- data/app/models/dynamic_fieldsets/dependency.rb +76 -0
- data/app/models/dynamic_fieldsets/dependency_clause.rb +32 -0
- data/app/models/dynamic_fieldsets/dependency_group.rb +108 -0
- data/app/models/dynamic_fieldsets/field.rb +17 -12
- data/app/models/dynamic_fieldsets/field_default.rb +27 -1
- data/app/models/dynamic_fieldsets/field_record.rb +19 -4
- data/app/models/dynamic_fieldsets/fieldset.rb +35 -30
- data/app/models/dynamic_fieldsets/fieldset_associator.rb +52 -8
- data/app/models/dynamic_fieldsets/fieldset_child.rb +148 -0
- data/app/views/dynamic_fieldsets/fields/_disable_field_form.html.erb +4 -0
- data/app/views/dynamic_fieldsets/fields/_field_default_fields.html.erb +1 -1
- data/app/views/dynamic_fieldsets/fields/_form.html.erb +9 -27
- data/app/views/dynamic_fieldsets/fields/index.html.erb +8 -5
- data/app/views/dynamic_fieldsets/fields/new.html.erb +5 -1
- data/app/views/dynamic_fieldsets/fields/show.html.erb +1 -13
- data/app/views/dynamic_fieldsets/fieldset_children/_dependency_clause_fields.html.erb +25 -0
- data/app/views/dynamic_fieldsets/fieldset_children/_dependency_fields.html.erb +12 -0
- data/app/views/dynamic_fieldsets/fieldset_children/_dependency_group_fields.html.erb +16 -0
- data/app/views/dynamic_fieldsets/fieldset_children/_form.html.erb +34 -0
- data/app/views/dynamic_fieldsets/fieldset_children/edit.html.erb +6 -0
- data/app/views/dynamic_fieldsets/fieldsets/_associate_child.html.erb +4 -0
- data/app/views/dynamic_fieldsets/fieldsets/_child.html.erb +41 -0
- data/app/views/dynamic_fieldsets/fieldsets/_form.html.erb +2 -8
- data/app/views/dynamic_fieldsets/fieldsets/children.html.erb +47 -39
- data/app/views/dynamic_fieldsets/fieldsets/index.html.erb +4 -4
- data/app/views/dynamic_fieldsets/fieldsets/new.html.erb +5 -1
- data/app/views/dynamic_fieldsets/fieldsets/reorder.html.erb +4 -0
- data/app/views/dynamic_fieldsets/fieldsets/show.html.erb +1 -12
- data/app/views/dynamic_fieldsets/shared/_javascript_watcher.html.erb +255 -0
- data/app/views/dynamic_fieldsets/shared/_nested_model_javascript.html.erb +35 -0
- data/config/.routes.rb.swp +0 -0
- data/config/routes.rb +11 -0
- data/dynamic_fieldsets.gemspec +41 -4
- data/lib/dynamic_fieldsets/dynamic_fieldsets_in_model.rb +141 -14
- data/lib/generators/dynamic_fieldsets/templates/migrations/install_migration.rb +39 -5
- data/spec/dummy/app/controllers/information_forms_controller.rb +2 -1
- data/spec/dummy/app/models/information_form.rb +1 -1
- data/spec/dummy/app/views/information_forms/dynamic_view.html.erb +18 -0
- data/spec/dummy/app/views/information_forms/show.html.erb +1 -0
- data/spec/dummy/app/views/layouts/application.html.erb +9 -1
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/db/migrate/{20110726215814_create_dynamic_fieldsets_tables.rb → 20110809161724_create_dynamic_fieldsets_tables.rb} +39 -5
- data/spec/dummy/db/schema.rb +40 -11
- data/spec/dummy/features/field.feature +17 -2
- data/spec/dummy/features/fieldset.feature +1 -21
- data/spec/dummy/features/fieldset_children.feature +50 -0
- data/spec/dummy/features/javascript_tests.feature +91 -0
- data/spec/dummy/features/step_definitions/field_steps.rb +9 -5
- data/spec/dummy/features/step_definitions/fieldset_associator_steps.rb +3 -1
- data/spec/dummy/features/step_definitions/fieldset_children_steps.rb +65 -0
- data/spec/dummy/features/step_definitions/fieldset_steps.rb +0 -27
- data/spec/dummy/features/step_definitions/javascript_steps.rb +208 -0
- data/spec/dummy/features/step_definitions/web_steps.rb +5 -0
- data/spec/dummy/features/support/paths.rb +10 -1
- data/spec/dummy/features/support/selectors.rb +2 -0
- data/spec/dummy/public/javascripts/jquery-1.6.2.min.js +18 -0
- data/spec/dummy/public/javascripts/jquery-ui-1.8.15.custom.min.js +111 -0
- data/spec/dummy/public/javascripts/jquery-ui-nestedSortable.js +356 -0
- data/spec/dummy/public/stylesheets/scaffold.css +101 -0
- data/spec/dynamic_fieldsets_helper_spec.rb +236 -55
- data/spec/dynamic_fieldsets_in_model_spec.rb +122 -4
- data/spec/models/dependency_clause_spec.rb +55 -0
- data/spec/models/dependency_group_spec.rb +237 -0
- data/spec/models/dependency_spec.rb +173 -0
- data/spec/models/field_default_spec.rb +49 -0
- data/spec/models/field_record_spec.rb +11 -2
- data/spec/models/field_spec.rb +30 -6
- data/spec/models/fieldset_associator_spec.rb +138 -25
- data/spec/models/fieldset_child_spec.rb +122 -0
- data/spec/models/fieldset_spec.rb +78 -80
- data/spec/support/dependency_group_helper.rb +9 -0
- data/spec/support/dependency_helper.rb +13 -0
- data/spec/support/field_helper.rb +0 -2
- data/spec/support/fieldset_child_helper.rb +10 -0
- data/spec/support/fieldset_helper.rb +2 -18
- metadata +51 -5
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
<script type='text/javascript'>
|
|
2
|
+
|
|
3
|
+
// The only inputs we care about are visible... not hidden
|
|
4
|
+
var allInputs = $(":input:not(:hidden)");
|
|
5
|
+
|
|
6
|
+
/***************************************************************************
|
|
7
|
+
|
|
8
|
+
field-[group_field]-child-[group_fsc] - just want the last value from the
|
|
9
|
+
input's id. This function rips it.
|
|
10
|
+
|
|
11
|
+
input - called upon the input that just called the change()
|
|
12
|
+
returns [integer] - the group_fsc id from the end of the id
|
|
13
|
+
|
|
14
|
+
***************************************************************************/
|
|
15
|
+
|
|
16
|
+
function grab_fsc_id(field, field_type) {
|
|
17
|
+
switch(field_type)
|
|
18
|
+
{
|
|
19
|
+
case 'text':
|
|
20
|
+
var id_array = field.attr('id').split('-');
|
|
21
|
+
return id_array[id_array.length-1];
|
|
22
|
+
case 'radio':
|
|
23
|
+
var id_array = field.closest("div").attr("id").split('-');
|
|
24
|
+
return id_array[id_array.length-1];
|
|
25
|
+
case 'textarea':
|
|
26
|
+
var id_array = field.attr('id').split('-');
|
|
27
|
+
return id_array[id_array.length-1];
|
|
28
|
+
case 'checkbox':
|
|
29
|
+
var id_array = field.closest("div").attr("id").split('-');
|
|
30
|
+
return id_array[id_array.length-1];
|
|
31
|
+
case 'select':
|
|
32
|
+
var id_array = field.attr('id').split('-');
|
|
33
|
+
return id_array[id_array.length-1];
|
|
34
|
+
case 'multi-select':
|
|
35
|
+
var id_array = field.attr('id').split('-');
|
|
36
|
+
return id_array[id_array.length-1];
|
|
37
|
+
default:
|
|
38
|
+
return ''
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/***************************************************************************
|
|
43
|
+
|
|
44
|
+
evaluate() does the logical computing between two values with a given
|
|
45
|
+
relationship.
|
|
46
|
+
|
|
47
|
+
params [entered_value] - The current value of the input that called the
|
|
48
|
+
change()
|
|
49
|
+
params [relationship] - The relationship of the dependency that the
|
|
50
|
+
input that called the change() is tied to
|
|
51
|
+
params [value] - The value that we are testing against for the dependency
|
|
52
|
+
that the input that called the change() is tied to
|
|
53
|
+
returns [bool] - The boolean value by comparing the entered_value against
|
|
54
|
+
the value using the relationship.
|
|
55
|
+
|
|
56
|
+
**************************************************************************/
|
|
57
|
+
|
|
58
|
+
function evaluate(entered_value, relationship, value) {
|
|
59
|
+
switch(relationship)
|
|
60
|
+
{
|
|
61
|
+
/* CHANGE THIS if the model changes on which relationships
|
|
62
|
+
are allowed. */
|
|
63
|
+
case 'equals':
|
|
64
|
+
return entered_value == value;
|
|
65
|
+
case 'not equals':
|
|
66
|
+
return entered_value != value;
|
|
67
|
+
case 'includes':
|
|
68
|
+
return jQuery.inArray(value, entered_value) != -1;
|
|
69
|
+
case 'not includes':
|
|
70
|
+
return jQuery.inArray(value, entered_value) == -1;
|
|
71
|
+
case 'blank':
|
|
72
|
+
return entered_value == "";
|
|
73
|
+
case 'not blank':
|
|
74
|
+
return entered_value != "";
|
|
75
|
+
default:
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/*************************************************************************
|
|
81
|
+
|
|
82
|
+
group_action() responds to the results of evaluate() to enact the
|
|
83
|
+
appropriate action upon the group_field of the dependency_group.
|
|
84
|
+
|
|
85
|
+
params [success_flag] - Either set to succeed or failure to indicate
|
|
86
|
+
the results of evaluate()
|
|
87
|
+
params [action] - Either set to show or enable.
|
|
88
|
+
params [group_field] - The field tied to the dependency_group that is
|
|
89
|
+
to experience the action based off of the success of evaluate()
|
|
90
|
+
returns - changes the group_field
|
|
91
|
+
|
|
92
|
+
*************************************************************************/
|
|
93
|
+
|
|
94
|
+
function group_action(success_flag, action, group_field) {
|
|
95
|
+
|
|
96
|
+
/* CHANGE THIS if the model change on which actions are allowed */
|
|
97
|
+
|
|
98
|
+
if (success_flag == true){
|
|
99
|
+
switch(action)
|
|
100
|
+
{
|
|
101
|
+
case 'show':
|
|
102
|
+
$('#input-' + group_field).show();
|
|
103
|
+
case 'enable':
|
|
104
|
+
$('#' + group_field + ' :input').removeAttr('disabled');
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
switch(action)
|
|
108
|
+
{
|
|
109
|
+
case 'show':
|
|
110
|
+
$('#input-' + group_field).hide();
|
|
111
|
+
case 'enable':
|
|
112
|
+
$('#' + group_field + ' :input').attr('disabled', true);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
function grab_value(field, field_type) {
|
|
118
|
+
switch(field_type)
|
|
119
|
+
{
|
|
120
|
+
case 'text':
|
|
121
|
+
return field.attr('value').toLowerCase();
|
|
122
|
+
case 'radio':
|
|
123
|
+
if (field.val() == $(':checked').val())
|
|
124
|
+
{
|
|
125
|
+
field_val = field.attr('id').split('-').slice(2);
|
|
126
|
+
return field_val.join(" ").toLowerCase();
|
|
127
|
+
}
|
|
128
|
+
case 'textarea':
|
|
129
|
+
return field.val();
|
|
130
|
+
case 'checkbox':
|
|
131
|
+
var value_ray = [];
|
|
132
|
+
var field_ray = [];
|
|
133
|
+
var sibling_ray = field.closest('div').children().children();
|
|
134
|
+
var checked_ray = $('input:checked');
|
|
135
|
+
value_ray = getIntersect(sibling_ray, checked_ray)
|
|
136
|
+
for (var element in value_ray) {
|
|
137
|
+
field_ray.push(value_ray[element].id.split('-').slice(2)[0]);
|
|
138
|
+
}
|
|
139
|
+
return field_ray;
|
|
140
|
+
case 'select':
|
|
141
|
+
return $('#' + field.attr('id') + ' option:selected').text().toLowerCase();
|
|
142
|
+
case 'multi-select':
|
|
143
|
+
var value_ray = $('#' + field.attr('id') + ' option:selected');
|
|
144
|
+
var field_ray = []
|
|
145
|
+
for (var element in value_ray)
|
|
146
|
+
{
|
|
147
|
+
var temp = value_ray[element].text;
|
|
148
|
+
if (typeof(temp) == "string") { field_ray.push(temp.toLowerCase()); }
|
|
149
|
+
}
|
|
150
|
+
return field_ray;
|
|
151
|
+
default:
|
|
152
|
+
return '';
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
function grab_type(field) {
|
|
157
|
+
if (field.attr('type') != undefined)
|
|
158
|
+
{
|
|
159
|
+
return field.attr('type')
|
|
160
|
+
}
|
|
161
|
+
else if ($('textarea#'+field.attr('id')).length > 0)
|
|
162
|
+
{
|
|
163
|
+
return "textarea";
|
|
164
|
+
}
|
|
165
|
+
else if ($('select#'+field.attr('id')).length > 0)
|
|
166
|
+
{
|
|
167
|
+
if (field.attr('multiple') == "multiple")
|
|
168
|
+
{
|
|
169
|
+
return "multi-select";
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
return "select";
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else
|
|
176
|
+
{
|
|
177
|
+
return "invalid";
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function getIntersect(arr1, arr2) {
|
|
182
|
+
var temp = [];
|
|
183
|
+
for(var i = 0; i < arr1.length; i++){
|
|
184
|
+
for(var k = 0; k < arr2.length; k++){
|
|
185
|
+
if(arr1[i] == arr2[k]){
|
|
186
|
+
temp.push( arr1[i]);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return temp;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/***********************************************************************
|
|
195
|
+
|
|
196
|
+
This watches for ANY change that may take place on the page. It then
|
|
197
|
+
pushes the object through grab_fsc_id to get an id we can check against
|
|
198
|
+
the json_holder. If it's in there, it then grabs all the related data,
|
|
199
|
+
checks the current value against the expected value through the
|
|
200
|
+
evaluate() function and then goes through the needed action AFTER
|
|
201
|
+
checking each dependency and dependency_clause.
|
|
202
|
+
|
|
203
|
+
***********************************************************************/
|
|
204
|
+
|
|
205
|
+
allInputs.change( function() {
|
|
206
|
+
var field = $(this);
|
|
207
|
+
var field_type = grab_type(field);
|
|
208
|
+
var fieldset_child_id = grab_fsc_id(field, field_type);
|
|
209
|
+
var entered_value = grab_value(field, field_type)
|
|
210
|
+
if (fieldset_child_id in json_holder) {
|
|
211
|
+
for (var group in json_holder[fieldset_child_id]) {
|
|
212
|
+
var action = json_holder[fieldset_child_id][group]['action'];
|
|
213
|
+
var group_fsc_id = json_holder[fieldset_child_id][group]['fieldset_child_id'];
|
|
214
|
+
var group_field_id = json_holder[fieldset_child_id][group]['field_id'];
|
|
215
|
+
var group_field = 'field-' + group_field_id + '-child-' + group_fsc_id;
|
|
216
|
+
|
|
217
|
+
// As each dependency clause is AND'd together, we'll assume it'll be
|
|
218
|
+
// true until short circuited into being false.`
|
|
219
|
+
var group_break_flag = true;
|
|
220
|
+
group:
|
|
221
|
+
for (var clause in json_holder[fieldset_child_id][group]["clause"]) {
|
|
222
|
+
// As each clause ORs dependencies together, we'll assume it'll be
|
|
223
|
+
// false until short circuited into being true.
|
|
224
|
+
var clause_break_flag = false;
|
|
225
|
+
clause:
|
|
226
|
+
for (var dependency in json_holder[fieldset_child_id][group]["clause"][clause])
|
|
227
|
+
{
|
|
228
|
+
var relationship = json_holder[fieldset_child_id][group]["clause"][clause][dependency]['relationship'];
|
|
229
|
+
var value = json_holder[fieldset_child_id][group]["clause"][clause][dependency]['value'].toLowerCase();
|
|
230
|
+
// Short circuit from looking at each dependency in the case
|
|
231
|
+
// we determine a true dependency (OR)
|
|
232
|
+
if (evaluate(entered_value, relationship, value)) {
|
|
233
|
+
clause_break_flag = true;
|
|
234
|
+
break clause;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Short circuit from looking at each clause in the case we determine
|
|
239
|
+
// a false dependency (AND)
|
|
240
|
+
if (clause_break_flag == false) {
|
|
241
|
+
group_break_flag = false;
|
|
242
|
+
break group;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// If successful, group_break_flag will pass true into group_action
|
|
246
|
+
group_action(group_break_flag, action, group_field);
|
|
247
|
+
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
})
|
|
253
|
+
.change();
|
|
254
|
+
|
|
255
|
+
</script>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
<%# Sorry for these duplicated functions %>
|
|
3
|
+
function remove_fields(link) {
|
|
4
|
+
$(link).prev("input[type=hidden]").val("1");
|
|
5
|
+
$(link).closest(".fields").hide();
|
|
6
|
+
$(link).parent().hide();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function remove_fields_and_parent_fields(link) {
|
|
10
|
+
$(link).prev("input[type=hidden]").val("1");
|
|
11
|
+
$(link).closest(".fields").hide();
|
|
12
|
+
$(link).parent().parent().hide();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function remove_fields_from_table(link) {
|
|
16
|
+
$(link).prev("input[type=hidden]").val("1");
|
|
17
|
+
$(link).closest(".fields").hide();
|
|
18
|
+
$(link).parent().parent().hide();
|
|
19
|
+
//also remove the next row
|
|
20
|
+
$(link).parent().parent().next().hide();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function add_fields(link, association, content) {
|
|
24
|
+
var new_id = new Date().getTime();
|
|
25
|
+
var regexp = new RegExp("new_" + association, "g");
|
|
26
|
+
$(link).parent().before(content.replace(regexp, new_id));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function add_fields_to_table(link, association, content) {
|
|
30
|
+
var new_id = new Date().getTime();
|
|
31
|
+
var regexp = new RegExp("new_" + association, "g");
|
|
32
|
+
$(link).parent().parent().before(content.replace(regexp, new_id));
|
|
33
|
+
}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
Binary file
|
data/config/routes.rb
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
Rails.application.routes.draw do
|
|
2
2
|
namespace :dynamic_fieldsets do
|
|
3
3
|
resources :fieldset_associators
|
|
4
|
+
|
|
4
5
|
resources :fieldsets
|
|
6
|
+
match "/fieldsets/roots" => "fieldsets#roots"
|
|
5
7
|
match "/fieldsets/:id/children" => "fieldsets#children", :as => :children_dynamic_fieldsets_fieldset
|
|
8
|
+
match "/fieldsets/:id/children/reorder" => "fieldsets#reorder"
|
|
9
|
+
match "/fieldsets/new(/:parent)" => "fieldsets#new", :as => :new_dynamic_fieldsets_fieldset
|
|
10
|
+
match "fieldsets/:id/associate_child" => "fieldsets#associate_child", :as => :associate_child_to_fieldset
|
|
11
|
+
|
|
6
12
|
resources :fields
|
|
13
|
+
match "/fields/new(/:parent)" => "fields#new", :as => :new_dynamic_fieldsets_field
|
|
14
|
+
match "/fields/:id/enable" => "fields#enable", :as => "enable_field", :method => :post
|
|
15
|
+
|
|
16
|
+
resources :fieldset_children
|
|
17
|
+
match "/fieldset_children/:id/remove" => "fieldset_children#remove", :as => :remove_fieldset_child, :method => :post
|
|
7
18
|
end
|
|
8
19
|
|
|
9
20
|
end
|
data/dynamic_fieldsets.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{dynamic_fieldsets}
|
|
8
|
-
s.version = "0.0.
|
|
8
|
+
s.version = "0.0.4"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
|
-
s.authors = [%q{Jeremiah Hemphill}, %q{Ethan Pemble}]
|
|
12
|
-
s.date = %q{2011-
|
|
11
|
+
s.authors = [%q{Jeremiah Hemphill}, %q{Ethan Pemble}, %q{John Carter}]
|
|
12
|
+
s.date = %q{2011-08-25}
|
|
13
13
|
s.description = %q{Dynamic fieldsets for rails controllers}
|
|
14
14
|
s.email = %q{jeremiah@cloudspace.com}
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -25,9 +25,15 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
"VERSION",
|
|
26
26
|
"app/controllers/dynamic_fieldsets/fields_controller.rb",
|
|
27
27
|
"app/controllers/dynamic_fieldsets/fieldset_associators_controller.rb",
|
|
28
|
+
"app/controllers/dynamic_fieldsets/fieldset_children_controller.rb",
|
|
28
29
|
"app/controllers/dynamic_fieldsets/fieldsets_controller.rb",
|
|
29
30
|
"app/helpers/dynamic_fieldsets/fields_helper.rb",
|
|
31
|
+
"app/helpers/dynamic_fieldsets/fieldset_children_helper.rb",
|
|
32
|
+
"app/helpers/dynamic_fieldsets/nested_model_helper.rb",
|
|
30
33
|
"app/helpers/dynamic_fieldsets_helper.rb",
|
|
34
|
+
"app/models/dynamic_fieldsets/dependency.rb",
|
|
35
|
+
"app/models/dynamic_fieldsets/dependency_clause.rb",
|
|
36
|
+
"app/models/dynamic_fieldsets/dependency_group.rb",
|
|
31
37
|
"app/models/dynamic_fieldsets/field.rb",
|
|
32
38
|
"app/models/dynamic_fieldsets/field_default.rb",
|
|
33
39
|
"app/models/dynamic_fieldsets/field_html_attribute.rb",
|
|
@@ -35,6 +41,8 @@ Gem::Specification.new do |s|
|
|
|
35
41
|
"app/models/dynamic_fieldsets/field_record.rb",
|
|
36
42
|
"app/models/dynamic_fieldsets/fieldset.rb",
|
|
37
43
|
"app/models/dynamic_fieldsets/fieldset_associator.rb",
|
|
44
|
+
"app/models/dynamic_fieldsets/fieldset_child.rb",
|
|
45
|
+
"app/views/dynamic_fieldsets/fields/_disable_field_form.html.erb",
|
|
38
46
|
"app/views/dynamic_fieldsets/fields/_field_default_fields.html.erb",
|
|
39
47
|
"app/views/dynamic_fieldsets/fields/_field_html_attribute_fields.html.erb",
|
|
40
48
|
"app/views/dynamic_fieldsets/fields/_field_option_fields.html.erb",
|
|
@@ -45,12 +53,23 @@ Gem::Specification.new do |s|
|
|
|
45
53
|
"app/views/dynamic_fieldsets/fields/show.html.erb",
|
|
46
54
|
"app/views/dynamic_fieldsets/fieldset_associators/index.html.erb",
|
|
47
55
|
"app/views/dynamic_fieldsets/fieldset_associators/show.html.erb",
|
|
56
|
+
"app/views/dynamic_fieldsets/fieldset_children/_dependency_clause_fields.html.erb",
|
|
57
|
+
"app/views/dynamic_fieldsets/fieldset_children/_dependency_fields.html.erb",
|
|
58
|
+
"app/views/dynamic_fieldsets/fieldset_children/_dependency_group_fields.html.erb",
|
|
59
|
+
"app/views/dynamic_fieldsets/fieldset_children/_form.html.erb",
|
|
60
|
+
"app/views/dynamic_fieldsets/fieldset_children/edit.html.erb",
|
|
61
|
+
"app/views/dynamic_fieldsets/fieldsets/_associate_child.html.erb",
|
|
62
|
+
"app/views/dynamic_fieldsets/fieldsets/_child.html.erb",
|
|
48
63
|
"app/views/dynamic_fieldsets/fieldsets/_form.html.erb",
|
|
49
64
|
"app/views/dynamic_fieldsets/fieldsets/children.html.erb",
|
|
50
65
|
"app/views/dynamic_fieldsets/fieldsets/edit.html.erb",
|
|
51
66
|
"app/views/dynamic_fieldsets/fieldsets/index.html.erb",
|
|
52
67
|
"app/views/dynamic_fieldsets/fieldsets/new.html.erb",
|
|
68
|
+
"app/views/dynamic_fieldsets/fieldsets/reorder.html.erb",
|
|
53
69
|
"app/views/dynamic_fieldsets/fieldsets/show.html.erb",
|
|
70
|
+
"app/views/dynamic_fieldsets/shared/_javascript_watcher.html.erb",
|
|
71
|
+
"app/views/dynamic_fieldsets/shared/_nested_model_javascript.html.erb",
|
|
72
|
+
"config/.routes.rb.swp",
|
|
54
73
|
"config/routes.rb",
|
|
55
74
|
"dynamic_fieldsets.gemspec",
|
|
56
75
|
"lib/dynamic_fieldsets.rb",
|
|
@@ -68,6 +87,7 @@ Gem::Specification.new do |s|
|
|
|
68
87
|
"spec/dummy/app/helpers/information_forms_helper.rb",
|
|
69
88
|
"spec/dummy/app/models/information_form.rb",
|
|
70
89
|
"spec/dummy/app/views/information_forms/_form.html.erb",
|
|
90
|
+
"spec/dummy/app/views/information_forms/dynamic_view.html.erb",
|
|
71
91
|
"spec/dummy/app/views/information_forms/edit.html.erb",
|
|
72
92
|
"spec/dummy/app/views/information_forms/index.html.erb",
|
|
73
93
|
"spec/dummy/app/views/information_forms/new.html.erb",
|
|
@@ -88,16 +108,20 @@ Gem::Specification.new do |s|
|
|
|
88
108
|
"spec/dummy/config/initializers/session_store.rb",
|
|
89
109
|
"spec/dummy/config/locales/en.yml",
|
|
90
110
|
"spec/dummy/config/routes.rb",
|
|
91
|
-
"spec/dummy/db/migrate/20110726215814_create_dynamic_fieldsets_tables.rb",
|
|
92
111
|
"spec/dummy/db/migrate/20110727210451_create_information_forms.rb",
|
|
112
|
+
"spec/dummy/db/migrate/20110809161724_create_dynamic_fieldsets_tables.rb",
|
|
93
113
|
"spec/dummy/db/schema.rb",
|
|
94
114
|
"spec/dummy/features/field.feature",
|
|
95
115
|
"spec/dummy/features/fieldset.feature",
|
|
96
116
|
"spec/dummy/features/fieldset_associator.feature",
|
|
117
|
+
"spec/dummy/features/fieldset_children.feature",
|
|
118
|
+
"spec/dummy/features/javascript_tests.feature",
|
|
97
119
|
"spec/dummy/features/step_definitions/debugging_steps.rb",
|
|
98
120
|
"spec/dummy/features/step_definitions/field_steps.rb",
|
|
99
121
|
"spec/dummy/features/step_definitions/fieldset_associator_steps.rb",
|
|
122
|
+
"spec/dummy/features/step_definitions/fieldset_children_steps.rb",
|
|
100
123
|
"spec/dummy/features/step_definitions/fieldset_steps.rb",
|
|
124
|
+
"spec/dummy/features/step_definitions/javascript_steps.rb",
|
|
101
125
|
"spec/dummy/features/step_definitions/web_steps.rb",
|
|
102
126
|
"spec/dummy/features/support/env.rb",
|
|
103
127
|
"spec/dummy/features/support/paths.rb",
|
|
@@ -107,6 +131,9 @@ Gem::Specification.new do |s|
|
|
|
107
131
|
"spec/dummy/public/500.html",
|
|
108
132
|
"spec/dummy/public/favicon.ico",
|
|
109
133
|
"spec/dummy/public/javascripts/application.js",
|
|
134
|
+
"spec/dummy/public/javascripts/jquery-1.6.2.min.js",
|
|
135
|
+
"spec/dummy/public/javascripts/jquery-ui-1.8.15.custom.min.js",
|
|
136
|
+
"spec/dummy/public/javascripts/jquery-ui-nestedSortable.js",
|
|
110
137
|
"spec/dummy/public/javascripts/jquery.min.js",
|
|
111
138
|
"spec/dummy/public/stylesheets/.gitkeep",
|
|
112
139
|
"spec/dummy/public/stylesheets/scaffold.css",
|
|
@@ -115,24 +142,31 @@ Gem::Specification.new do |s|
|
|
|
115
142
|
"spec/dynamic_fieldsets_in_model_spec.rb",
|
|
116
143
|
"spec/dynamic_fieldsets_spec.rb",
|
|
117
144
|
"spec/integration/navigation_spec.rb",
|
|
145
|
+
"spec/models/dependency_clause_spec.rb",
|
|
146
|
+
"spec/models/dependency_group_spec.rb",
|
|
147
|
+
"spec/models/dependency_spec.rb",
|
|
118
148
|
"spec/models/field_default_spec.rb",
|
|
119
149
|
"spec/models/field_html_attribute_spec.rb",
|
|
120
150
|
"spec/models/field_option_spec.rb",
|
|
121
151
|
"spec/models/field_record_spec.rb",
|
|
122
152
|
"spec/models/field_spec.rb",
|
|
123
153
|
"spec/models/fieldset_associator_spec.rb",
|
|
154
|
+
"spec/models/fieldset_child_spec.rb",
|
|
124
155
|
"spec/models/fieldset_spec.rb",
|
|
125
156
|
"spec/reports/SPEC-ActsAsMultipartForm.xml",
|
|
126
157
|
"spec/reports/SPEC-MultipartForm-InProgressForm-validations.xml",
|
|
127
158
|
"spec/reports/SPEC-MultipartForm-InProgressForm.xml",
|
|
128
159
|
"spec/reports/SPEC-Navigation.xml",
|
|
129
160
|
"spec/spec_helper.rb",
|
|
161
|
+
"spec/support/dependency_group_helper.rb",
|
|
162
|
+
"spec/support/dependency_helper.rb",
|
|
130
163
|
"spec/support/field_default_helper.rb",
|
|
131
164
|
"spec/support/field_helper.rb",
|
|
132
165
|
"spec/support/field_html_attribute_helper.rb",
|
|
133
166
|
"spec/support/field_option_helper.rb",
|
|
134
167
|
"spec/support/field_record_helper.rb",
|
|
135
168
|
"spec/support/fieldset_associator_helper.rb",
|
|
169
|
+
"spec/support/fieldset_child_helper.rb",
|
|
136
170
|
"spec/support/fieldset_helper.rb"
|
|
137
171
|
]
|
|
138
172
|
s.homepage = %q{http://github.com/jeremiahishere/dynamic_fieldsets}
|
|
@@ -158,6 +192,7 @@ Gem::Specification.new do |s|
|
|
|
158
192
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
|
159
193
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
|
|
160
194
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
|
195
|
+
s.add_development_dependency(%q<json>, [">= 0"])
|
|
161
196
|
s.add_development_dependency(%q<ci_reporter>, [">= 0"])
|
|
162
197
|
else
|
|
163
198
|
s.add_dependency(%q<rails>, ["= 3.0.7"])
|
|
@@ -173,6 +208,7 @@ Gem::Specification.new do |s|
|
|
|
173
208
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
|
174
209
|
s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
|
|
175
210
|
s.add_dependency(%q<rcov>, [">= 0"])
|
|
211
|
+
s.add_dependency(%q<json>, [">= 0"])
|
|
176
212
|
s.add_dependency(%q<ci_reporter>, [">= 0"])
|
|
177
213
|
end
|
|
178
214
|
else
|
|
@@ -189,6 +225,7 @@ Gem::Specification.new do |s|
|
|
|
189
225
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
|
190
226
|
s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
|
|
191
227
|
s.add_dependency(%q<rcov>, [">= 0"])
|
|
228
|
+
s.add_dependency(%q<json>, [">= 0"])
|
|
192
229
|
s.add_dependency(%q<ci_reporter>, [">= 0"])
|
|
193
230
|
end
|
|
194
231
|
end
|
|
@@ -39,27 +39,154 @@ module DynamicFieldsets
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
module InstanceMethods
|
|
42
|
+
|
|
43
|
+
# Overrides the ActiveModel Validations run_validations! method
|
|
44
|
+
# It additionally adds validations for the fields that are required
|
|
45
|
+
#
|
|
46
|
+
# I am not sure if this is the correct place to put this. Seems like a reasonable one.
|
|
47
|
+
#
|
|
48
|
+
# @return [Boolean] The result of run_validations! with the extra errors added, should be true if errors.empty?
|
|
49
|
+
def run_validations!
|
|
50
|
+
run_dynamic_fieldset_validations!
|
|
51
|
+
super
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Iterates over the fieldset associator's children and adds errors
|
|
55
|
+
def run_dynamic_fieldset_validations!
|
|
56
|
+
# for each fsa
|
|
57
|
+
self.dynamic_fieldsets.keys.each do |key|
|
|
58
|
+
fsa = self.fieldset_associator(key)
|
|
59
|
+
run_fieldset_child_validations!(fsa.id, fsa.fieldset)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Checks if a fieldset child is required and adds an error if it's value is blank
|
|
64
|
+
# Adds errors to the sel.errors array, does not return them
|
|
65
|
+
#
|
|
66
|
+
# @param [Integer] fsa_id The id for the fieldset associator the child belongs to
|
|
67
|
+
# @param [Field or Fieldset] child The child of the fieldset associator
|
|
68
|
+
def run_fieldset_child_validations!(fsa_id, child)
|
|
69
|
+
if child.is_a?(DynamicFieldsets::Fieldset)
|
|
70
|
+
# if a fieldset, then recurse
|
|
71
|
+
child.children.each do |grand_child|
|
|
72
|
+
run_fieldset_child_validations!(fsa_id, grand_child)
|
|
73
|
+
end
|
|
74
|
+
elsif child.is_a?(DynamicFieldsets::Field)
|
|
75
|
+
# if a child, check if the params value is set, check if it is required, check if it satisfies condition
|
|
76
|
+
fsa_tag_id = "fsa-" + fsa_id.to_s
|
|
77
|
+
field_tag_id = "field-" + child.id.to_s
|
|
78
|
+
if !self.dynamic_fieldset_values.has_key?(fsa_tag_id) || !self.dynamic_fieldset_values[fsa_tag_id].has_key?(field_tag_id)
|
|
79
|
+
self.errors.add(:base, child.label + " is required and the input is missing")
|
|
80
|
+
else
|
|
81
|
+
# get the value
|
|
82
|
+
value = self.dynamic_fieldset_values[fsa_tag_id][field_tag_id]
|
|
83
|
+
if child.required?
|
|
84
|
+
# empty works on array or string, so simplifying here
|
|
85
|
+
self.errors.add(:base, child.label + " is required") if value.nil? || value.empty?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
else
|
|
89
|
+
# found a major problem, not sure how to get here
|
|
90
|
+
puts "found a child that wasn't a field or fieldset" + child.inspect
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Stores the dynamic fieldset values
|
|
95
|
+
def set_fieldset_values( params )
|
|
96
|
+
values = params.select{ |key| key.match(/^fsa-/) }
|
|
97
|
+
values.keys.each do |key|
|
|
98
|
+
set_date_to_mysql( values[key] )
|
|
99
|
+
end
|
|
100
|
+
self.dynamic_fieldset_values = values
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# This turns your date fields into a MySQL-happy single format. This modifies the hash.
|
|
104
|
+
# @param [Hash] post The post parameters that include date fields like date(1i), date(2i), ...
|
|
105
|
+
# @return [Hash] The modified hash containing one key-pair value in YYYY-MM-DD[ hh:mm] format.
|
|
106
|
+
def set_date_to_mysql( post )
|
|
107
|
+
# 'dates' is an array of the "field-ID"s that have multiple date fields of the format field(1i), field(2i), ...
|
|
108
|
+
# e.g. [ "field-4", "field-7" ]
|
|
109
|
+
dates = post.select{ |k| k =~ /\([0-9]i\)/ }.keys.map{ |k| k.gsub /\([0-9]i\)/, '' }.uniq
|
|
110
|
+
dates.each do |field|
|
|
111
|
+
datefield = ''
|
|
112
|
+
datefield += post.delete( "#{field}(1i)" ) # year
|
|
113
|
+
datefield += '-'
|
|
114
|
+
datefield += '%02d' % post.delete( "#{field}(2i)" ) # month
|
|
115
|
+
datefield += '-'
|
|
116
|
+
datefield += '%02d' % post.delete( "#{field}(3i)" ) # day
|
|
117
|
+
if post.keys.include? "#{field}(4i)" then
|
|
118
|
+
datefield += ' '
|
|
119
|
+
datefield += '%02d' % post.delete( "#{field}(4i)" ) # hour
|
|
120
|
+
datefield += ':'
|
|
121
|
+
datefield += '%02d' % post.delete( "#{field}(5i)" ) # minute
|
|
122
|
+
datefield += ':'
|
|
123
|
+
datefield += '00' # second
|
|
124
|
+
end
|
|
125
|
+
# adding the formatted string to the hash to be saved.
|
|
126
|
+
post.merge! field => datefield
|
|
127
|
+
end
|
|
128
|
+
return post
|
|
129
|
+
end
|
|
130
|
+
|
|
42
131
|
|
|
43
132
|
# hacky system to save fieldset values
|
|
44
133
|
# needs to be refactored and tested
|
|
45
134
|
#
|
|
46
135
|
# among other things, it can edit field records for random fsas if the wrong information comes from the controller
|
|
136
|
+
|
|
47
137
|
def save_dynamic_fieldsets
|
|
48
|
-
|
|
49
|
-
|
|
138
|
+
values = self.dynamic_fieldset_values
|
|
139
|
+
if !values.nil?
|
|
140
|
+
values.keys.each do |key|
|
|
50
141
|
if key.start_with?("fsa-")
|
|
51
142
|
key_id = key.gsub(/^fsa-/, "")
|
|
52
|
-
|
|
53
|
-
|
|
143
|
+
|
|
144
|
+
if key_id.eql? ""
|
|
145
|
+
then fsa = DynamicFieldsets::FieldsetAssociator.create(
|
|
146
|
+
:fieldset_id => values[key][:fieldset_id],
|
|
147
|
+
:fieldset_model_id => self.id,
|
|
148
|
+
:fieldset_model_type => self.class.name,
|
|
149
|
+
:fieldset_model_name => values[key][:fieldset_model_name] )
|
|
150
|
+
else fsa = DynamicFieldsets::FieldsetAssociator.find_by_id key_id
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
values[key].keys.each do |sub_key| # EACH FIELD
|
|
54
154
|
if sub_key.start_with?("field-")
|
|
55
155
|
sub_key_id = sub_key.gsub(/^field-/, "")
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
156
|
+
|
|
157
|
+
this_value = values[key][sub_key]
|
|
158
|
+
if this_value.is_a? Array
|
|
159
|
+
then # multiple values
|
|
160
|
+
field_records = DynamicFieldsets::FieldRecord.where(:fieldset_associator_id => fsa.id, :fieldset_child_id => sub_key_id)
|
|
161
|
+
|
|
162
|
+
this_value.each do |value|
|
|
163
|
+
if field_records.select{ |record| record.value.eql? value }.empty? # record does not exist?
|
|
164
|
+
#ADD
|
|
165
|
+
DynamicFieldsets::FieldRecord.create( :fieldset_associator_id => fsa.id,
|
|
166
|
+
:fieldset_child_id => sub_key_id,
|
|
167
|
+
:value => value)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
field_records.each do |record|
|
|
171
|
+
if !this_value.include? record.value then
|
|
172
|
+
#DELETE
|
|
173
|
+
record.destroy
|
|
174
|
+
else
|
|
175
|
+
#KEEP
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
else # single value
|
|
180
|
+
# retrieve record
|
|
181
|
+
field_record = DynamicFieldsets::FieldRecord.where(:fieldset_associator_id => fsa.id, :fieldset_child_id => sub_key_id).first
|
|
182
|
+
if field_record.nil? # create record
|
|
183
|
+
field_record = DynamicFieldsets::FieldRecord.create(:fieldset_associator_id => fsa.id, :fieldset_child_id => sub_key_id, :value => this_value)
|
|
184
|
+
else # update record
|
|
185
|
+
field_record.value = this_value
|
|
186
|
+
field_record.save
|
|
187
|
+
end
|
|
62
188
|
end
|
|
189
|
+
|
|
63
190
|
end
|
|
64
191
|
end
|
|
65
192
|
end
|
|
@@ -130,14 +257,14 @@ module DynamicFieldsets
|
|
|
130
257
|
def fieldset_associator(sym)
|
|
131
258
|
if match_fieldset_associator?(sym)
|
|
132
259
|
fsa = DynamicFieldsets::FieldsetAssociator.find_by_fieldset_model_parameters(
|
|
133
|
-
:fieldset_model_id => self.id,
|
|
260
|
+
:fieldset_model_id => self.id,
|
|
134
261
|
:fieldset_model_type => self.class.name,
|
|
135
262
|
:fieldset_model_name => sym,
|
|
136
263
|
:fieldset => self.dynamic_fieldsets[sym][:fieldset]).first
|
|
137
264
|
if fsa.nil?
|
|
138
|
-
fsa = DynamicFieldsets::FieldsetAssociator.
|
|
139
|
-
:fieldset_model_id => self.id,
|
|
140
|
-
:fieldset_model_type => self.class.name,
|
|
265
|
+
fsa = DynamicFieldsets::FieldsetAssociator.new(
|
|
266
|
+
:fieldset_model_id => self.id,
|
|
267
|
+
:fieldset_model_type => self.class.name,
|
|
141
268
|
:fieldset_model_name => sym.to_s,
|
|
142
269
|
:fieldset => DynamicFieldsets::Fieldset.find_by_nkey(self.dynamic_fieldsets[sym][:fieldset]))
|
|
143
270
|
end
|