fakecrm 0.9.9.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +76 -0
  7. data/Rakefile +113 -0
  8. data/bin/fakecrm +37 -0
  9. data/fakecrm.gemspec +34 -0
  10. data/lib/fakecrm/application.rb +85 -0
  11. data/lib/fakecrm/configuration.rb +8 -0
  12. data/lib/fakecrm/drop.rb +59 -0
  13. data/lib/fakecrm/embedded.rb +32 -0
  14. data/lib/fakecrm/fetch.rb +139 -0
  15. data/lib/fakecrm/initialize.rb +16 -0
  16. data/lib/fakecrm/localized_dm.rb +12 -0
  17. data/lib/fakecrm/resource/account.rb +33 -0
  18. data/lib/fakecrm/resource/activity.rb +57 -0
  19. data/lib/fakecrm/resource/contact.rb +51 -0
  20. data/lib/fakecrm/resource/custom_attribute.rb +20 -0
  21. data/lib/fakecrm/resource/custom_type.rb +96 -0
  22. data/lib/fakecrm/resource/event.rb +52 -0
  23. data/lib/fakecrm/resource/event_contact.rb +21 -0
  24. data/lib/fakecrm/resource/extensions/kinds.rb +26 -0
  25. data/lib/fakecrm/resource/extensions/type_extender.rb +42 -0
  26. data/lib/fakecrm/resource/extensions/type_extension.rb +55 -0
  27. data/lib/fakecrm/resource/mailing.rb +30 -0
  28. data/lib/fakecrm/resource/password.rb +17 -0
  29. data/lib/fakecrm/resource/role.rb +18 -0
  30. data/lib/fakecrm/resource/template.rb +41 -0
  31. data/lib/fakecrm/resource/views/resource_view.rb +90 -0
  32. data/lib/fakecrm/resources.rb +11 -0
  33. data/lib/fakecrm/server/accounts.rb +39 -0
  34. data/lib/fakecrm/server/activities.rb +39 -0
  35. data/lib/fakecrm/server/contacts.rb +118 -0
  36. data/lib/fakecrm/server/custom_types.rb +34 -0
  37. data/lib/fakecrm/server/event_contacts.rb +38 -0
  38. data/lib/fakecrm/server/events.rb +47 -0
  39. data/lib/fakecrm/server/mailings.rb +44 -0
  40. data/lib/fakecrm/server/roles.rb +44 -0
  41. data/lib/fakecrm/server/templates.rb +24 -0
  42. data/lib/fakecrm/server.rb +37 -0
  43. data/lib/fakecrm/version.rb +5 -0
  44. data/lib/fakecrm.rb +36 -0
  45. data/locales/de.yml +25 -0
  46. data/locales/en.yml +25 -0
  47. data/test/embedded/.gitignore +15 -0
  48. data/test/embedded/Gemfile +6 -0
  49. data/test/embedded/Rakefile +7 -0
  50. data/test/embedded/app/models/.gitkeep +0 -0
  51. data/test/embedded/config/application.rb +44 -0
  52. data/test/embedded/config/boot.rb +6 -0
  53. data/test/embedded/config/environment.rb +5 -0
  54. data/test/embedded/config/environments/development.rb +20 -0
  55. data/test/embedded/config/environments/test.rb +21 -0
  56. data/test/embedded/config/initializers/fakecrm.rb +8 -0
  57. data/test/embedded/config/initializers/secret_token.rb +7 -0
  58. data/test/embedded/config/initializers/session_store.rb +8 -0
  59. data/test/embedded/config/initializers/wrap_parameters.rb +14 -0
  60. data/test/embedded/config/locales/en.yml +5 -0
  61. data/test/embedded/config/routes.rb +2 -0
  62. data/test/embedded/config.ru +4 -0
  63. data/test/embedded/lib/assets/.gitkeep +0 -0
  64. data/test/embedded/lib/tasks/.gitkeep +0 -0
  65. data/test/embedded/log/.gitkeep +0 -0
  66. data/test/embedded/script/rails +6 -0
  67. metadata +301 -0
