From 9d134599b22a28632ecf9bf64a16dea9ded1f6f8 Mon Sep 17 00:00:00 2001 From: dinedine Date: Thu, 20 May 2010 01:42:19 +0200 Subject: [PATCH] first bricks of the CustomFields plugin --- app/models/asset_collection.rb | 3 + config/initializers/custom_fields.rb | 78 ------- spec/models/asset_collections_spec.rb | 213 ++++++++---------- vendor/plugins/custom_fields/MIT-LICENSE | 20 ++ vendor/plugins/custom_fields/README | 13 ++ vendor/plugins/custom_fields/Rakefile | 23 ++ vendor/plugins/custom_fields/init.rb | 2 + vendor/plugins/custom_fields/install.rb | 1 + .../custom_fields/lib/custom_fields.rb | 16 ++ .../lib/custom_fields/custom_fields_for.rb | 40 ++++ .../mongoid/associations/embeds_many.rb | 29 +++ .../mongoid/associations/options.rb | 10 + .../extensions/mongoid/document.rb | 28 +++ vendor/plugins/custom_fields/uninstall.rb | 1 + 14 files changed, 282 insertions(+), 195 deletions(-) delete mode 100644 config/initializers/custom_fields.rb create mode 100644 vendor/plugins/custom_fields/MIT-LICENSE create mode 100644 vendor/plugins/custom_fields/README create mode 100644 vendor/plugins/custom_fields/Rakefile create mode 100644 vendor/plugins/custom_fields/init.rb create mode 100644 vendor/plugins/custom_fields/install.rb create mode 100644 vendor/plugins/custom_fields/lib/custom_fields.rb create mode 100644 vendor/plugins/custom_fields/lib/custom_fields/custom_fields_for.rb create mode 100644 vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/embeds_many.rb create mode 100644 vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/options.rb create mode 100644 vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/document.rb create mode 100644 vendor/plugins/custom_fields/uninstall.rb diff --git a/app/models/asset_collection.rb b/app/models/asset_collection.rb index 182f093f..a1f4908f 100644 --- a/app/models/asset_collection.rb +++ b/app/models/asset_collection.rb @@ -1,6 +1,7 @@ class AssetCollection include Mongoid::Document include Mongoid::Timestamps + include Mongoid::CustomFields ## fields ## field :name, :type => String @@ -15,6 +16,8 @@ class AssetCollection embeds_many :asset_fields # FIXME (custom fields) ## behaviours ## + custom_fields_for :assets + accepts_nested_attributes_for :asset_fields, :allow_destroy => true # FIXME (custom fields) ## callbacks ## diff --git a/config/initializers/custom_fields.rb b/config/initializers/custom_fields.rb deleted file mode 100644 index 5060ce00..00000000 --- a/config/initializers/custom_fields.rb +++ /dev/null @@ -1,78 +0,0 @@ -# encoding: utf-8 -module Mongoid #:nodoc: - module Associations #:nodoc: - class Options #:nodoc: - def custom_fields - @attributes[:custom_fields] == true - end - end - end -end - -# encoding: utf-8 -module Mongoid #:nodoc: - module Associations #:nodoc: - class EmbedsMany < Proxy - def build_with_custom_field_settings(attrs = {}, type = nil) - document = build_without_custom_field_settings(attrs, type) - if self.target_custom_field_association? - document.send(:set_unique_name!) - document.send(:set_alias) - end - document - end - - alias_method_chain :build, :custom_field_settings - - def target_custom_field_association? - return unless @association_name.ends_with?('_fields') - - target_name = @association_name.gsub(/_fields$/, '').pluralize - # puts "target_name = #{target_name} / #{@parent.associations.key?(target_name).inspect} / #{@parent.inspect} / #{@parent.associations.inspect}" - if @parent.associations.key?(target_name) - @parent.associations[target_name].options.custom_fields - end - end - - end - - end -end - -# encoding: utf-8 -module Mongoid #:nodoc: - module Document - module InstanceMethods - def parentize_with_custom_fields(object, association_name) - # puts "...parentize_with_custom_fields...#{self.inspect} - #{object.inspect} - #{association_name}" - parentize_without_custom_fields(object, association_name) - - if self.custom_fields?(object, association_name) - # puts "custom fields = #{object.asset_fields.inspect}" - # puts "((((((((" - - # puts " custom fields = #{self.custom_fields_association_name(association_name).inspect} / #{object.send(self.custom_fields_association_name(association_name)).inspect}" - - [*object.send(self.custom_fields_association_name(association_name))].each do |field| - # puts "field = #{field.inspect}" - # self.class.send(:set_field, field.name, { :type => field.field_type }) - field.apply(self, association_name) - end - # puts "))))))))" - end - end - - alias_method_chain :parentize, :custom_fields - - def custom_fields_association_name(association_name) - "#{association_name.singularize}_fields".to_sym - end - - def custom_fields?(object, association_name) - object.respond_to?(custom_fields_association_name(association_name)) && - object.associations[association_name] && - object.associations[association_name].options.custom_fields - end - end - end -end \ No newline at end of file diff --git a/spec/models/asset_collections_spec.rb b/spec/models/asset_collections_spec.rb index 39564a27..5f45661f 100644 --- a/spec/models/asset_collections_spec.rb +++ b/spec/models/asset_collections_spec.rb @@ -15,133 +15,112 @@ describe AssetCollection do puts "first field index = #{@collection.asset_fields.first._index}" end - # context 'define core attributes' do - # - # it 'should have an unique name' do - # @collection.asset_fields.first._name.should == "custom_field_1" - # @collection.asset_fields.last._name.should == "custom_field_2" - # end - # - # it 'should have an unique alias' do - # @collection.asset_fields.first._alias.should == "description" - # @collection.asset_fields.last._alias.should == "active" - # end - # - # end - # - # context 'build and save' do - # - # it 'should build asset' do - # asset = @collection.assets.build - # lambda { - # asset.description - # asset.active - # }.should_not raise_error - # end - # - # it 'should assign values to newly built asset' do - # asset = build_asset(@collection) - # asset.description.should == 'Lorem ipsum' - # asset.active.should == true - # end - # - # it 'should save asset' do - # asset = build_asset(@collection) - # asset.save and @collection.reload - # asset = @collection.assets.first - # asset.description.should == 'Lorem ipsum' - # asset.active.should == true - # end - # - # it 'should not modify assets from another collection' do - # asset = build_asset(@collection) - # asset.save and @collection.reload - # new_collection = AssetCollection.new - # lambda { new_collection.assets.build.description }.should raise_error - # end - # - # end - # - # context 'modifying fields' do - # - # before(:each) do - # @asset = build_asset(@collection).save - # end - # - # it 'should add new field' do - # @collection.asset_fields.build :label => 'Active at', :name => 'active_at', :kind => 'Date' - # @collection.upsert(false) - # @collection.reload - # asset = @collection.assets.first - # lambda { asset.active_at }.should_not raise_error - # end - # - # it 'should remove field' do - # @collection.asset_fields.clear - # @collection.upsert(false) - # @collection.reload - # asset = @collection.assets.first - # lambda { asset.active }.should raise_error - # end - # - # it 'should rename field label' do - # @collection.asset_fields.first.label = 'Simple description' - # @collection.asset_fields.first._alias = nil - # @collection.upsert(false) - # @collection.reload - # asset = @collection.assets.first - # asset.simple_description.should == 'Lorem ipsum' - # end - # - # end + context 'define core attributes' do + + it 'should have an unique name' do + @collection.asset_fields.first._name.should == "custom_field_1" + @collection.asset_fields.last._name.should == "custom_field_2" + end + + it 'should have an unique alias' do + @collection.asset_fields.first._alias.should == "description" + @collection.asset_fields.last._alias.should == "active" + end + + end + + context 'build and save' do + + it 'should build asset' do + asset = @collection.assets.build + lambda { + asset.description + asset.active + }.should_not raise_error + end + + it 'should assign values to newly built asset' do + asset = build_asset(@collection) + asset.description.should == 'Lorem ipsum' + asset.active.should == true + end + + it 'should save asset' do + asset = build_asset(@collection) + asset.save and @collection.reload + asset = @collection.assets.first + asset.description.should == 'Lorem ipsum' + asset.active.should == true + end + + it 'should not modify assets from another collection' do + asset = build_asset(@collection) + asset.save and @collection.reload + new_collection = AssetCollection.new + lambda { new_collection.assets.build.description }.should raise_error + end + + end + + context 'modifying fields' do + + before(:each) do + @asset = build_asset(@collection).save + end + + it 'should add new field' do + @collection.asset_fields.build :label => 'Active at', :name => 'active_at', :kind => 'Date' + @collection.upsert(false) + @collection.reload + asset = @collection.assets.first + lambda { asset.active_at }.should_not raise_error + end + + it 'should remove field' do + @collection.asset_fields.clear + @collection.upsert(false) + @collection.reload + asset = @collection.assets.first + lambda { asset.active }.should raise_error + end + + it 'should rename field label' do + @collection.asset_fields.first.label = 'Simple description' + @collection.asset_fields.first._alias = nil + @collection.upsert(false) + @collection.reload + asset = @collection.assets.first + asset.simple_description.should == 'Lorem ipsum' + end + + end context 'managing from hash' do before(:each) do - # @collection.asset_fields.clear - # @collection.stubs(:validate).returns(true) - # @collection.stubs(:valid?).returns(true) - @collection.site = Factory(:site) + site = Factory.build(:site) + Site.stubs(:find).returns(site) + @collection.site = site end - # it 'should add new field' do - # @collection.asset_fields.clear - # @collection.asset_fields_attributes = { 'NEW_RECORD' => { 'label' => 'Tagline', 'kind' => 'String' } } - # @collection.asset_fields.first.label.should == 'Tagline' - # end - # - # it 'should add new field' do - # @collection.asset_fields.build :label => 'Title' - # @collection.asset_fields_attributes = { '0' => { 'label' => 'A title', 'kind' => 'String' }, '-1' => { 'label' => 'Tagline', 'kind' => 'String' } } - # @collection.asset_fields.size.should == 2 - # @collection.asset_fields.first.label.should == 'A title' - # @collection.asset_fields.last.label.should == 'Tagline' - # end - # - # it 'should rename field' - - it 'should remove field' do + it 'should add new field' do + @collection.asset_fields.clear + @collection.asset_fields.build :label => 'Title' + @collection.asset_fields_attributes = { '0' => { 'label' => 'A title', 'kind' => 'String' }, '-1' => { 'label' => 'Tagline', 'kind' => 'String' } } + @collection.asset_fields.size.should == 2 + @collection.asset_fields.first.label.should == 'A title' + @collection.asset_fields.last.label.should == 'Tagline' + end + + it 'should update/remove fields' do @collection.asset_fields.build :label => 'Title', :kind => 'String' - # puts @collection.asset_fields.collect { |d| d._index }.inspect - @collection.save - @collection = AssetCollection.first - foo = @collection.asset_fields - @collection.asset_fields.size.should == 3 + @collection.save; @collection = AssetCollection.first @collection.update_attributes(:asset_fields_attributes => { - # @collection.asset_fields_attributes = { - '0' => { 'label' => 'My Description', 'kind' => 'Text', '_destroy' => "1", "id" => foo[0].id }, - '1' => { 'label' => 'Active', 'kind' => 'Boolean', '_destroy' => "0", "id" => foo[1].id }, - '2' => { 'label' => 'My Title !', 'kind' => 'String', "id" => foo[2].id } - # } + '0' => { 'label' => 'My Description', 'kind' => 'Text', '_destroy' => "1" }, + '1' => { 'label' => 'Active', 'kind' => 'Boolean', '_destroy' => "0" }, + '2' => { 'label' => 'My Title !', 'kind' => 'String' } }) - - puts @collection.raw_attributes.inspect - - # @collection.save @collection = AssetCollection.first - # @collection.reload - puts "________________ #{@collection.asset_fields.class.inspect}" - puts @collection.asset_fields.inspect @collection.asset_fields.size.should == 1 @collection.asset_fields.first.label.should == 'My Title !' end diff --git a/vendor/plugins/custom_fields/MIT-LICENSE b/vendor/plugins/custom_fields/MIT-LICENSE new file mode 100644 index 00000000..ec4ddd4c --- /dev/null +++ b/vendor/plugins/custom_fields/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010 [name of plugin creator] + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/plugins/custom_fields/README b/vendor/plugins/custom_fields/README new file mode 100644 index 00000000..99cd98b0 --- /dev/null +++ b/vendor/plugins/custom_fields/README @@ -0,0 +1,13 @@ +CustomField +=========== + +Introduction goes here. + + +Example +======= + +Example goes here. + + +Copyright (c) 2010 [name of plugin creator], released under the MIT license diff --git a/vendor/plugins/custom_fields/Rakefile b/vendor/plugins/custom_fields/Rakefile new file mode 100644 index 00000000..6276c122 --- /dev/null +++ b/vendor/plugins/custom_fields/Rakefile @@ -0,0 +1,23 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the custom_field plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the custom_field plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'CustomField' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end \ No newline at end of file diff --git a/vendor/plugins/custom_fields/init.rb b/vendor/plugins/custom_fields/init.rb new file mode 100644 index 00000000..6f69f32d --- /dev/null +++ b/vendor/plugins/custom_fields/init.rb @@ -0,0 +1,2 @@ +# Include hook code here +require File.dirname(__FILE__) + '/lib/custom_fields' \ No newline at end of file diff --git a/vendor/plugins/custom_fields/install.rb b/vendor/plugins/custom_fields/install.rb new file mode 100644 index 00000000..f7732d37 --- /dev/null +++ b/vendor/plugins/custom_fields/install.rb @@ -0,0 +1 @@ +# Install hook code here diff --git a/vendor/plugins/custom_fields/lib/custom_fields.rb b/vendor/plugins/custom_fields/lib/custom_fields.rb new file mode 100644 index 00000000..ca506184 --- /dev/null +++ b/vendor/plugins/custom_fields/lib/custom_fields.rb @@ -0,0 +1,16 @@ +$:.unshift File.expand_path(File.dirname(__FILE__)) + +require 'custom_fields/extensions/mongoid/associations/options' +require 'custom_fields/extensions/mongoid/associations/embeds_many' +require 'custom_fields/extensions/mongoid/document' +require 'custom_fields/custom_fields_for' + +module Mongoid + module CustomFields + extend ActiveSupport::Concern + included do + puts "loading from CustomFieldsFor" + include ::CustomFields::CustomFieldsFor + end + end +end diff --git a/vendor/plugins/custom_fields/lib/custom_fields/custom_fields_for.rb b/vendor/plugins/custom_fields/lib/custom_fields/custom_fields_for.rb new file mode 100644 index 00000000..f1d72d85 --- /dev/null +++ b/vendor/plugins/custom_fields/lib/custom_fields/custom_fields_for.rb @@ -0,0 +1,40 @@ +module CustomFields + + module CustomFieldsFor + + def self.included(base) + base.extend(ClassMethods) + end + + # Enhance an embedded collection by providing methods to manage custom fields + # + # class Person + # embeds_many :addresses + # custom_fields_for :addresses + # end + # + # class Address + # embedded_in :person, :inverse_of => :addresses + # field :street, String + # end + # + # person.address_fields.build :label => 'Floor', :kind => 'String' + # + # person.addresses.build :street => 'Laflin Street', :floor => '42' + # + module ClassMethods + + def custom_fields_for(collection_name) + puts "settings custom fields for #{collection_name}" + + class_eval <<-EOV + + + EOV + end + + end + + end + +end \ No newline at end of file diff --git a/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/embeds_many.rb b/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/embeds_many.rb new file mode 100644 index 00000000..73f52086 --- /dev/null +++ b/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/embeds_many.rb @@ -0,0 +1,29 @@ +# encoding: utf-8 +module Mongoid #:nodoc: + module Associations #:nodoc: + class EmbedsMany < Proxy + def build_with_custom_field_settings(attrs = {}, type = nil) + document = build_without_custom_field_settings(attrs, type) + if self.target_custom_field_association? + document.send(:set_unique_name!) + document.send(:set_alias) + end + document + end + + alias_method_chain :build, :custom_field_settings + + def target_custom_field_association? + return unless @association_name.ends_with?('_fields') + + target_name = @association_name.gsub(/_fields$/, '').pluralize + # puts "target_name = #{target_name} / #{@parent.associations.key?(target_name).inspect} / #{@parent.inspect} / #{@parent.associations.inspect}" + if @parent.associations.key?(target_name) + @parent.associations[target_name].options.custom_fields + end + end + + end + + end +end \ No newline at end of file diff --git a/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/options.rb b/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/options.rb new file mode 100644 index 00000000..f13c81ff --- /dev/null +++ b/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/associations/options.rb @@ -0,0 +1,10 @@ +# encoding: utf-8 +module Mongoid #:nodoc: + module Associations #:nodoc: + class Options #:nodoc: + def custom_fields + @attributes[:custom_fields] == true + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/document.rb b/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/document.rb new file mode 100644 index 00000000..833fae47 --- /dev/null +++ b/vendor/plugins/custom_fields/lib/custom_fields/extensions/mongoid/document.rb @@ -0,0 +1,28 @@ +# encoding: utf-8 +module Mongoid #:nodoc: + module Document + module InstanceMethods + def parentize_with_custom_fields(object, association_name) + parentize_without_custom_fields(object, association_name) + + if self.custom_fields?(object, association_name) + object.send(self.custom_fields_association_name(association_name)).each do |field| + field.apply(self, association_name) + end + end + end + + alias_method_chain :parentize, :custom_fields + + def custom_fields_association_name(association_name) + "#{association_name.singularize}_fields".to_sym + end + + def custom_fields?(object, association_name) + object.respond_to?(custom_fields_association_name(association_name)) && + object.associations[association_name] && + object.associations[association_name].options.custom_fields + end + end + end +end \ No newline at end of file diff --git a/vendor/plugins/custom_fields/uninstall.rb b/vendor/plugins/custom_fields/uninstall.rb new file mode 100644 index 00000000..97383334 --- /dev/null +++ b/vendor/plugins/custom_fields/uninstall.rb @@ -0,0 +1 @@ +# Uninstall hook code here