From 1f10858b830d321868f79801099627f1e417c1e9 Mon Sep 17 00:00:00 2001 From: Tim Glen Date: Fri, 9 Sep 2016 12:07:59 -0400 Subject: [PATCH] The permitted_params now automatically included Registered Content Blocks in both #page_attributes and #page_content_attributes --- app/models/smithy/permitted_params.rb | 52 +++++++++++++-------- spec/factories/smithy_assets.rb | 2 + spec/models/smithy/permitted_params_spec.rb | 41 ++++++++++++++-- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/app/models/smithy/permitted_params.rb b/app/models/smithy/permitted_params.rb index 0a63bc6..b1681a3 100644 --- a/app/models/smithy/permitted_params.rb +++ b/app/models/smithy/permitted_params.rb @@ -37,18 +37,18 @@ def image_attributes end def page_attributes - # :all [ :browser_title, :cache_length, :description, :external_link, :keywords, :permalink, :publish, :published_at, :show_in_navigation, :title, :parent_id, :template_id, :copy_content_from, - contents_attributes: nested_attributes(:page_content) + contents_attributes: page_content_attributes + [:id, :_destroy] ] end def page_content_attributes attributes = [ :label, :css_classes, :container, :content_block_type, :content_block_template_id, :position ] - if params[:content_block_type].present? - attributes << { content_block_attributes: [:id] + content_block_attributes + content_block_attributes_for(params[:content_block_type]) + [ :_destroy ] } + content_block_attributes = ::Smithy::ContentBlocks::Registry.content_blocks.inject([]) do |association_attributes, content_block_type| + association_attributes += nested_content_block_attributes_for(content_block_type) end + attributes << { content_block_attributes: content_block_attributes + [:id, :_destroy] } if content_block_attributes.present? attributes end @@ -68,23 +68,35 @@ def template_container_attributes [ :name, :position ] end - def content_block_attributes_for(content_block_type) - klass = content_block_type.safe_constantize || "Smithy::#{content_block_type}".safe_constantize - content_block_attributes += klass.column_names.delete_if { |n| n.to_s.presence_in %w(id updated_at created_at) }.map(&:to_sym) - klass.reflections.delete_if{|k,v| k.to_s.presence_in %w(id page_contents pages) }.each do |name,association| - association_attributes << {"#{name}_attributes".to_sym => association.klass.column_names.delete_if { |n| n.to_s.presence_in %w(updated_at created_at) }.map(&:to_sym) + [:_destroy] } + private + def content_block_attributes_for(content_block_type) + attributes_method = "#{content_block_type.underscore}_attributes".to_sym + if self.respond_to?(attributes_method) + public_send(attributes_method) + else + klass = "Smithy::#{content_block_type.camelize}".safe_constantize || content_block_type.camelize.safe_constantize + klass.present? ? klass.column_names.delete_if { |n| n.to_s.presence_in %w(id updated_at created_at) }.map(&:to_sym) : [] + end + end + + def nested_content_block_attributes_for(content_block_type) + content_block_attributes = content_block_attributes_for(content_block_type) + association_attributes = [] + reflected_content_block_associations(content_block_type).each do |reflection| + name, association = reflection + next if association.active_record.nested_attributes_options[name.to_sym].blank? + allowed_attributes = content_block_attributes_for(content_block_type) + [:id] + allowed_attributes += [:_destroy] if association.active_record.nested_attributes_options[name.to_sym][:allow_destroy] == true + association_attributes << {"#{name}_attributes".to_sym => allowed_attributes } + end + content_block_attributes += association_attributes + content_block_attributes.uniq + end + + def reflected_content_block_associations(content_block_type) + klass = "Smithy::#{content_block_type}".safe_constantize || content_block_type.safe_constantize + reflections = klass.reflections.delete_if{|k,v| k.to_s.presence_in %w(id page_contents pages) } end - # ContentBlocks::Registry.content_blocks.inject([]) do |association_attributes, content_block_type| - # klass = content_block_type.safe_constantize || "Smithy::#{content_block_type}".safe_constantize - # content_block_attributes += klass.column_names.delete_if { |n| n.to_s.presence_in %w(id updated_at created_at) }.map(&:to_sym) - # klass.reflections.delete_if{|k,v| k.to_s.presence_in %w(id page_contents pages) }.each do |name,association| - # association_attributes << {"#{name}_attributes".to_sym => association.klass.column_names.delete_if { |n| n.to_s.presence_in %w(updated_at created_at) }.map(&:to_sym) + [:_destroy] } - # end - # end - end - def nested_attributes(object_name) - send("#{object_name}_attributes".to_sym) + [ :id, :_destroy ] - end end end diff --git a/spec/factories/smithy_assets.rb b/spec/factories/smithy_assets.rb index 9d49557..3f89dbf 100644 --- a/spec/factories/smithy_assets.rb +++ b/spec/factories/smithy_assets.rb @@ -2,5 +2,7 @@ FactoryGirl.define do factory :asset, :class => 'Smithy::Asset' do + name { FFaker::Lorem.words(2).join(' ') } + file { File.open Smithy::Engine.root.join('spec', 'fixtures', 'assets', 'treats-and_stuff.png') } end end diff --git a/spec/models/smithy/permitted_params_spec.rb b/spec/models/smithy/permitted_params_spec.rb index 4ec2093..3684975 100644 --- a/spec/models/smithy/permitted_params_spec.rb +++ b/spec/models/smithy/permitted_params_spec.rb @@ -42,7 +42,7 @@ let(:setting_attributes) { [ :name, :value ] } let(:template_attributes) { [ :name, :content, :template_type ] } let(:template_container_attributes) { [ :name, :position ] } - let(:extra_nested_attribtues) { [:id, :_destroy] } + let(:extra_nested_attributes) { [:_destroy] } describe "asset attributes" do it_should_behave_like "returning permitted_params" do @@ -75,15 +75,46 @@ end end describe "page attributes" do + # page allowed_attributes need to include all of the content_attributes, including the nested content_block_attributes it_should_behave_like "returning permitted_params" do - let(:param_name) { "page" } - let(:allowed_attributes) { page_attributes << { contents_attributes: page_content_attributes + extra_nested_attribtues } } + let(:param_name) { "page" } + let(:allowed_attributes) do + contents_attributes = page_content_attributes + content_block_attributes = content_attributes + image_attributes + page_list_attributes + [:id, :_destroy] + contents_attributes << { content_block_attributes: content_block_attributes } + contents_attributes += [:id, :_destroy] + page_attributes << { contents_attributes: contents_attributes } + end end end + # page_content allowed_attributes need to include all of the nested content_block_attributes describe "page_content attributes" do it_should_behave_like "returning permitted_params" do let(:param_name) { "page_content" } - let(:allowed_attributes) { page_content_attributes } + let(:allowed_attributes) do + allowed_attributes = page_content_attributes + # the default content blocks pieces + content_block_attributes = content_attributes + image_attributes + page_list_attributes + [:id, :_destroy] + allowed_attributes << {content_block_attributes: content_block_attributes } + allowed_attributes + end + end + context "with #content_block_type" do + it_should_behave_like "returning permitted_params" do + let(:param_name) { "page_content" } + let(:attributes) do + attributes = FactoryGirl.build(param, page: Smithy::Page.first).attributes.select{|k, v| page_content_attributes.include?(k.to_sym) } + attributes[:content_block_attributes] = FactoryGirl.build(:content).attributes.select{|k,v| (content_attributes + extra_nested_attributes + [:id]).include?(k.to_sym) } + ActionController::Parameters.new(attributes) + end + let(:allowed_attributes) do + allowed_attributes = page_content_attributes + # the default content blocks pieces + content_block_attributes = content_attributes + image_attributes + page_list_attributes + [:id, :_destroy] + allowed_attributes << {content_block_attributes: content_block_attributes } + allowed_attributes + end + end end end describe "page_list attributes" do @@ -112,6 +143,6 @@ end def fetch_attributes(model) - ActionController::Parameters.new(attributes_for(model)) + ActionController::Parameters.new(FactoryGirl.build(model)) end end