first bricks of the CustomFields plugin

This commit is contained in:
dinedine 2010-05-20 01:42:19 +02:00
parent 05a93cb5c1
commit 9d134599b2
14 changed files with 282 additions and 195 deletions

View File

@ -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 ##

View File

@ -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

View File

@ -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

View File

@ -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.

13
vendor/plugins/custom_fields/README vendored Normal file
View File

@ -0,0 +1,13 @@
CustomField
===========
Introduction goes here.
Example
=======
Example goes here.
Copyright (c) 2010 [name of plugin creator], released under the MIT license

23
vendor/plugins/custom_fields/Rakefile vendored Normal file
View File

@ -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

2
vendor/plugins/custom_fields/init.rb vendored Normal file
View File

@ -0,0 +1,2 @@
# Include hook code here
require File.dirname(__FILE__) + '/lib/custom_fields'

View File

@ -0,0 +1 @@
# Install hook code here

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
# Uninstall hook code here