@@ -0,0 +1,33 @@
1
+ # -*- encoding : utf-8 -*-
2
+ #
3
+ module Fakecrm
4
+ class Account
5
+ include DataMapper::Resource
6
+
7
+ property :id, Serial
8
+ property :name, String, :required => true
9
+
10
+ property :account_group, String
11
+ property :country, String
12
+ property :extended_address, String
13
+ property :home_page, String
14
+ property :locality, String
15
+ property :merged_into_id, String
16
+ property :org_name_address, String
17
+ property :org_unit_address, String
18
+ property :phone, String
19
+ property :postalcode, String
20
+ property :region, String
21
+ property :street_address, String
22
+ property :want_geo_location, Boolean
23
+
24
+ property :created_at, DateTime
25
+ property :changed_at, DateTime
26
+ property :updated_at, DateTime
27
+ property :deleted_at, ParanoidDateTime
28
+
29
+ property :updated_by, String, :default => 'root'
30
+
31
+ end
32
+ end
33
+
@@ -0,0 +1,57 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/extensions/kinds'
3
+
4
+ require 'fakecrm/resource/account'
5
+ require 'fakecrm/resource/contact'
6
+ require 'fakecrm/resource/custom_type'
7
+
8
+ module Fakecrm
9
+ class Activity
10
+ include DataMapper::Resource
11
+
12
+ include Kinds
13
+
14
+ belongs_to :account, :required => false
15
+ belongs_to :contact, :required => false
16
+
17
+ property :id, Serial
18
+ property :title, String, :required => true
19
+ property :appointment_dtend_at, DateTime
20
+ property :appointment_dtstart_at, DateTime
21
+ property :appointment_location, String
22
+ property :email_cc, String
23
+ property :state, String
24
+ property :priority, Integer
25
+ property :tags, CommaSeparatedList
26
+ property :created_at, DateTime
27
+ property :changed_at, DateTime
28
+ property :updated_at, DateTime
29
+ property :deleted_at, ParanoidDateTime
30
+
31
+ property :comments, Json # FIXME: i'm not sure it will work
32
+
33
+ property :updated_by, String, :default => 'root'
34
+
35
+
36
+ validates_with_method :state, :method => :check_state
37
+ validates_presence_of :title
38
+
39
+ def custom_type
40
+ CustomType.get!(self.kind) unless self.kind.nil?
41
+ end
42
+
43
+ def check_state
44
+ custom_type = self.custom_type
45
+ if !custom_type.nil? && !custom_type.states.nil? && !custom_type.states.empty?
46
+ if self.state.nil? || !custom_type.states.include?(self.state)
47
+ # FIXME: localization
48
+ return [false, 'ist kein gültiger Wert']
49
+ end
50
+ end
51
+
52
+ return true
53
+ end
54
+
55
+ end
56
+ end
57
+
@@ -0,0 +1,51 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/account'
3
+
4
+ module Fakecrm
5
+ class Contact
6
+ include DataMapper::Resource
7
+
8
+ property :id, Serial
9
+ property :first_name, String
10
+ property :last_name, String, :required => true
11
+
12
+ property :email, String
13
+ property :login, String, :unique => true
14
+
15
+ belongs_to :account, :required => false
16
+ property :country, String
17
+ property :extended_address, String
18
+ property :fax, String
19
+ property :gender, Enum['M', 'F', 'N'], :required => true
20
+ property :job_title, String
21
+ property :language, String, :required => true
22
+ property :locality, String
23
+ property :merged_into_id, String
24
+ property :mobile_phone, String
25
+ property :name_prefix, String
26
+ property :org_name_address, String
27
+ property :org_unit_address, String
28
+ property :phone, String
29
+ property :postalcode, String
30
+ property :region, String
31
+ property :street_address, String
32
+ property :want_email, Boolean
33
+ property :want_geo_location, Boolean
34
+ property :want_phonecall, Boolean
35
+ property :want_snailmail, Boolean
36
+
37
+ property :role_names, CommaSeparatedList, :default => ''
38
+
39
+ property :created_at, DateTime
40
+ property :changed_at, DateTime # FIXME: doesn't work automatically
41
+ property :updated_at, DateTime
42
+ property :deleted_at, ParanoidDateTime
43
+
44
+ property :updated_by, String, :default => 'root'
45
+
46
+ before :save do
47
+ self.country = self.country.upcase unless self.country.nil?
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/custom_type'
3
+
4
+ module Fakecrm
5
+ class CustomAttribute
6
+ include DataMapper::Resource
7
+
8
+ belongs_to :custom_type
9
+
10
+ property :id, Serial
11
+ property :name, String, :required => true
12
+ property :title, String
13
+ property :type, Enum["string", "text", "enum", "multienum"], :required => true
14
+ property :mandatory, Boolean, :default => false
15
+ property :max_length, String, :default => 100
16
+ property :valid_values, CommaSeparatedList
17
+
18
+ end
19
+ end
20
+
@@ -0,0 +1,96 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/extensions/type_extender'
3
+
4
+ # workaround circular reference
5
+ module Fakecrm
6
+ class CustomType
7
+ include DataMapper::Resource
8
+
9
+ property :id, String, :unique => true, :key => true # default will not work here
10
+ property :name, String, :required => true, :length => 20
11
+ end
12
+ end
13
+
14
+ require 'fakecrm/resource/custom_attribute'
15
+
16
+ # workaround circular reference
17
+ module Fakecrm
18
+ class CustomType
19
+
20
+ property :kind, Enum["Activity", "Account", "Event", "Contact", "EventContact"], :required => true
21
+ property :icon_css_class, String
22
+
23
+ # only one entry for 'Contact' possible
24
+ validates_uniqueness_of :kind, :if => lambda { |c| c.kind == 'Contact' }
25
+
26
+ # only for activity && event_contact
27
+ property :states, CommaSeparatedList
28
+
29
+ has n, :custom_attributes
30
+
31
+ def activity?
32
+ self.kind == 'Activity'
33
+ end
34
+
35
+ # setting name for the first time also sets id
36
+ def name=(new_name)
37
+ if self.id.nil?
38
+ if self.kind == "EventContact"
39
+ self.id = SecureRandom.hex
40
+ else
41
+ self.id = new_name
42
+ end
43
+ end
44
+
45
+ super
46
+ end
47
+
48
+ # This is neccessary because updating DM associations is BROKEN
49
+ def custom_attributes=(custom_attributes)
50
+ if custom_attributes
51
+ existing_attributes = self.custom_attributes.all
52
+ existing_attributes.each do |existing_attribute|
53
+ if !(custom_attributes.find {|c| (c[:name] || c["name"]) == existing_attribute.name})
54
+ existing_attribute.destroy
55
+ end
56
+ end
57
+
58
+ custom_attributes.each do |custom_attribute|
59
+ name = custom_attribute["name"] || custom_attribute[:name]
60
+ c = self.custom_attributes.first(:name => name)
61
+ if c
62
+ c.attributes = custom_attribute
63
+ else
64
+ self.custom_attributes.new(custom_attribute)
65
+ end
66
+ end
67
+ @dm_is_broken = true
68
+ end
69
+ attribute_set(:custom_attributes, self.custom_attributes)
70
+ end
71
+
72
+ after :save, :propagate_type_extension
73
+
74
+ def propagate_type_extension
75
+ ::Fakecrm.logger.debug "Installing custom attributes@ kind=#{self.kind} name=#{self.name}"
76
+ ::Fakecrm::TypeExtender.new(self).extend!
77
+ end
78
+
79
+ def dirty_self?
80
+ # This forces DM to save after changing custom attributes
81
+ # We need this for our callback
82
+ # Did I mention that DM associations ARE BROKEN?
83
+ @dm_is_broken || super
84
+ ensure
85
+ @dm_is_broken = false # NOT REALLY
86
+ end
87
+
88
+ class << self
89
+ def virtual_properties
90
+ [:custom_attributes]
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+
@@ -0,0 +1,52 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/extensions/kinds'
3
+
4
+ require 'fakecrm/resource/custom_type'
5
+
6
+ module Fakecrm
7
+ class Event
8
+ include DataMapper::Resource
9
+
10
+ include Kinds
11
+
12
+ property :id, Serial
13
+ property :title, String, :required => true, :message => 'muss ausgefüllt werden'
14
+
15
+ property :dtstart_at, DateTime, :required => true
16
+ property :dtend_at, DateTime, :required => true
17
+
18
+ property :event_set, String
19
+ property :location, String
20
+
21
+ property :created_at, DateTime
22
+ property :changed_at, DateTime
23
+ property :updated_at, DateTime
24
+ property :deleted_at, ParanoidDateTime
25
+
26
+ property :updated_by, String, :default => 'root'
27
+
28
+ class << self
29
+ def virtual_properties
30
+ [:custom_attributes]
31
+ end
32
+ end
33
+
34
+ def custom_type
35
+ CustomType.first_or_create(:kind => 'EventContact', :name => self.kind)
36
+ end
37
+
38
+ def custom_attributes
39
+ custom_type ? custom_type.custom_attributes : []
40
+ end
41
+
42
+ def custom_attributes=(new_attributes)
43
+ custom_type.update({"custom_attributes"=>new_attributes})
44
+ end
45
+
46
+ def attributes=(attributes)
47
+ custom_attributes = attributes.delete("custom_attributes") || attributes.delete(:custom_attributes) || []
48
+ super(attributes) && (custom_attributes.empty? || (self.custom_attributes = custom_attributes))
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,21 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Fakecrm
3
+ class EventContact
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :state, Enum['unregistered', 'registered', 'attended', 'refused', 'noshow'], :required => true
8
+
9
+ property :created_at, DateTime
10
+ property :changed_at, DateTime
11
+ property :updated_at, DateTime
12
+ property :deleted_at, ParanoidDateTime
13
+
14
+ property :updated_by, String, :default => 'root'
15
+
16
+ belongs_to :event, :required => true
17
+ belongs_to :contact, :required => true
18
+
19
+ end
20
+ end
21
+
@@ -0,0 +1,26 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/custom_type'
3
+
4
+ module Fakecrm
5
+ module Kinds
6
+ def one_of_a_kind?
7
+ true
8
+ end
9
+ def self.included(base)
10
+ base.class_eval do
11
+ property :kind, ::DataMapper::Property::String, :required => true
12
+
13
+ validates_with_method :kind, :method => :check_kind
14
+
15
+ def check_kind
16
+ if CustomType.first(:name => self.kind, :kind => self.class.name.split('::').last)
17
+ return true
18
+ else
19
+ return [false, "Custom type #{self.kind} not found"]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,42 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/account'
3
+ require 'fakecrm/resource/activity'
4
+ require 'fakecrm/resource/contact'
5
+ require 'fakecrm/resource/event'
6
+ require 'fakecrm/resource/event_contact'
7
+
8
+ require 'fakecrm/resource/extensions/type_extension'
9
+
10
+ require 'dm-types'
11
+
12
+ module Fakecrm
13
+ class TypeExtender
14
+ def initialize(custom_type)
15
+ self.custom_type = custom_type
16
+ end
17
+
18
+ def extend!
19
+ custom_attributes = self.custom_type.custom_attributes
20
+ case self.custom_type.id
21
+ when 'contact'
22
+ TypeExtension.new(Contact).replace!(custom_attributes)
23
+ when 'account'
24
+ TypeExtension.new(Account).replace!(custom_attributes)
25
+ else
26
+ case self.custom_type.kind
27
+ when 'Event'
28
+ TypeExtension.new(Event).add!(custom_attributes)
29
+ when 'Activity'
30
+ TypeExtension.new(Activity).add!(custom_attributes)
31
+ when 'EventContact'
32
+ TypeExtension.new(EventContact).add!(custom_attributes)
33
+ else
34
+ true
35
+ end
36
+ end
37
+ end
38
+
39
+ attr_accessor :custom_type
40
+ end
41
+ end
42
+
@@ -0,0 +1,55 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Fakecrm
3
+ class TypeExtension
4
+ def initialize(resource)
5
+ self.resource = resource
6
+ end
7
+
8
+ def replace!(custom_attributes)
9
+ remove_custom_properties!
10
+ add!(custom_attributes)
11
+ end
12
+
13
+ def add!(custom_attributes)
14
+ custom_attributes.each do |custom_attribute|
15
+ ::Fakecrm.logger.debug "adding custom attribute: #{custom_attribute.name} to #{self.resource.name}"
16
+ add_property!(custom_attribute)
17
+ end
18
+
19
+ # write state
20
+ return self.resource.auto_upgrade! unless custom_attributes.empty?
21
+ end
22
+
23
+ def remove_custom_properties!
24
+ self.resource.properties.each do |property|
25
+ self.resource.properties.delete(property) if property.name =~ /^custom_/
26
+ end
27
+ end
28
+
29
+ def add_property!(custom_attribute)
30
+ property_name = "custom_#{custom_attribute.name}".to_sym
31
+
32
+ # do not overwrite existing properties!
33
+ if self.resource.properties[property_name]
34
+ ::Fakecrm.logger.debug "adding custom attribute: #{custom_attribute.name} to #{self.resource.name}"
35
+ end
36
+
37
+ case custom_attribute.type
38
+ when "string"
39
+ self.resource.send(:property, property_name, ::DataMapper::Property::String, :length => custom_attribute.max_length.to_i)
40
+ when "text"
41
+ self.resource.send(:property, property_name, ::DataMapper::Property::Text)
42
+ when "enum"
43
+ self.resource.send(:property, property_name, ::DataMapper::Property::Enum, :flags => custom_attribute.valid_values)
44
+ when "multienum"
45
+ # FIXME: multienum should validate valid_values
46
+ self.resource.send(:property, property_name, ::DataMapper::Property::CommaSeparatedList)
47
+ end
48
+
49
+ # FIXME: validate mandatory fields
50
+ end
51
+
52
+ attr_accessor :resource
53
+ end
54
+ end
55
+
@@ -0,0 +1,30 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module Fakecrm
4
+ class Mailing
5
+ include DataMapper::Resource
6
+
7
+ property :id, Serial
8
+ property :title, String, :required => true
9
+ property :mailing_type, String, :required => true
10
+
11
+ property :body, Text
12
+ property :dtstart_at, DateTime
13
+ property :email_from, String
14
+ property :email_reply_to, String
15
+ property :email_subject, String
16
+ property :html_body, Text
17
+
18
+ property :released_at, DateTime
19
+ property :created_at, DateTime
20
+ property :changed_at, DateTime
21
+ property :updated_at, DateTime
22
+ property :deleted_at, ParanoidDateTime
23
+
24
+ property :updated_by, String, :default => 'root'
25
+ property :released_by, String, :default => 'root'
26
+
27
+ belongs_to :event, :required => false
28
+ end
29
+ end
30
+
@@ -0,0 +1,17 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/contact'
3
+
4
+ module Fakecrm
5
+ class Password
6
+ include DataMapper::Resource
7
+
8
+ property :id, Serial
9
+ property :token, String, :default => 'dead' * 10
10
+ property :password, String
11
+
12
+ validates_length_of :password, :min => 1, :unless => lambda { |p| p.password.nil? }
13
+
14
+ belongs_to :contact
15
+ end
16
+ end
17
+
@@ -0,0 +1,18 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Fakecrm
3
+ class Role
4
+ include DataMapper::Resource
5
+
6
+ property :id, String, :key => true # default will not work here
7
+ property :name, String, :required => true
8
+ property :description, String
9
+
10
+ property :permissions, CommaSeparatedList
11
+
12
+ def name=(new_name)
13
+ self.id = new_name if self.id.nil?
14
+ super
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,41 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Fakecrm
3
+ class Template
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :body, Json, :default => {}
8
+
9
+ def templates
10
+ system_default.merge(body)
11
+ end
12
+
13
+ private
14
+
15
+ def system_default
16
+ {
17
+ "notification_email_to"=>"",
18
+ "notification_email_from"=>"",
19
+ "notification_email_reply_to"=>"",
20
+ "notification_email_bcc"=>"",
21
+ "notification_email_subject"=>"",
22
+ "notification_email_body"=>"",
23
+ "digest_email_from"=>"",
24
+ "digest_email_reply_to"=>"",
25
+ "digest_email_bcc"=>"",
26
+ "digest_email_subject"=>"",
27
+ "digest_email_body"=>"",
28
+ "password_request_email_from"=>"",
29
+ "password_request_email_reply_to"=>"",
30
+ "password_request_email_bcc"=>"",
31
+ "password_request_email_subject"=>"New Password Requested",
32
+ "password_request_email_body"=>
33
+ "To reset your password click the URL below:\r\n\r\n {{password_request_url}}\r\n\r\nIf you did not request your password to be reset please ignore this email and your password will stay as it is.",
34
+ "contact_salutation"=>
35
+ "{% assign anr = '' %} \r\n{% if contact.name_prefix contains 'Dr.' %} \r\n{% assign anr = 'Dr. ' %} \r\n{% endif %} \r\n{% if contact.name_prefix contains 'Prof.' %} \r\n{% assign anr = 'Prof. ' %} \r\n{% endif %} \r\n\r\n{% case contact.gender %} \r\n{% when \"M\" %} \r\nSehr geehrter Herr {{anr}}{{contact.last_name}}, \r\n{% when \"F\" %} \r\nSehr geehrte Frau {{anr}}{{contact.last_name}}, \r\n{% else %} \r\nSehr geehrte Damen und Herren, \r\n{% endcase %}"
36
+ }
37
+ end
38
+
39
+ end
40
+ end
41
+
@@ -0,0 +1,90 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/custom_type'
3
+
4
+ module Fakecrm
5
+ class ResourceView
6
+ class << self
7
+ def decorate(source, options={})
8
+ if source.class.include?(::Enumerable)
9
+ source.map {|item| self.new(item, options)}
10
+ else
11
+ self.new(source, options)
12
+ end
13
+ end
14
+ end
15
+
16
+ def initialize(resource, options={})
17
+ self.resource = resource
18
+
19
+ self.custom_attributes = get_custom_attributes(self.resource)
20
+ self.properties = get_resource_properties(self.resource)
21
+
22
+ self.include = options.fetch(:include, :all)
23
+ self.exclude = options.fetch(:exclude, [])
24
+ self.additional = options.fetch(:methods, get_additional_methods(self.resource))
25
+ end
26
+
27
+
28
+ def to_json(*args)
29
+ return as_json.to_json
30
+ end
31
+
32
+ def as_json(*args)
33
+ result = {}
34
+
35
+ self.properties.each do |property|
36
+ if available?(property) && include?(property)
37
+ result[property] = resource.send(property)
38
+ end
39
+ end
40
+
41
+ self.additional.each do |method|
42
+ result[method] = resource.send(method)
43
+ end
44
+
45
+ return result
46
+ end
47
+
48
+ def available?(property)
49
+ if property =~ /^custom/
50
+ self.custom_attributes.include?(property)
51
+ else
52
+ true
53
+ end
54
+ end
55
+
56
+ def include?(property)
57
+ !self.exclude.include?(property) && (self.include == :all || self.include.include?(property))
58
+ end
59
+
60
+ def exclude?(property)
61
+ !include?(property)
62
+ end
63
+
64
+ def get_additional_methods(resource)
65
+ if resource.class.respond_to? :virtual_properties
66
+ resource.class.virtual_properties || []
67
+ else
68
+ []
69
+ end
70
+ end
71
+
72
+ def get_resource_properties(resource)
73
+ resource.class.properties.map(&:name)
74
+ end
75
+
76
+ def get_custom_attributes(resource)
77
+ if resource.respond_to?(:one_of_a_kind?) && resource.one_of_a_kind?
78
+ CustomType.get!(resource.kind).custom_attributes.map(&:name).map(&:to_sym)
79
+ else
80
+ get_resource_properties(resource).select {|property| property =~ /^custom/ }
81
+ end
82
+ end
83
+
84
+ protected
85
+ attr_accessor :properties, :resource, :custom_attributes
86
+ attr_accessor :include, :exclude, :additional
87
+
88
+ end
89
+ end
90
+
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'fakecrm/resource/account'
3
+ require 'fakecrm/resource/activity'
4
+ require 'fakecrm/resource/contact'
5
+ require 'fakecrm/resource/custom_type'
6
+ require 'fakecrm/resource/event'
7
+ require 'fakecrm/resource/mailing'
8
+ require 'fakecrm/resource/password'
9
+ require 'fakecrm/resource/role'
10
+ require 'fakecrm/resource/template'
11
+