active_scaffold 3.4.1 → 3.4.2
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.
- 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
|