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 class AssetCollection
include Mongoid::Document include Mongoid::Document
include Mongoid::Timestamps include Mongoid::Timestamps
include Mongoid::CustomFields
## fields ## ## fields ##
field :name, :type => String field :name, :type => String
@ -15,6 +16,8 @@ class AssetCollection
embeds_many :asset_fields # FIXME (custom fields) embeds_many :asset_fields # FIXME (custom fields)
## behaviours ## ## behaviours ##
custom_fields_for :assets
accepts_nested_attributes_for :asset_fields, :allow_destroy => true # FIXME (custom fields) accepts_nested_attributes_for :asset_fields, :allow_destroy => true # FIXME (custom fields)
## callbacks ## ## 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}" puts "first field index = #{@collection.asset_fields.first._index}"
end end
# context 'define core attributes' do context 'define core attributes' do
#
# it 'should have an unique name' do it 'should have an unique name' do
# @collection.asset_fields.first._name.should == "custom_field_1" @collection.asset_fields.first._name.should == "custom_field_1"
# @collection.asset_fields.last._name.should == "custom_field_2" @collection.asset_fields.last._name.should == "custom_field_2"
# end end
#
# it 'should have an unique alias' do it 'should have an unique alias' do
# @collection.asset_fields.first._alias.should == "description" @collection.asset_fields.first._alias.should == "description"
# @collection.asset_fields.last._alias.should == "active" @collection.asset_fields.last._alias.should == "active"
# end end
#
# end end
#
# context 'build and save' do context 'build and save' do
#
# it 'should build asset' do it 'should build asset' do
# asset = @collection.assets.build asset = @collection.assets.build
# lambda { lambda {
# asset.description asset.description
# asset.active asset.active
# }.should_not raise_error }.should_not raise_error
# end end
#
# it 'should assign values to newly built asset' do it 'should assign values to newly built asset' do
# asset = build_asset(@collection) asset = build_asset(@collection)
# asset.description.should == 'Lorem ipsum' asset.description.should == 'Lorem ipsum'
# asset.active.should == true asset.active.should == true
# end end
#
# it 'should save asset' do it 'should save asset' do
# asset = build_asset(@collection) asset = build_asset(@collection)
# asset.save and @collection.reload asset.save and @collection.reload
# asset = @collection.assets.first asset = @collection.assets.first
# asset.description.should == 'Lorem ipsum' asset.description.should == 'Lorem ipsum'
# asset.active.should == true asset.active.should == true
# end end
#
# it 'should not modify assets from another collection' do it 'should not modify assets from another collection' do
# asset = build_asset(@collection) asset = build_asset(@collection)
# asset.save and @collection.reload asset.save and @collection.reload
# new_collection = AssetCollection.new new_collection = AssetCollection.new
# lambda { new_collection.assets.build.description }.should raise_error lambda { new_collection.assets.build.description }.should raise_error
# end end
#
# end end
#
# context 'modifying fields' do context 'modifying fields' do
#
# before(:each) do before(:each) do
# @asset = build_asset(@collection).save @asset = build_asset(@collection).save
# end end
#
# it 'should add new field' do it 'should add new field' do
# @collection.asset_fields.build :label => 'Active at', :name => 'active_at', :kind => 'Date' @collection.asset_fields.build :label => 'Active at', :name => 'active_at', :kind => 'Date'
# @collection.upsert(false) @collection.upsert(false)
# @collection.reload @collection.reload
# asset = @collection.assets.first asset = @collection.assets.first
# lambda { asset.active_at }.should_not raise_error lambda { asset.active_at }.should_not raise_error
# end end
#
# it 'should remove field' do it 'should remove field' do
# @collection.asset_fields.clear @collection.asset_fields.clear
# @collection.upsert(false) @collection.upsert(false)
# @collection.reload @collection.reload
# asset = @collection.assets.first asset = @collection.assets.first
# lambda { asset.active }.should raise_error lambda { asset.active }.should raise_error
# end end
#
# it 'should rename field label' do it 'should rename field label' do
# @collection.asset_fields.first.label = 'Simple description' @collection.asset_fields.first.label = 'Simple description'
# @collection.asset_fields.first._alias = nil @collection.asset_fields.first._alias = nil
# @collection.upsert(false) @collection.upsert(false)
# @collection.reload @collection.reload
# asset = @collection.assets.first asset = @collection.assets.first
# asset.simple_description.should == 'Lorem ipsum' asset.simple_description.should == 'Lorem ipsum'
# end end
#
# end end
context 'managing from hash' do context 'managing from hash' do
before(:each) do before(:each) do
# @collection.asset_fields.clear site = Factory.build(:site)
# @collection.stubs(:validate).returns(true) Site.stubs(:find).returns(site)
# @collection.stubs(:valid?).returns(true) @collection.site = site
@collection.site = Factory(:site)
end end
# it 'should add new field' do it 'should add new field' do
# @collection.asset_fields.clear @collection.asset_fields.clear
# @collection.asset_fields_attributes = { 'NEW_RECORD' => { 'label' => 'Tagline', 'kind' => 'String' } } @collection.asset_fields.build :label => 'Title'
# @collection.asset_fields.first.label.should == 'Tagline' @collection.asset_fields_attributes = { '0' => { 'label' => 'A title', 'kind' => 'String' }, '-1' => { 'label' => 'Tagline', 'kind' => 'String' } }
# end @collection.asset_fields.size.should == 2
# @collection.asset_fields.first.label.should == 'A title'
# it 'should add new field' do @collection.asset_fields.last.label.should == 'Tagline'
# @collection.asset_fields.build :label => 'Title' end
# @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 update/remove fields' do
@collection.asset_fields.build :label => 'Title', :kind => 'String' @collection.asset_fields.build :label => 'Title', :kind => 'String'
# puts @collection.asset_fields.collect { |d| d._index }.inspect @collection.save; @collection = AssetCollection.first
@collection.save
@collection = AssetCollection.first
foo = @collection.asset_fields
@collection.asset_fields.size.should == 3
@collection.update_attributes(:asset_fields_attributes => { @collection.update_attributes(:asset_fields_attributes => {
# @collection.asset_fields_attributes = { '0' => { 'label' => 'My Description', 'kind' => 'Text', '_destroy' => "1" },
'0' => { 'label' => 'My Description', 'kind' => 'Text', '_destroy' => "1", "id" => foo[0].id }, '1' => { 'label' => 'Active', 'kind' => 'Boolean', '_destroy' => "0" },
'1' => { 'label' => 'Active', 'kind' => 'Boolean', '_destroy' => "0", "id" => foo[1].id }, '2' => { 'label' => 'My Title !', 'kind' => 'String' }
'2' => { 'label' => 'My Title !', 'kind' => 'String', "id" => foo[2].id }
# }
}) })
puts @collection.raw_attributes.inspect
# @collection.save
@collection = AssetCollection.first @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.size.should == 1
@collection.asset_fields.first.label.should == 'My Title !' @collection.asset_fields.first.label.should == 'My Title !'
end 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