active_scaffold 3.4.1 → 3.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +16 -0
- data/app/assets/javascripts/active_scaffold.js.erb +7 -6
- data/app/assets/javascripts/jquery/active_scaffold.js +18 -15
- data/app/assets/javascripts/prototype/active_scaffold.js +10 -9
- data/app/assets/stylesheets/active_scaffold_jquery_ui.css.erb +4 -0
- data/app/assets/stylesheets/active_scaffold_layout.css +3 -3
- data/app/views/active_scaffold_overrides/_form_association_footer.html.erb +2 -2
- data/app/views/active_scaffold_overrides/_list_inline_adapter.html.erb +2 -2
- data/app/views/active_scaffold_overrides/destroy.js.erb +1 -1
- data/app/views/active_scaffold_overrides/on_action_update.js.erb +1 -1
- data/app/views/active_scaffold_overrides/on_create.js.erb +1 -1
- data/app/views/active_scaffold_overrides/on_mark.js.erb +1 -1
- data/app/views/active_scaffold_overrides/on_update.js.erb +1 -1
- data/app/views/active_scaffold_overrides/update_column.js.erb +2 -2
- data/lib/active_scaffold/actions/common_search.rb +2 -2
- data/lib/active_scaffold/actions/core.rb +8 -5
- data/lib/active_scaffold/actions/create.rb +2 -1
- data/lib/active_scaffold/actions/list.rb +4 -3
- data/lib/active_scaffold/actions/mark.rb +2 -1
- data/lib/active_scaffold/actions/show.rb +1 -1
- data/lib/active_scaffold/actions/update.rb +2 -1
- data/lib/active_scaffold/attribute_params.rb +1 -0
- data/lib/active_scaffold/config/base.rb +1 -1
- data/lib/active_scaffold/config/list.rb +1 -1
- data/lib/active_scaffold/config/search.rb +1 -1
- data/lib/active_scaffold/constraints.rb +1 -1
- data/lib/active_scaffold/data_structures/column.rb +16 -5
- data/lib/active_scaffold/extensions/action_view_rendering.rb +6 -6
- data/lib/active_scaffold/extensions/reverse_associations.rb +82 -46
- data/lib/active_scaffold/extensions/unsaved_associated.rb +2 -1
- data/lib/active_scaffold/finder.rb +6 -6
- data/lib/active_scaffold/helpers/form_column_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/search_column_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/view_helpers.rb +10 -1
- data/lib/active_scaffold/marked_model.rb +12 -6
- data/lib/active_scaffold/tableless.rb +6 -4
- data/lib/active_scaffold/version.rb +1 -1
- data/test/misc/attribute_params_test.rb +3 -0
- data/test/mock_app/app/models/person.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f13a22b391abab0509c40d617c528902fda68c27
|
4
|
+
data.tar.gz: a4bc30e40eb947290999544fcdec3cce07fe3236
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56f0cf576372ed2f10ddd03c6a798738237e5a3bda87e01d62b6bd3f8fe4831b7579589aa0fa50a6989c9b372e8e9c23dfd1643d682231fe356091e93f30c0d0
|
7
|
+
data.tar.gz: e8d69d8f3c33c9167829635378146560e2b771d8ab495db3adf2966d4af0061394594541020696f72b5cfb7f21577934656d26667288ba32abd318680ba7338c
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
= 3.4.2 (not released yet)
|
2
|
+
- fix tableless on latest rails4 versions
|
3
|
+
- respond with 406 for html request on js only actions
|
4
|
+
- fix JS issue on IE8
|
5
|
+
- support jquery-ui-rails 5
|
6
|
+
- update_columns fixes on subforms refreshing
|
7
|
+
- fix dynamic links menu in group links
|
8
|
+
- fix id_condition (/:id/index) for models with different primary key
|
9
|
+
- fix parent_controller param when rendering subforms on render_field
|
10
|
+
- fix session usage on rails >= 4.1
|
11
|
+
- fix marked records on rails >= 4.1
|
12
|
+
- add display_dynamic_action_group helper to help building js and html to display a dynamic action group
|
13
|
+
- display error when has_one association with :select form_ui fails to set, save continued but change was lost
|
14
|
+
- fix each_record_in_scope for rails 4 (fixes mark all records)
|
15
|
+
- trigger as:element_created for created record
|
16
|
+
|
1
17
|
= 3.4.1
|
2
18
|
- fix search value when both field_search and search are enabled and a search with field_search is active
|
3
19
|
- fix cancan permissions check on subform
|
@@ -7,12 +7,13 @@
|
|
7
7
|
<% require_asset "jquery/date_picker_bridge" %>
|
8
8
|
<% require_asset "jquery/draggable_lists" %>
|
9
9
|
<% elsif Jquery.const_defined? 'Ui' %>
|
10
|
-
<%
|
11
|
-
<% require_asset "
|
12
|
-
<% require_asset "
|
13
|
-
<% require_asset "
|
14
|
-
<% require_asset "
|
15
|
-
<% require_asset "
|
10
|
+
<% jquery_ui_prefix = Jquery::Ui::Rails::VERSION < '5.0.0' ? 'jquery.ui.' : 'jquery-ui/' %>
|
11
|
+
<% require_asset "#{jquery_ui_prefix}core" %>
|
12
|
+
<% require_asset "#{jquery_ui_prefix}effect" %>
|
13
|
+
<% require_asset "#{jquery_ui_prefix}sortable" %>
|
14
|
+
<% require_asset "#{jquery_ui_prefix}draggable" %>
|
15
|
+
<% require_asset "#{jquery_ui_prefix}droppable" %>
|
16
|
+
<% require_asset "#{jquery_ui_prefix}datepicker" %>
|
16
17
|
<% require_asset "jquery-ui-timepicker-addon" %>
|
17
18
|
<% require_asset "jquery/date_picker_bridge" %>
|
18
19
|
<% require_asset "jquery/draggable_lists" %>
|
@@ -38,7 +38,7 @@ jQuery(document).ready(function($) {
|
|
38
38
|
jQuery(document).on('focus', ':input', function() { ActiveScaffold.last_focus = this; });
|
39
39
|
jQuery(document).on('blur', ':input', function(e) { ActiveScaffold.last_focus = e.relatedTarget; });
|
40
40
|
jQuery(document).click(function(event) {
|
41
|
-
jQuery('.action_group.dyn ul').hide(); // only hide so action links loading still work
|
41
|
+
jQuery('.action_group.dyn > ul').hide(); // only hide so action links loading still work
|
42
42
|
});
|
43
43
|
jQuery(document).on('ajax:beforeSend', 'form.as_form', function(event) {
|
44
44
|
var as_form = jQuery(this).closest("form");
|
@@ -193,10 +193,10 @@ jQuery(document).ready(function($) {
|
|
193
193
|
return true;
|
194
194
|
} else return false;
|
195
195
|
});
|
196
|
-
jQuery(document).on('ajax:complete', '.action_group.dyn ul a', function(event) {
|
196
|
+
jQuery(document).on('ajax:complete', '.action_group.dyn > ul a', function(event) {
|
197
197
|
var action_link = ActiveScaffold.find_action_link(event.target);
|
198
198
|
if (action_link.loading_indicator) action_link.loading_indicator.css('visibility','hidden');
|
199
|
-
jQuery(event.target).closest('.action_group.dyn ul').remove();
|
199
|
+
jQuery(event.target).closest('.action_group.dyn > ul').remove();
|
200
200
|
});
|
201
201
|
|
202
202
|
jQuery(document).on('change', 'input.update_form:not(.recordselect), textarea.update_form, select.update_form, .checkbox-list.update_form input:checkbox', function(event) {
|
@@ -252,8 +252,8 @@ jQuery(document).ready(function($) {
|
|
252
252
|
});
|
253
253
|
|
254
254
|
jQuery(document).on('click', '.active-scaffold .sub-form a.destroy', function(event) {
|
255
|
-
|
256
|
-
|
255
|
+
event.preventDefault();
|
256
|
+
ActiveScaffold.delete_subform_record($(this).data('delete-id'));
|
257
257
|
});
|
258
258
|
|
259
259
|
jQuery(document).on("click", '.hover_click', function(event) {
|
@@ -495,7 +495,7 @@ var ActiveScaffold = {
|
|
495
495
|
replace: function(element, html) {
|
496
496
|
if (typeof(element) == 'string') element = '#' + element;
|
497
497
|
element = jQuery(element);
|
498
|
-
var new_element = typeof(html) == 'string' ? jQuery.parseHTML(
|
498
|
+
var new_element = typeof(html) == 'string' ? jQuery.parseHTML(jQuery.trim(html), true) : html;
|
499
499
|
new_element = jQuery(new_element);
|
500
500
|
if (element.length) {
|
501
501
|
element.replaceWith(new_element);
|
@@ -583,13 +583,13 @@ var ActiveScaffold = {
|
|
583
583
|
create_record_row: function(active_scaffold_id, html, options) {
|
584
584
|
if (typeof(active_scaffold_id) == 'string') active_scaffold_id = '#' + active_scaffold_id;
|
585
585
|
tbody = jQuery(active_scaffold_id).find('tbody.records').first();
|
586
|
+
var new_row;
|
586
587
|
|
587
588
|
if (options.insert_at == 'top') {
|
588
589
|
tbody.prepend(html);
|
589
|
-
|
590
|
+
new_row = tbody.children('tr.record:first-child');
|
590
591
|
} else if (options.insert_at == 'bottom') {
|
591
592
|
var rows = tbody.children('tr.record, tr.inline-adapter');
|
592
|
-
var new_row = null;
|
593
593
|
if (rows.length > 0) {
|
594
594
|
new_row = rows.last().after(html).next();
|
595
595
|
} else {
|
@@ -613,6 +613,7 @@ var ActiveScaffold = {
|
|
613
613
|
this.hide_empty_message(tbody);
|
614
614
|
this.increment_record_count(tbody.closest('div.active-scaffold'));
|
615
615
|
this.highlight(new_row);
|
616
|
+
new_row.trigger('as:element_created');
|
616
617
|
},
|
617
618
|
|
618
619
|
create_record_row_from_url: function(action_link, url, options) {
|
@@ -663,14 +664,16 @@ var ActiveScaffold = {
|
|
663
664
|
},
|
664
665
|
|
665
666
|
display_dynamic_action_group: function(link, html) {
|
667
|
+
var container;
|
666
668
|
if (typeof(link) == 'string') link = jQuery('#' + link);
|
667
|
-
link.
|
668
|
-
|
669
|
-
else {
|
670
|
-
if (link.parent('div.actions').length) link.wrap(
|
671
|
-
link.parent().addClass('action_group dyn');
|
669
|
+
if (link.closest('td.actions').length) {
|
670
|
+
container = link.closest('td').addClass('action_group dyn');
|
671
|
+
} else {
|
672
|
+
if (link.parent('div.actions').length) link.wrap(jQuery('<div>'));
|
673
|
+
container = link.parent().addClass('action_group dyn');
|
672
674
|
}
|
673
|
-
|
675
|
+
container.find('> ul').remove();
|
676
|
+
container.append(html);
|
674
677
|
},
|
675
678
|
|
676
679
|
scroll_to: function(element, checkInViewport) {
|
@@ -939,7 +942,7 @@ var ActiveScaffold = {
|
|
939
942
|
complete: function(event) {
|
940
943
|
element.nextAll('img.loading-indicator').css('visibility','hidden');
|
941
944
|
ActiveScaffold.enable_form(as_form);
|
942
|
-
if (ActiveScaffold.last_focus)
|
945
|
+
if (ActiveScaffold.last_focus) jQuery(ActiveScaffold.last_focus).focus().select();
|
943
946
|
},
|
944
947
|
error: function (xhr, status, error) {
|
945
948
|
var as_div = element.closest("div.active-scaffold");
|
@@ -13,13 +13,13 @@ if (!Element.Methods.highlight) Element.addMethods({highlight: Prototype.emptyFu
|
|
13
13
|
|
14
14
|
document.observe("dom:loaded", function() {
|
15
15
|
document.on('click', function(event) {
|
16
|
-
$$('.action_group.dyn ul').invoke('
|
16
|
+
$$('.action_group.dyn > ul').invoke('hide');
|
17
17
|
});
|
18
|
-
document.on('ajax:complete', '.action_group.dyn ul a', function() {
|
18
|
+
document.on('ajax:complete', '.action_group.dyn > ul a', function() {
|
19
19
|
var source = event.findElement();
|
20
20
|
var action_link = ActiveScaffold.find_action_link(source);
|
21
21
|
if (action_link.loading_indicator) action_link.loading_indicator.css('visibility','hidden');
|
22
|
-
$(source).up('.action_group.dyn ul').remove();
|
22
|
+
$(source).up('.action_group.dyn > ul').remove();
|
23
23
|
});
|
24
24
|
document.on('ajax:create', 'form.as_form', function(event) {
|
25
25
|
var source = event.findElement();
|
@@ -568,15 +568,16 @@ var ActiveScaffold = {
|
|
568
568
|
},
|
569
569
|
|
570
570
|
display_dynamic_action_group: function(link, html) {
|
571
|
+
var container;
|
571
572
|
link = $(link);
|
572
|
-
link.
|
573
|
-
|
574
|
-
|
575
|
-
else {
|
573
|
+
if (link.up('td.actions')) {
|
574
|
+
container = link.up('td').addClassName('action_group dyn');
|
575
|
+
} else {
|
576
576
|
if (link.up().hasClassName('actions')) link.wrap('div');
|
577
|
-
link.up().addClassName('action_group dyn');
|
577
|
+
container = link.up().addClassName('action_group dyn');
|
578
578
|
}
|
579
|
-
|
579
|
+
container.down('> ul').remove();
|
580
|
+
container.insert({bottom: html});
|
580
581
|
},
|
581
582
|
|
582
583
|
scroll_to: function(element, checkInViewport) {
|
@@ -2,6 +2,10 @@
|
|
2
2
|
<% require_asset "jquery-ui" %>
|
3
3
|
<% require_asset "jquery-ui-theme" %>
|
4
4
|
<% elsif Jquery.const_defined? 'Ui' %>
|
5
|
+
<% if Jquery::Ui::Rails::VERSION < '5.0.0' %>
|
5
6
|
<% require_asset "jquery.ui.datepicker" %>
|
7
|
+
<% else %>
|
8
|
+
<% require_asset "jquery-ui/datepicker" %>
|
9
|
+
<% end %>
|
6
10
|
<% require_asset "jquery-ui-theme" %>
|
7
11
|
<% end %>
|
@@ -261,7 +261,7 @@ min-width: 150px;
|
|
261
261
|
right: 0px;
|
262
262
|
z-index: 2;
|
263
263
|
}
|
264
|
-
.active-scaffold .actions .action_group.dyn ul {
|
264
|
+
.active-scaffold .actions .action_group.dyn > ul {
|
265
265
|
width: auto;
|
266
266
|
display: block;
|
267
267
|
}
|
@@ -296,7 +296,7 @@ text-align: left;
|
|
296
296
|
background-position: 5px 50%;
|
297
297
|
background-repeat: no-repeat;
|
298
298
|
}
|
299
|
-
.active-scaffold .actions .action_group.dyn ul li a {
|
299
|
+
.active-scaffold .actions .action_group.dyn > ul li a {
|
300
300
|
padding-left: 5px;
|
301
301
|
}
|
302
302
|
|
@@ -309,7 +309,7 @@ border-top-width: 0px;
|
|
309
309
|
display: none;
|
310
310
|
}
|
311
311
|
|
312
|
-
.active-scaffold .actions .action_group:hover ul,
|
312
|
+
.active-scaffold .actions .action_group:hover > ul,
|
313
313
|
.active-scaffold .actions .action_group ul li:hover > ul,
|
314
314
|
.active-scaffold .actions .action_group ul ul li:hover ul {
|
315
315
|
display: block;
|
@@ -13,8 +13,8 @@ return unless show_add_new or show_add_existing
|
|
13
13
|
|
14
14
|
temporary_id = generated_id(parent_record) if parent_record.new_record?
|
15
15
|
controller_path = active_scaffold_controller_for(parent_record.class).controller_path
|
16
|
-
edit_associated_url = params_for(:controller => controller_path, :action => 'edit_associated', :child_association => column.name, :associated_id => '--ID--', :scope => scope, :id => parent_record.to_param, :generated_id => temporary_id, :parent_controller => controller.controller_path) if show_add_existing
|
17
|
-
add_new_url = params_for(:controller => controller_path, :action => 'edit_associated', :child_association => column.name, :scope => scope, :id => parent_record.to_param, :generated_id => temporary_id, :parent_controller => controller.controller_path) if show_add_new
|
16
|
+
edit_associated_url = params_for(:controller => controller_path, :action => 'edit_associated', :child_association => column.name, :associated_id => '--ID--', :scope => scope, :id => parent_record.to_param, :generated_id => temporary_id, :parent_controller => params[:parent_controller] || controller.controller_path) if show_add_existing
|
17
|
+
add_new_url = params_for(:controller => controller_path, :action => 'edit_associated', :child_association => column.name, :scope => scope, :id => parent_record.to_param, :generated_id => temporary_id, :parent_controller => params[:parent_controller] || controller.controller_path) if show_add_new
|
18
18
|
|
19
19
|
-%>
|
20
20
|
<div class="footer-wrapper">
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<%# nested_id, allows us to remove a nested scaffold programmatically %>
|
2
2
|
<tr class="inline-adapter" id="<%= element_row_id :action => :nested %>">
|
3
3
|
<td class="inline-adapter-cell">
|
4
|
-
<% if
|
4
|
+
<% if successful? %>
|
5
5
|
<div class="<%= "#{params[:action]}-view" if params[:action] %> <%= "#{nested? ? nested.name : id_from_controller(params[:controller])}-view" %> view">
|
6
6
|
<%= link_to(as_(:close), '', :class => 'inline-adapter-close as_cancel', :remote => true, :title => as_(:close)) -%>
|
7
7
|
<%= payload -%>
|
8
8
|
</div>
|
9
9
|
<% end %>
|
10
|
+
<%= javascript_tag("setTimeout(function() { var action_link = ActiveScaffold.ActionLink.get('#{element_row_id(:action => :nested)}'); if (action_link) { action_link.update_flash_messages('#{escape_javascript(render(:partial => 'messages').strip)}');#{' action_link.close(); ActiveScaffold.scroll_to(action_link.scaffold(), ActiveScaffold.config.scroll_on_close == "checkInViewport");' unless successful?} } }, 10);") %>
|
10
11
|
</td>
|
11
12
|
</tr>
|
12
|
-
<%= javascript_tag("setTimeout(function() { var action_link = ActiveScaffold.ActionLink.get('#{element_row_id(:action => :nested)}'); if (action_link) { action_link.update_flash_messages('#{escape_javascript(render(:partial => 'messages').strip)}');#{' action_link.close(); ActiveScaffold.scroll_to(action_link.scaffold(), ActiveScaffold.config.scroll_on_close == "checkInViewport");' unless controller.send(:successful?)} } }, 10);") %>
|
@@ -8,7 +8,7 @@ insert_at ||= :top -%>
|
|
8
8
|
action_link = ActiveScaffold.find_action_link('<%= form_selector %>');
|
9
9
|
action_link.update_flash_messages('<%= escape_javascript(render(:partial => 'messages')) %>');
|
10
10
|
<% end -%>
|
11
|
-
<% if
|
11
|
+
<% if successful? -%>
|
12
12
|
<% if render_parent? %>
|
13
13
|
<% if nested_singular_association? %>
|
14
14
|
action_link.close(true);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<%
|
2
2
|
checked = all_marked? unless local_assigns.has_key? :checked
|
3
|
-
options = {:checked => checked, :include_mark_all => true, :include_checkboxes =>
|
3
|
+
options = {:checked => checked, :include_mark_all => true, :include_checkboxes => @include_checkboxes}
|
4
4
|
%>
|
5
5
|
ActiveScaffold.mark_records('<%= active_scaffold_tbody_id %>',<%= options.to_json.html_safe %>);
|
6
6
|
<%= render :partial => 'update_messages' %>
|
@@ -2,7 +2,7 @@ try {
|
|
2
2
|
<% form_selector = "#{element_form_id(:action => :update, :id => @record.try(:id) || params[:id])}" %>
|
3
3
|
var action_link = ActiveScaffold.find_action_link('<%= form_selector %>');
|
4
4
|
action_link.update_flash_messages('<%= escape_javascript(render(:partial => 'messages')) %>');
|
5
|
-
<% if
|
5
|
+
<% if successful? %>
|
6
6
|
<% if params[:dont_close] %>
|
7
7
|
<% row_selector = element_row_id(:action => :list, :id => @record.id) %>
|
8
8
|
ActiveScaffold.update_row('<%= row_selector %>', '<%= escape_javascript(render(:partial => 'list_record', :locals => {:record => @record})) %>');
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<% @column_span_id ||= element_cell_id(:id => @record.id.to_s, :action => 'update_column', :name => @column.name) -%>
|
2
|
-
<% unless
|
2
|
+
<% unless successful? -%>
|
3
3
|
alert('<%= escape_javascript(@record.errors.full_messages.join("\n")) %>');
|
4
4
|
<% @record.reload -%>
|
5
5
|
<% end -%>
|
6
6
|
<% if @column.inplace_edit
|
7
|
-
ipe_update = @column.inplace_edit_update if
|
7
|
+
ipe_update = @column.inplace_edit_update if successful? -%>
|
8
8
|
<% case ipe_update
|
9
9
|
when :row -%>
|
10
10
|
ActiveScaffold.update_row('<%= element_row_id(:action => :list) %>', '<%= escape_javascript render('row', :record => @record) %>');
|
@@ -29,14 +29,14 @@ module ActiveScaffold::Actions
|
|
29
29
|
|
30
30
|
def store_search_params_into_session
|
31
31
|
if active_scaffold_config.store_user_settings
|
32
|
-
active_scaffold_session_storage[
|
32
|
+
active_scaffold_session_storage['search'] = params.delete :search if params[:search]
|
33
33
|
else
|
34
34
|
@search_params = params.delete :search
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def search_params
|
39
|
-
@search_params || active_scaffold_session_storage[
|
39
|
+
@search_params || active_scaffold_session_storage['search']
|
40
40
|
end
|
41
41
|
|
42
42
|
def global_search_ignore?
|
@@ -17,8 +17,12 @@ module ActiveScaffold::Actions
|
|
17
17
|
def render_field
|
18
18
|
if request.get?
|
19
19
|
render_field_for_inplace_editing
|
20
|
+
respond_to do |format|
|
21
|
+
format.js { render :action => 'render_field_inplace', :layout => false }
|
22
|
+
end
|
20
23
|
else
|
21
24
|
render_field_for_update_columns
|
25
|
+
respond_to { |format| format.js }
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
@@ -38,7 +42,6 @@ module ActiveScaffold::Actions
|
|
38
42
|
def render_field_for_inplace_editing
|
39
43
|
@column = active_scaffold_config.columns[params[:update_column]]
|
40
44
|
@record = find_if_allowed(params[:id], :crud_type => :update, :column => params[:update_column])
|
41
|
-
render :action => 'render_field_inplace', :layout => false
|
42
45
|
end
|
43
46
|
|
44
47
|
def render_field_for_update_columns
|
@@ -62,7 +65,7 @@ module ActiveScaffold::Actions
|
|
62
65
|
end
|
63
66
|
|
64
67
|
# check permissions and support overriding to_param
|
65
|
-
record = find_if_allowed(id, :
|
68
|
+
record = find_if_allowed(id, :read) if id
|
66
69
|
# call update_record_from_params with new_model
|
67
70
|
# in other case some associations can be saved
|
68
71
|
@record = new_model
|
@@ -70,7 +73,7 @@ module ActiveScaffold::Actions
|
|
70
73
|
apply_constraints_to_record(@record) unless @scope
|
71
74
|
@record = update_record_from_params(@record, @main_columns, hash, true)
|
72
75
|
else
|
73
|
-
@record = params[:id] ? find_if_allowed(params[:id], :
|
76
|
+
@record = params[:id] ? find_if_allowed(params[:id], :read) : new_model
|
74
77
|
if @record.new_record?
|
75
78
|
apply_constraints_to_record(@record) unless @scope
|
76
79
|
else
|
@@ -125,11 +128,11 @@ module ActiveScaffold::Actions
|
|
125
128
|
end
|
126
129
|
|
127
130
|
def each_marked_record(&block)
|
128
|
-
active_scaffold_config.model.
|
131
|
+
active_scaffold_config.model.as_marked.each &block
|
129
132
|
end
|
130
133
|
|
131
134
|
def marked_records
|
132
|
-
active_scaffold_session_storage[
|
135
|
+
active_scaffold_session_storage['marked_records'] ||= {}
|
133
136
|
end
|
134
137
|
|
135
138
|
def default_formats
|
@@ -101,7 +101,8 @@ module ActiveScaffold::Actions
|
|
101
101
|
apply_constraints_to_record(@record, :allow_autosave => true)
|
102
102
|
create_association_with_parent(@record) if nested?
|
103
103
|
before_create_save(@record)
|
104
|
-
|
104
|
+
# errors to @record can be added by update_record_from_params when association fails to set and ActiveRecord::RecordNotSaved is raised
|
105
|
+
self.successful = [@record.errors.empty? && @record.valid?, @record.associated_valid?].all? # this syntax avoids a short-circuit
|
105
106
|
create_save(@record) unless options[:skip_save]
|
106
107
|
end
|
107
108
|
rescue ActiveRecord::ActiveRecordError => ex
|
@@ -132,7 +132,8 @@ module ActiveScaffold::Actions
|
|
132
132
|
def each_record_in_scope
|
133
133
|
do_search if respond_to? :do_search, true
|
134
134
|
set_includes_for_columns
|
135
|
-
|
135
|
+
# where(nil) is needed because we need a relation
|
136
|
+
append_to_query(beginning_of_chain.where(nil), finder_options).each {|record| yield record}
|
136
137
|
end
|
137
138
|
|
138
139
|
# The default security delegates to ActiveRecordPermissions.
|
@@ -151,11 +152,11 @@ module ActiveScaffold::Actions
|
|
151
152
|
def process_action_link_action(render_action = :action_update, crud_type_or_security_options = nil)
|
152
153
|
if request.get?
|
153
154
|
# someone has disabled javascript, we have to show confirmation form first
|
154
|
-
@record = find_if_allowed(params[:id], :read) if params[:id]
|
155
|
+
@record = find_if_allowed(params[:id], :read) if params[:id]
|
155
156
|
respond_to_action(:action_confirmation)
|
156
157
|
else
|
157
158
|
@action_link = active_scaffold_config.action_links[action_name]
|
158
|
-
if params[:id]
|
159
|
+
if params[:id]
|
159
160
|
crud_type_or_security_options ||= (request.post? || request.put?) ? :update : :delete
|
160
161
|
get_row(crud_type_or_security_options)
|
161
162
|
unless @record.nil?
|
@@ -27,12 +27,13 @@ module ActiveScaffold::Actions
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def mark_respond_to_js
|
30
|
-
if params
|
30
|
+
if params.delete(:id) # so find_page doesn't filter by :id
|
31
31
|
do_search if respond_to? :do_search, true
|
32
32
|
set_includes_for_columns if active_scaffold_config.actions.include? :list
|
33
33
|
@page = find_page(:pagination => active_scaffold_config.mark.mark_all_mode != :page)
|
34
34
|
render :action => 'on_mark'
|
35
35
|
else
|
36
|
+
@include_checkboxes = true
|
36
37
|
render :action => 'on_mark', :locals => {:checked => mark?}
|
37
38
|
end
|
38
39
|
end
|
@@ -11,7 +11,7 @@ module ActiveScaffold::Actions
|
|
11
11
|
do_show
|
12
12
|
respond_to_action(:show)
|
13
13
|
else
|
14
|
-
@record = find_if_allowed(params[:id], :read) if params[:id]
|
14
|
+
@record = find_if_allowed(params[:id], :read) if params[:id]
|
15
15
|
action_confirmation_respond_to_html(:destroy)
|
16
16
|
end
|
17
17
|
end
|
@@ -101,7 +101,8 @@ module ActiveScaffold::Actions
|
|
101
101
|
active_scaffold_config.model.transaction do
|
102
102
|
@record = update_record_from_params(@record, active_scaffold_config.update.columns, attributes) unless options[:no_record_param_update]
|
103
103
|
before_update_save(@record)
|
104
|
-
|
104
|
+
# errors to @record can be added by update_record_from_params when association fails to set and ActiveRecord::RecordNotSaved is raised
|
105
|
+
self.successful = [@record.errors.empty? && @record.valid?, @record.associated_valid?].all? # this syntax avoids a short-circuit
|
105
106
|
if successful?
|
106
107
|
@record.save! and @record.save_associated!
|
107
108
|
after_update_save(@record)
|
@@ -41,7 +41,7 @@ module ActiveScaffold::Config
|
|
41
41
|
def columns
|
42
42
|
# we want to delay initializing to the @core.columns set for as long as possible. Too soon and .search_sql will not be available to .searchable?
|
43
43
|
unless @columns
|
44
|
-
self.columns = @core.columns.collect{|c| c.name if @core.columns._inheritable.include?(c.name) and c.searchable? and c.
|
44
|
+
self.columns = @core.columns.collect{|c| c.name if @core.columns._inheritable.include?(c.name) and c.searchable? and c.text?}.compact
|
45
45
|
end
|
46
46
|
@columns
|
47
47
|
end
|
@@ -5,7 +5,7 @@ module ActiveScaffold
|
|
5
5
|
|
6
6
|
# Returns the current constraints
|
7
7
|
def active_scaffold_constraints
|
8
|
-
@active_scaffold_constraints ||= active_scaffold_session_storage[
|
8
|
+
@active_scaffold_constraints ||= active_scaffold_session_storage['constraints'] || {}
|
9
9
|
end
|
10
10
|
|
11
11
|
# For each enabled action, adds the constrained columns to the ActionColumns object (if it exists).
|
@@ -291,6 +291,10 @@ module ActiveScaffold::DataStructures
|
|
291
291
|
@number
|
292
292
|
end
|
293
293
|
|
294
|
+
def text?
|
295
|
+
@text
|
296
|
+
end
|
297
|
+
|
294
298
|
# this is so that array.delete and array.include?, etc., will work by column name
|
295
299
|
def ==(other) #:nodoc:
|
296
300
|
# another column
|
@@ -338,11 +342,18 @@ module ActiveScaffold::DataStructures
|
|
338
342
|
end
|
339
343
|
end
|
340
344
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
345
|
+
@text = @column.nil? || [:string, :text].include?(@column.type)
|
346
|
+
if @column
|
347
|
+
@form_ui = case @column.type
|
348
|
+
when :boolean then :checkbox
|
349
|
+
when :text then :textarea
|
350
|
+
end
|
351
|
+
if @column.number?
|
352
|
+
@number = true
|
353
|
+
@form_ui = :number
|
354
|
+
@options = {:format => :i18n_number}
|
355
|
+
end
|
356
|
+
end
|
346
357
|
@allow_add_existing = true
|
347
358
|
@form_ui = self.class.association_form_ui if @association && self.class.association_form_ui
|
348
359
|
|
@@ -45,19 +45,19 @@ module ActionView::Helpers #:nodoc:
|
|
45
45
|
eid = Digest::MD5.hexdigest(params[:controller] + remote_controller.to_s + constraints.to_s + conditions.to_s)
|
46
46
|
eid_info = session["as:#{eid}"] ||= {}
|
47
47
|
if constraints
|
48
|
-
eid_info[
|
48
|
+
eid_info['constraints'] = constraints
|
49
49
|
else
|
50
|
-
eid_info.delete
|
50
|
+
eid_info.delete 'constraints'
|
51
51
|
end
|
52
52
|
if conditions
|
53
|
-
eid_info[
|
53
|
+
eid_info['conditions'] = conditions
|
54
54
|
else
|
55
|
-
eid_info.delete
|
55
|
+
eid_info.delete 'conditions'
|
56
56
|
end
|
57
57
|
if options[:label]
|
58
|
-
eid_info[
|
58
|
+
eid_info['list'] = {'label' => options[:label]}
|
59
59
|
else
|
60
|
-
eid_info.delete
|
60
|
+
eid_info.delete 'list'
|
61
61
|
end
|
62
62
|
session.delete "as:#{eid}" if eid_info.empty?
|
63
63
|
options[:params] ||= {}
|
@@ -1,12 +1,20 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
1
|
+
module ActiveScaffold
|
2
|
+
module ReverseAssociation
|
3
|
+
module CommonMethods
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval { attr_writer :reverse }
|
6
|
+
base.alias_method_chain :inverse_of, :autodetect
|
7
|
+
end
|
8
|
+
|
9
|
+
def inverse_of_with_autodetect
|
10
|
+
inverse_of_without_autodetect || autodetect_inverse
|
11
|
+
end
|
12
|
+
|
4
13
|
def inverse_for?(klass)
|
5
14
|
inverse_class = inverse_of.try(:active_record)
|
6
15
|
inverse_class.present? && (inverse_class == klass || klass < inverse_class)
|
7
16
|
end
|
8
17
|
|
9
|
-
attr_writer :reverse
|
10
18
|
def reverse(klass = nil)
|
11
19
|
unless defined? @reverse
|
12
20
|
@reverse ||= inverse_of.try(:name)
|
@@ -14,56 +22,84 @@ module ActiveRecord
|
|
14
22
|
@reverse || (autodetect_inverse(klass).try(:name) unless klass.nil?)
|
15
23
|
end
|
16
24
|
|
17
|
-
def
|
18
|
-
|
25
|
+
def autodetect_inverse(klass = nil)
|
26
|
+
return nil if klass.nil? && options[:polymorphic]
|
27
|
+
klass ||= self.klass
|
28
|
+
|
29
|
+
# name-based matching (association name vs self.active_record.to_s)
|
30
|
+
matches = self.reverse_matches(klass)
|
31
|
+
if matches.length > 1
|
32
|
+
matches.find_all do |assoc|
|
33
|
+
self.active_record.to_s.underscore.include? assoc.name.to_s.pluralize.singularize
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
matches.first
|
19
38
|
end
|
20
|
-
|
39
|
+
end
|
21
40
|
|
41
|
+
module AssociationReflection
|
42
|
+
def self.included(base)
|
43
|
+
base.send :include, ActiveScaffold::ReverseAssociation::CommonMethods
|
44
|
+
end
|
45
|
+
|
22
46
|
protected
|
47
|
+
def reverse_matches(klass)
|
48
|
+
reverse_matches = []
|
23
49
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
klass.reflect_on_all_associations.each do |assoc|
|
31
|
-
next if assoc == self
|
32
|
-
if self.options[:through]
|
33
|
-
# only iterate has_many :through associations
|
34
|
-
next unless assoc.options[:through]
|
35
|
-
next unless assoc.through_reflection.klass == self.through_reflection.klass
|
36
|
-
else
|
37
|
-
# skip over has_many :through associations
|
38
|
-
next if assoc.options[:through]
|
39
|
-
next unless assoc.options[:polymorphic] or assoc.class_name == self.active_record.name
|
40
|
-
|
41
|
-
case [assoc.macro, self.macro].find_all{|m| m == :has_and_belongs_to_many}.length
|
42
|
-
# if both are a habtm, then match them based on the join table
|
43
|
-
when 2
|
44
|
-
next unless assoc.options[:join_table] == self.options[:join_table]
|
45
|
-
|
46
|
-
# if only one is a habtm, they do not match
|
47
|
-
when 1
|
48
|
-
next
|
49
|
-
|
50
|
-
# otherwise, match them based on the foreign_key
|
51
|
-
when 0
|
52
|
-
next unless assoc.foreign_key.to_sym == self.foreign_key.to_sym
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
reverse_matches << assoc
|
57
|
-
end
|
50
|
+
# collect associations that point back to this model and use the same foreign_key
|
51
|
+
klass.reflect_on_all_associations.each do |assoc|
|
52
|
+
next if assoc == self
|
53
|
+
# skip over has_many :through associations
|
54
|
+
next if assoc.options[:through]
|
55
|
+
next unless assoc.options[:polymorphic] or assoc.class_name == self.active_record.name
|
58
56
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
case [assoc.macro, self.macro].find_all{|m| m == :has_and_belongs_to_many}.length
|
58
|
+
# if both are a habtm, then match them based on the join table
|
59
|
+
when 2
|
60
|
+
next unless assoc.options[:join_table] == self.options[:join_table]
|
61
|
+
|
62
|
+
# if only one is a habtm, they do not match
|
63
|
+
when 1
|
64
|
+
next
|
65
|
+
|
66
|
+
# otherwise, match them based on the foreign_key
|
67
|
+
when 0
|
68
|
+
next unless assoc.foreign_key.to_sym == self.foreign_key.to_sym
|
69
|
+
end
|
63
70
|
|
64
|
-
reverse_matches
|
71
|
+
reverse_matches << assoc
|
65
72
|
end
|
73
|
+
reverse_matches
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
module ThroughReflection
|
78
|
+
def self.included(base)
|
79
|
+
base.send :include, ActiveScaffold::ReverseAssociation::CommonMethods unless base < ActiveScaffold::ReverseAssociation::CommonMethods
|
80
|
+
end
|
66
81
|
|
82
|
+
protected
|
83
|
+
|
84
|
+
def reverse_matches(klass)
|
85
|
+
reverse_matches = []
|
86
|
+
|
87
|
+
# collect associations that point back to this model and use the same foreign_key
|
88
|
+
klass.reflect_on_all_associations.each do |assoc|
|
89
|
+
next if assoc == self
|
90
|
+
# only iterate has_many :through associations
|
91
|
+
next unless assoc.options[:through]
|
92
|
+
next unless assoc.class_name == self.active_record.name
|
93
|
+
next unless assoc.through_reflection.class_name == self.through_reflection.class_name
|
94
|
+
|
95
|
+
reverse_matches << assoc
|
96
|
+
end
|
97
|
+
reverse_matches
|
98
|
+
end
|
67
99
|
end
|
100
|
+
|
68
101
|
end
|
69
102
|
end
|
103
|
+
|
104
|
+
ActiveRecord::Reflection::AssociationReflection.send :include, ActiveScaffold::ReverseAssociation::AssociationReflection
|
105
|
+
ActiveRecord::Reflection::ThroughReflection.send :include, ActiveScaffold::ReverseAssociation::ThroughReflection
|
@@ -4,7 +4,8 @@ class ActiveRecord::Base
|
|
4
4
|
return true if path.include?(self) # prevent recursion (if associated and parent are new records)
|
5
5
|
path << self
|
6
6
|
# using [].all? syntax to avoid a short-circuit
|
7
|
-
|
7
|
+
# errors to associated record can be added by update_record_from_params when association fails to set and ActiveRecord::RecordNotSaved is raised
|
8
|
+
with_unsaved_associated { |a| [a.errors.empty? && a.valid?, a.associated_valid?(path)].all? }
|
8
9
|
end
|
9
10
|
|
10
11
|
def save_associated
|
@@ -18,7 +18,7 @@ module ActiveScaffold
|
|
18
18
|
where_clauses = []
|
19
19
|
columns.each do |column|
|
20
20
|
Array(column.search_sql).each do |search_sql|
|
21
|
-
where_clauses << "#{search_sql} #{
|
21
|
+
where_clauses << "#{search_sql} #{column.text? ? ActiveScaffold::Finder.like_operator : '='} ?"
|
22
22
|
end
|
23
23
|
end
|
24
24
|
phrase = where_clauses.join(' OR ')
|
@@ -26,7 +26,7 @@ module ActiveScaffold
|
|
26
26
|
tokens.collect do |value|
|
27
27
|
columns.inject([phrase]) do |condition, column|
|
28
28
|
Array(column.search_sql).size.times do
|
29
|
-
condition.push(
|
29
|
+
condition.push(column.text? ? like_pattern.sub('?', value) : column.column.type_cast(value))
|
30
30
|
end
|
31
31
|
condition
|
32
32
|
end
|
@@ -62,7 +62,7 @@ module ActiveScaffold
|
|
62
62
|
when :select, :multi_select, :country, :usa_state, :chosen, :multi_chosen
|
63
63
|
["%{search_sql} in (?)", Array(value)]
|
64
64
|
else
|
65
|
-
if column.
|
65
|
+
if column.text?
|
66
66
|
["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
|
67
67
|
else
|
68
68
|
["%{search_sql} = ?", column.column.type_cast(value)]
|
@@ -97,7 +97,7 @@ module ActiveScaffold
|
|
97
97
|
|
98
98
|
def condition_for_range(column, value, like_pattern = nil)
|
99
99
|
if !value.is_a?(Hash)
|
100
|
-
if column.
|
100
|
+
if column.text?
|
101
101
|
["%{search_sql} #{ActiveScaffold::Finder.like_operator} ?", like_pattern.sub('?', value)]
|
102
102
|
else
|
103
103
|
["%{search_sql} = ?", column.column.type_cast(value)]
|
@@ -320,12 +320,12 @@ module ActiveScaffold
|
|
320
320
|
conditions_for_collection, # from the dev
|
321
321
|
conditions_from_params, # from the parameters (e.g. /users/list?first_name=Fred)
|
322
322
|
conditions_from_constraints, # from any constraints (embedded scaffolds)
|
323
|
-
active_scaffold_session_storage[
|
323
|
+
active_scaffold_session_storage['conditions'] # embedding conditions (weaker constraints)
|
324
324
|
].reject(&:blank?)
|
325
325
|
end
|
326
326
|
|
327
327
|
def id_condition
|
328
|
-
{
|
328
|
+
{active_scaffold_config.model.primary_key => params[:id]} if params[:id]
|
329
329
|
end
|
330
330
|
|
331
331
|
# returns a single record (the given id) but only if it's allowed for the specified security options.
|
@@ -130,7 +130,7 @@ module ActiveScaffold
|
|
130
130
|
ActiveSupport::Deprecation.warn "Relying on @record is deprecated, include :object in options with record.", caller if record.nil? # TODO Remove when relying on @record is removed
|
131
131
|
record ||= @record # TODO Remove when relying on @record is removed
|
132
132
|
subform_controller = controller.class.active_scaffold_controller_for(record.class) if scope
|
133
|
-
form_columns = @main_columns.try(:names)
|
133
|
+
form_columns = @main_columns.try(:names) if scope.nil? || subform_controller == controller.class
|
134
134
|
form_columns ||= current_form_columns(record, scope, subform_controller)
|
135
135
|
if force || (form_columns && column.update_columns && (column.update_columns & form_columns).present?)
|
136
136
|
url_params = params_for(:action => 'render_field', :column => column.name, :id => record.to_param)
|
@@ -156,7 +156,7 @@ module ActiveScaffold
|
|
156
156
|
end
|
157
157
|
|
158
158
|
def active_scaffold_search_range_string?(column)
|
159
|
-
|
159
|
+
column.text? || column.search_ui == :string
|
160
160
|
end
|
161
161
|
|
162
162
|
def active_scaffold_search_range_comparator_options(column)
|
@@ -96,6 +96,15 @@ module ActiveScaffold
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
+
def display_dynamic_action_group(action_link, links, record_or_ul_options = nil, ul_options = nil)
|
100
|
+
ul_options = record_or_ul_options if ul_options.nil? && record_or_ul_options.is_a?(Hash)
|
101
|
+
record = record_or_ul_options unless record_or_ul_options.is_a?(Hash)
|
102
|
+
html = content_tag :ul, ul_options do
|
103
|
+
links.map { |link| content_tag :li, link }.join('').html_safe
|
104
|
+
end
|
105
|
+
raw "ActiveScaffold.display_dynamic_action_group('#{get_action_link_id action_link, record}', '#{escape_javascript html}');"
|
106
|
+
end
|
107
|
+
|
99
108
|
def display_action_links(action_links, record, options, &block)
|
100
109
|
options[:level_0_tag] ||= nil
|
101
110
|
options[:options_level_0_tag] ||= nil
|
@@ -512,7 +521,7 @@ module ActiveScaffold
|
|
512
521
|
|
513
522
|
def column_empty?(column_value)
|
514
523
|
empty = column_value.nil?
|
515
|
-
empty ||=
|
524
|
+
empty ||= false != column_value && column_value.blank?
|
516
525
|
empty ||= [' ', active_scaffold_config.list.empty_field_text].include? column_value if String === column_value
|
517
526
|
return empty
|
518
527
|
end
|
@@ -3,31 +3,37 @@ module ActiveScaffold
|
|
3
3
|
# This is a module aimed at making the make session_stored marked_records available to ActiveRecord models
|
4
4
|
|
5
5
|
def self.included(base)
|
6
|
-
base.
|
7
|
-
|
6
|
+
base.class_eval do
|
7
|
+
extend ClassMethods
|
8
|
+
scope :as_marked, lambda { where(primary_key => marked_record_ids) }
|
9
|
+
end
|
8
10
|
end
|
9
11
|
|
10
12
|
def as_marked
|
11
|
-
marked_records.include?(self.id)
|
13
|
+
marked_records.include?(self.id.to_s)
|
12
14
|
end
|
13
15
|
|
14
16
|
def as_marked=(value)
|
15
17
|
value = [true, 'true', 1, '1', 'T', 't'].include?(value.class == String ? value.downcase : value)
|
16
18
|
if value == true
|
17
|
-
marked_records
|
19
|
+
marked_records[self.id.to_s] = true if !as_marked
|
18
20
|
else
|
19
|
-
marked_records.delete(self.id)
|
21
|
+
marked_records.delete(self.id.to_s)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
module ClassMethods
|
24
26
|
def marked_records
|
25
|
-
Thread.current[:marked_records] ||=
|
27
|
+
Thread.current[:marked_records] ||= {}
|
26
28
|
end
|
27
29
|
|
28
30
|
def marked_records=(marked)
|
29
31
|
Thread.current[:marked_records] = marked
|
30
32
|
end
|
33
|
+
|
34
|
+
def marked_record_ids
|
35
|
+
marked_records.keys
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
39
|
# Instance-level access to the marked_records
|
@@ -195,13 +195,15 @@ class ActiveScaffold::Tableless < ActiveRecord::Base
|
|
195
195
|
raise 'destroy must be implemented in a Tableless model'
|
196
196
|
end
|
197
197
|
|
198
|
-
def
|
198
|
+
def _create_record #:nodoc:
|
199
199
|
run_callbacks(:create) {}
|
200
200
|
end
|
201
|
-
alias_method :
|
201
|
+
alias_method :create_record, :_create_record # for rails4 < 4.0.6, < 4.1.2
|
202
|
+
alias_method :create, :_create_record # for rails3
|
202
203
|
|
203
|
-
def
|
204
|
+
def _update_record(*) #:nodoc:
|
204
205
|
run_callbacks(:update) {}
|
205
206
|
end
|
206
|
-
alias_method :
|
207
|
+
alias_method :update_record, :_update_record # for rails4 < 4.0.6, < 4.1.2
|
208
|
+
alias_method :update, :_update_record # for rails3
|
207
209
|
end
|
@@ -2,7 +2,7 @@ class Person < ActiveRecord::Base
|
|
2
2
|
has_many :buildings, :foreign_key => :owner_id
|
3
3
|
has_one :floor, :foreign_key => :tenant_id
|
4
4
|
has_one :address, :through => :floor
|
5
|
-
has_one :home, :through => :floor, :source => :building
|
5
|
+
has_one :home, :through => :floor, :source => :building, :class_name => 'Building'
|
6
6
|
|
7
7
|
has_many :contacts, :as => :contactable
|
8
8
|
has_one :car, :dependent => :destroy
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_scaffold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.4.
|
4
|
+
version: 3.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Many, see README
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: shoulda
|