Skip to content

Commit

Permalink
Allow multiple levels of nesting
Browse files Browse the repository at this point in the history
  • Loading branch information
mtaylor committed Oct 11, 2012
1 parent dec583c commit afaeeda
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 30 deletions.
43 changes: 24 additions & 19 deletions app/filters/tim/user_keys_filter.rb
Expand Up @@ -4,49 +4,54 @@
module Tim
class UserKeysFilter

@@user_keys = { "base_image" => "base_image_attributes",
"image_versions" => "image_versions_attributes",
"image_version" => "image_version_attributes",
"target_images" => "target_image_attributes",
"target_image" => "target_image_attributes",
"provider_images" => "provider_images_attributes",
"provider_image" => "provider_image_attributes",
"template" => "template_attributes" }
@@user_keys = YAML.load(File.read(File.join(Tim::Engine.root, "config", "user_keys.yml")))

def self.before(controller)

begin
resource_name = controller.controller_name.singularize.to_sym
set_template_params(resource_name, controller)
controller.params[resource_name] = replace_user_keys(controller.params[resource_name])
@controller = controller
resource_name = @controller.controller_name.singularize.to_sym
set_template_params(resource_name)
@controller.params[resource_name] = replace_user_keys(@controller.params[resource_name], @@user_keys[resource_name])
rescue => e
controller.head :unprocessable_entity
@controller.head :unprocessable_entity
end
end

# Replaces all instances of user keys with those defined in @@user_keys
# Supports N levels of nested maps.
def self.replace_user_keys(map)
def self.replace_user_keys(map, user_keys)
modified_map = map.clone
map.each_pair do |key, value|
if @@user_keys.has_key? key
# Sets the full template XML in the template.xml attribute
if key == "template" || key == :template
modified_map[key] = { :xml => template_xml }
end

if user_keys.has_key? key
if map[key].instance_of? Hash
# FIXME Using recursion in this way increases heap memory usage.
# If we decide to stick with this approach a more memory efficient
# implementation should be considered.
modified_map[key] = replace_user_keys(map[key])
modified_map[key] = replace_user_keys(map[key], user_keys)
elsif map[key].instance_of? Array
modified_map[key] = map[key].collect { |v| replace_user_keys(v, user_keys)}
end
modified_map[@@user_keys[key]] = modified_map.delete(key)
modified_map[user_keys[key]] = modified_map.delete(key)
end
end
modified_map
end

def self.set_template_params(resource_name, controller)
# We are storing raw XML in the templates.xml attributes. Therefore we
# must retrieve the raw XML from the request body.
def self.set_template_params(resource_name)
if resource_name == :template
controller.params[:template] = { :xml => controller.request.body.read }
@controller.params[:template] = { :xml => template_xml }
end
end

def self.template_xml
::Nokogiri::XML(@controller.request.body.read).xpath("//template").to_xml
end
end
end
3 changes: 3 additions & 0 deletions app/views/tim/templates/_template.xml.haml
@@ -1,5 +1,8 @@
!!! XML
%template{:id => template.id, :href => template_url(template.id) }
!= template.xml_elements
%base_images
- template.base_images.each do |base_image|
= render :partial => 'tim/base_images/base_image_minimal', :locals => {:base_image => base_image}
- if controller.template_exists?("custom", "tim/templates", true)
= render :partial => 'tim/templates/custom', :locals => {:template => template}
26 changes: 26 additions & 0 deletions config/user_keys.yml
@@ -0,0 +1,26 @@
:template:
base_image: base_image_attributes

:base_image:
template: template_attributes
image_versions: image_versions_attributes
target_images: target_images_attributes
provider_images: provider_images_attributes

:image_version:
template: template_attributes
base_image: base_image_attributes
target_images: target_images_attributes
provider_images: provider_images_attributes

:target_image:
template: template_attributes
base_image: base_image_attributes
image_version: image_version_attributes
provider_images: provider_images_attributes

:provider_image:
template: template_attributes
base_image: base_image_attributes
image_version: image_version_attributes
target_image: target_image_attributes
2 changes: 1 addition & 1 deletion spec/controllers/templates_controller_spec.rb
Expand Up @@ -22,7 +22,7 @@ module Tim
response.code.should == "201"
template_xml = ::Nokogiri::XML::Document.parse(response.body)
template_xml.xpath("//template/*").to_xml
.should == template.xml_elements
.include?(template.xml_elements).should == true
template_xml.xpath("//template/@*").map { |node| node.name}
.should =~ ["id", "href"]
end
Expand Down
15 changes: 5 additions & 10 deletions spec/filters/user_keys_filter_spec.rb
Expand Up @@ -4,25 +4,20 @@ module Tim
describe UserKeysFilter do

before(:all) do |spec|
@user_keys = UserKeysFilter.class_variable_get(:@@user_keys)
UserKeysFilter.class_variable_set(:@@user_keys, {:k1 => :a1, :k2 => :a2})
end

after(:all) do |spec|
UserKeysFilter.class_variable_set(:@@user_keys, @user_keys)
@user_keys = {:k1 => :a1, :k2 => :a2}
end

describe "replace user keys" do
it 'should replace user keys with respective specified alternate' do
hash = UserKeysFilter.replace_user_keys({:k1 => :v1, :k2 => :v2})
hash = UserKeysFilter.replace_user_keys({:k1 => :v1, :k2 => :v2}, @user_keys)
hash[:a1].should == :v1
hash[:a2].should == :v2
hash.has_key?(:k1).should == false
hash.has_key?(:k2).should == false
end

it 'should replace nested user keys' do
hash = UserKeysFilter.replace_user_keys({:k1 => {:k2 => :v2}})
hash = UserKeysFilter.replace_user_keys({:k1 => {:k2 => :v2}}, @user_keys)
hash[:a1].should == {:a2 => :v2}
end
end
Expand All @@ -33,8 +28,8 @@ module Tim
controller.stub(:controller_name).and_return "resources"
controller.stub(:params).and_return({:resource => {:k1 => {:k2 => :v2}}})

UserKeysFilter.should_receive(:replace_user_keys).with({:k1 => {:k2 => :v2}})
UserKeysFilter.stub(:replace_user_keys).and_return({:a1 => {:a2 => :v2}})
UserKeysFilter.should_receive(:replace_user_keys).with({:k1 => {:k2 => :v2}}, nil)
UserKeysFilter.stub(:replace_user_keys).and_return({:a1 => {:a2 => :v2}}, nil)

UserKeysFilter.before(controller)
end
Expand Down

0 comments on commit afaeeda

Please sign in to comment.