xcodeproj 0.1.0 → 0.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/xcodeproj/extconf.h +8 -0
- data/ext/xcodeproj/extconf.rb +1 -0
- data/ext/xcodeproj/xcodeproj_ext.c +69 -11
- data/lib/xcodeproj.rb +1 -1
- data/lib/xcodeproj/config.rb +142 -10
- data/lib/xcodeproj/inflector.rb +1 -1
- data/lib/xcodeproj/project.rb +154 -566
- data/lib/xcodeproj/project/association.rb +54 -0
- data/lib/xcodeproj/project/association/has_many.rb +51 -0
- data/lib/xcodeproj/project/association/has_one.rb +39 -0
- data/lib/xcodeproj/project/association/reflection.rb +88 -0
- data/lib/xcodeproj/project/object.rb +207 -0
- data/lib/xcodeproj/project/object/build_phase.rb +89 -0
- data/lib/xcodeproj/project/object/configuration.rb +100 -0
- data/lib/xcodeproj/project/object/file_reference.rb +71 -0
- data/lib/xcodeproj/project/object/group.rb +102 -0
- data/lib/xcodeproj/project/object/native_target.rb +126 -0
- data/lib/xcodeproj/project/object_list.rb +146 -0
- metadata +19 -6
@@ -0,0 +1,100 @@
|
|
1
|
+
module Xcodeproj
|
2
|
+
class Project
|
3
|
+
module Object
|
4
|
+
|
5
|
+
class XCBuildConfiguration < AbstractPBXObject
|
6
|
+
COMMON_BUILD_SETTINGS = {
|
7
|
+
:all => {
|
8
|
+
'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
|
9
|
+
'GCC_PRECOMPILE_PREFIX_HEADER' => 'YES',
|
10
|
+
'PRODUCT_NAME' => '$(TARGET_NAME)',
|
11
|
+
'SKIP_INSTALL' => 'YES',
|
12
|
+
'DSTROOT' => '/tmp/xcodeproj.dst',
|
13
|
+
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
|
14
|
+
'GCC_C_LANGUAGE_STANDARD' => 'gnu99',
|
15
|
+
'INSTALL_PATH' => "$(BUILT_PRODUCTS_DIR)",
|
16
|
+
'GCC_WARN_ABOUT_MISSING_PROTOTYPES' => 'YES',
|
17
|
+
'GCC_WARN_ABOUT_RETURN_TYPE' => 'YES',
|
18
|
+
'GCC_WARN_UNUSED_VARIABLE' => 'YES',
|
19
|
+
'OTHER_LDFLAGS' => '',
|
20
|
+
'COPY_PHASE_STRIP' => 'YES',
|
21
|
+
}.freeze,
|
22
|
+
:debug => {
|
23
|
+
'GCC_DYNAMIC_NO_PIC' => 'NO',
|
24
|
+
'GCC_PREPROCESSOR_DEFINITIONS' => ["DEBUG=1", "$(inherited)"],
|
25
|
+
'GCC_SYMBOLS_PRIVATE_EXTERN' => 'NO',
|
26
|
+
'GCC_OPTIMIZATION_LEVEL' => '0',
|
27
|
+
'COPY_PHASE_STRIP' => 'NO',
|
28
|
+
}.freeze,
|
29
|
+
:ios => {
|
30
|
+
'ARCHS' => "$(ARCHS_STANDARD_32_BIT)",
|
31
|
+
'IPHONEOS_DEPLOYMENT_TARGET' => '4.3',
|
32
|
+
'PUBLIC_HEADERS_FOLDER_PATH' => "$(TARGET_NAME)",
|
33
|
+
'SDKROOT' => 'iphoneos',
|
34
|
+
}.freeze,
|
35
|
+
:osx => {
|
36
|
+
'ARCHS' => "$(ARCHS_STANDARD_64_BIT)",
|
37
|
+
'GCC_ENABLE_OBJC_EXCEPTIONS' => 'YES',
|
38
|
+
'GCC_WARN_64_TO_32_BIT_CONVERSION' => 'YES',
|
39
|
+
'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
|
40
|
+
'MACOSX_DEPLOYMENT_TARGET' => '10.7',
|
41
|
+
'SDKROOT' => 'macosx',
|
42
|
+
}.freeze,
|
43
|
+
[:osx, :debug] => {
|
44
|
+
'ONLY_ACTIVE_ARCH' => 'YES',
|
45
|
+
}.freeze,
|
46
|
+
[:osx, :release] => {
|
47
|
+
'DEBUG_INFORMATION_FORMAT' => 'dwarf-with-dsym',
|
48
|
+
}.freeze,
|
49
|
+
[:ios, :release] => {
|
50
|
+
'VALIDATE_PRODUCT' => 'YES',
|
51
|
+
}.freeze,
|
52
|
+
}.freeze
|
53
|
+
|
54
|
+
def self.new_release(project)
|
55
|
+
new(project, nil,
|
56
|
+
'name' => 'Release',
|
57
|
+
'buildSettings' => COMMON_BUILD_SETTINGS[:all].dup
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.new_debug(project)
|
62
|
+
new(project, nil,
|
63
|
+
'name' => 'Debug',
|
64
|
+
'buildSettings' => COMMON_BUILD_SETTINGS[:all].merge(COMMON_BUILD_SETTINGS[:debug])
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
# [Hash] the build settings used when building a target
|
69
|
+
attribute :build_settings
|
70
|
+
|
71
|
+
# TODO why do I need to specify the uuid here?
|
72
|
+
has_one :base_configuration, :uuid => :base_configuration_reference
|
73
|
+
|
74
|
+
def initialize(*)
|
75
|
+
super
|
76
|
+
self.build_settings ||= {}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class XCConfigurationList < AbstractPBXObject
|
81
|
+
attribute :default_configuration_is_visible
|
82
|
+
attribute :default_configuration_name
|
83
|
+
|
84
|
+
has_many :build_configurations
|
85
|
+
|
86
|
+
def initialize(*)
|
87
|
+
super
|
88
|
+
self.build_configuration_references ||= []
|
89
|
+
end
|
90
|
+
|
91
|
+
def build_settings(build_configuration_name)
|
92
|
+
if config = build_configurations.where(:name => build_configuration_name)
|
93
|
+
config.build_settings
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'xcodeproj/project/object/group'
|
2
|
+
|
3
|
+
module Xcodeproj
|
4
|
+
class Project
|
5
|
+
module Object
|
6
|
+
|
7
|
+
# @todo Add a list of all possible file types for `explicit_file_type`
|
8
|
+
# and `last_known_file_type`.
|
9
|
+
class PBXFileReference < AbstractGroupEntry
|
10
|
+
# [String] the path to the file relative to the source tree
|
11
|
+
attribute :path
|
12
|
+
|
13
|
+
# [String] the source tree to which the file is relative. It can be one
|
14
|
+
# of `SOURCE_ROOT` or `SDKROOT`
|
15
|
+
attribute :source_tree
|
16
|
+
|
17
|
+
# [String] the file type regardless of what Xcode might think it is
|
18
|
+
attribute :explicit_file_type
|
19
|
+
|
20
|
+
# [String] the file type guessed by Xcode
|
21
|
+
attribute :last_known_file_type
|
22
|
+
|
23
|
+
# [String] wether of not this file should be indexed. This can be
|
24
|
+
# either "0" or "1".
|
25
|
+
attribute :include_in_index
|
26
|
+
|
27
|
+
has_many :build_files, :inverse_of => :file
|
28
|
+
|
29
|
+
def self.new_static_library(project, product_name)
|
30
|
+
new(project, nil,
|
31
|
+
"includeInIndex" => "0",
|
32
|
+
"sourceTree" => "BUILT_PRODUCTS_DIR",
|
33
|
+
"path" => "lib#{product_name}.a"
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(*)
|
38
|
+
super
|
39
|
+
self.path = path if path # sets default name
|
40
|
+
self.source_tree ||= 'SOURCE_ROOT'
|
41
|
+
self.include_in_index ||= "1"
|
42
|
+
set_default_file_type!
|
43
|
+
end
|
44
|
+
|
45
|
+
alias_method :_path=, :path=
|
46
|
+
def path=(path)
|
47
|
+
self._path = path
|
48
|
+
self.name ||= pathname.basename.to_s
|
49
|
+
path
|
50
|
+
end
|
51
|
+
|
52
|
+
def pathname
|
53
|
+
Pathname.new(path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_default_file_type!
|
57
|
+
return if explicit_file_type || last_known_file_type
|
58
|
+
case path
|
59
|
+
when /\.a$/
|
60
|
+
self.explicit_file_type = 'archive.ar'
|
61
|
+
when /\.framework$/
|
62
|
+
self.last_known_file_type = 'wrapper.framework'
|
63
|
+
when /\.xcconfig$/
|
64
|
+
self.last_known_file_type = 'text.xcconfig'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Xcodeproj
|
2
|
+
class Project
|
3
|
+
module Object
|
4
|
+
|
5
|
+
class AbstractGroupEntry < AbstractPBXObject
|
6
|
+
has_one :group, :inverse_of => :children
|
7
|
+
|
8
|
+
def initialize(project, uuid, attributes)
|
9
|
+
is_new = uuid.nil?
|
10
|
+
super
|
11
|
+
# If there's no root_object yet, then this is probably the main group.
|
12
|
+
if is_new && @project.root_object
|
13
|
+
@project.main_group.children << self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def destroy
|
18
|
+
group.child_references.delete(uuid)
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sorts groups before files and inside those sorts by name.
|
23
|
+
def <=>(other)
|
24
|
+
if self.is_a?(PBXGroup) && other.is_a?(PBXFileReference)
|
25
|
+
-1
|
26
|
+
elsif self.is_a?(PBXFileReference) && other.is_a?(PBXGroup)
|
27
|
+
1
|
28
|
+
else
|
29
|
+
self.name <=> other.name
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @todo The `source_tree` can probably be more than just `<group>`.
|
35
|
+
class PBXGroup < AbstractGroupEntry
|
36
|
+
# [String] the source tree to which this group is relative. It can be
|
37
|
+
# `<group>`.
|
38
|
+
attribute :source_tree
|
39
|
+
|
40
|
+
has_many :children, :class => AbstractGroupEntry do |child|
|
41
|
+
# Associating the AbstractGroupEntry instance to this group through
|
42
|
+
# the inverse association will also remove it from the group it was
|
43
|
+
# in.
|
44
|
+
child.group = self
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(*)
|
48
|
+
super
|
49
|
+
self.source_tree ||= '<group>'
|
50
|
+
self.child_references ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
def main_group?
|
54
|
+
@project.main_group.uuid == uuid
|
55
|
+
end
|
56
|
+
|
57
|
+
def name
|
58
|
+
if name = super
|
59
|
+
name
|
60
|
+
elsif attributes.has_key?('path')
|
61
|
+
File.basename(attributes['path'])
|
62
|
+
elsif main_group?
|
63
|
+
'Main Group'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def files
|
68
|
+
children.list_by_class(PBXFileReference)
|
69
|
+
end
|
70
|
+
|
71
|
+
def create_file(path)
|
72
|
+
files.new("path" => path)
|
73
|
+
end
|
74
|
+
|
75
|
+
def create_files(paths)
|
76
|
+
paths.map { |path| create_file(path) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def source_files
|
80
|
+
children.list_by_class(PBXFileReference) do |list|
|
81
|
+
list.let(:uuid_scope) do
|
82
|
+
files.reject { |file| file.build_files.empty? }.map(&:uuid)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def groups
|
88
|
+
children.list_by_class(PBXGroup)
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_group(name)
|
92
|
+
groups.new("name" => name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def <<(child)
|
96
|
+
children << child
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Xcodeproj
|
2
|
+
class Project
|
3
|
+
module Object
|
4
|
+
|
5
|
+
class PBXNativeTarget < AbstractPBXObject
|
6
|
+
STATIC_LIBRARY = 'com.apple.product-type.library.static'
|
7
|
+
|
8
|
+
# [String] the name of the build product
|
9
|
+
attribute :product_name
|
10
|
+
|
11
|
+
# [String] the build product type identifier
|
12
|
+
attribute :product_type
|
13
|
+
|
14
|
+
has_many :build_phases
|
15
|
+
has_many :dependencies # TODO :class => ?
|
16
|
+
has_many :build_rules # TODO :class => ?
|
17
|
+
has_one :build_configuration_list, :class => XCConfigurationList
|
18
|
+
has_one :product, :uuid => :product_reference
|
19
|
+
|
20
|
+
def self.new_static_library(project, platform, name)
|
21
|
+
project.add_system_framework(platform == :ios ? 'Foundation' : 'Cocoa')
|
22
|
+
|
23
|
+
target = new(project, nil, 'productType' => STATIC_LIBRARY, 'productName' => name)
|
24
|
+
target.product.path = "lib#{name}.a"
|
25
|
+
|
26
|
+
target.build_configurations.each do |config|
|
27
|
+
config.build_settings.merge!(XCBuildConfiguration::COMMON_BUILD_SETTINGS[platform])
|
28
|
+
|
29
|
+
# E.g. [:ios, :release]
|
30
|
+
extra_settings_key = [platform, config.name.downcase.to_sym]
|
31
|
+
if extra_settings = XCBuildConfiguration::COMMON_BUILD_SETTINGS[extra_settings_key]
|
32
|
+
config.build_settings.merge!(extra_settings)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
target
|
37
|
+
end
|
38
|
+
|
39
|
+
# You need to specify a product. For a static library you can use
|
40
|
+
# PBXFileReference.new_static_library.
|
41
|
+
def initialize(project, *)
|
42
|
+
super
|
43
|
+
self.name ||= product_name
|
44
|
+
self.build_rule_references ||= []
|
45
|
+
self.dependency_references ||= []
|
46
|
+
|
47
|
+
unless build_phase_references
|
48
|
+
self.build_phase_references = []
|
49
|
+
|
50
|
+
source_build_phases.new
|
51
|
+
copy_files_build_phases.new
|
52
|
+
#shell_script_build_phases.new
|
53
|
+
|
54
|
+
phase = frameworks_build_phases.new
|
55
|
+
if frameworks_group = @project.groups.where(:name => 'Frameworks')
|
56
|
+
frameworks_group.files.each { |framework| phase << framework }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
unless build_configuration_list
|
61
|
+
self.build_configuration_list = project.objects.add(XCConfigurationList, {
|
62
|
+
'defaultConfigurationIsVisible' => '0',
|
63
|
+
'defaultConfigurationName' => 'Release',
|
64
|
+
})
|
65
|
+
# TODO or should this happen in buildConfigurationList?
|
66
|
+
build_configuration_list.build_configurations.new_debug
|
67
|
+
build_configuration_list.build_configurations.new_release
|
68
|
+
end
|
69
|
+
|
70
|
+
unless product
|
71
|
+
self.product = @project.files.new_static_library(product_name)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
alias_method :_product=, :product=
|
76
|
+
def product=(product)
|
77
|
+
self._product = product
|
78
|
+
@project.products << product
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_configurations
|
82
|
+
build_configuration_list.build_configurations
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_settings(build_configuration_name)
|
86
|
+
build_configuration_list.build_settings(build_configuration_name)
|
87
|
+
end
|
88
|
+
|
89
|
+
def source_build_phases
|
90
|
+
build_phases.list_by_class(PBXSourcesBuildPhase)
|
91
|
+
end
|
92
|
+
|
93
|
+
def copy_files_build_phases
|
94
|
+
build_phases.list_by_class(PBXCopyFilesBuildPhase)
|
95
|
+
end
|
96
|
+
|
97
|
+
def frameworks_build_phases
|
98
|
+
build_phases.list_by_class(PBXFrameworksBuildPhase)
|
99
|
+
end
|
100
|
+
|
101
|
+
def shell_script_build_phases
|
102
|
+
build_phases.list_by_class(PBXShellScriptBuildPhase)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Finds an existing file reference or creates a new one.
|
106
|
+
def add_source_file(path, copy_header_phase = nil, compiler_flags = nil)
|
107
|
+
file = @project.files.find { |file| file.path == path.to_s } || @project.files.new('path' => path.to_s)
|
108
|
+
build_file = file.build_files.new
|
109
|
+
if path.extname == '.h'
|
110
|
+
build_file.settings = { 'ATTRIBUTES' => ["Public"] }
|
111
|
+
# Working around a bug in Xcode 4.2 betas, remove this once the Xcode bug is fixed:
|
112
|
+
# https://github.com/alloy/cocoapods/issues/13
|
113
|
+
#phase = copy_header_phase || headers_build_phases.first
|
114
|
+
phase = copy_header_phase || copy_files_build_phases.first
|
115
|
+
phase.build_files << build_file
|
116
|
+
else
|
117
|
+
build_file.settings = { 'COMPILER_FLAGS' => compiler_flags } if compiler_flags
|
118
|
+
source_build_phases.first.build_files << build_file
|
119
|
+
end
|
120
|
+
file
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Xcodeproj
|
2
|
+
class Project
|
3
|
+
|
4
|
+
# In case `scoped` is an Array the list's order is maintained.
|
5
|
+
class PBXObjectList
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(represented_class, project)
|
9
|
+
@represented_class = represented_class
|
10
|
+
@project = project
|
11
|
+
@callbacks = {}
|
12
|
+
|
13
|
+
yield self if block_given?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Specify callbacks for:
|
17
|
+
# * :uuid_scope Returns the list of UUIDs to scope this list to.
|
18
|
+
# * :push When an object is added to the list.
|
19
|
+
def let(callback_name, &block)
|
20
|
+
raise ArgumentError, "Incorrect callback `#{callback_name}'." unless [:uuid_scope, :push].include?(callback_name)
|
21
|
+
@callbacks[callback_name] = block
|
22
|
+
end
|
23
|
+
|
24
|
+
def uuid_scope
|
25
|
+
@callbacks[:uuid_scope].call
|
26
|
+
end
|
27
|
+
|
28
|
+
def empty?
|
29
|
+
uuid_scope.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](uuid)
|
33
|
+
if uuid_scope.include?(uuid) && hash = @project.objects_hash[uuid]
|
34
|
+
Object.const_get(hash['isa']).new(@project, uuid, hash)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def add(klass, hash = {})
|
39
|
+
object = klass.new(@project, nil, hash)
|
40
|
+
self << object
|
41
|
+
object
|
42
|
+
end
|
43
|
+
|
44
|
+
def new(hash = {})
|
45
|
+
add(@represented_class, hash)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Run Ruby in debug mode to receive warnings about calls to :push when a
|
49
|
+
# list does not have a callback registered for :push.
|
50
|
+
def push(object)
|
51
|
+
if @callbacks[:push]
|
52
|
+
@callbacks[:push].call(object)
|
53
|
+
else
|
54
|
+
if $DEBUG
|
55
|
+
warn "Pushed object onto a PBXObjectList that does not have a :push callback from: #{caller.first}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
self
|
59
|
+
end
|
60
|
+
alias_method :<<, :push
|
61
|
+
|
62
|
+
def each
|
63
|
+
uuid_scope.each do |uuid|
|
64
|
+
yield self[uuid]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def ==(other)
|
69
|
+
self.to_a == other.to_a
|
70
|
+
end
|
71
|
+
|
72
|
+
def size
|
73
|
+
uuid_scope.size
|
74
|
+
end
|
75
|
+
|
76
|
+
# Since order can't always be guaranteed, these might need to move to an order specific subclass.
|
77
|
+
def first
|
78
|
+
to_a.first
|
79
|
+
end
|
80
|
+
def last
|
81
|
+
to_a.last
|
82
|
+
end
|
83
|
+
|
84
|
+
def inspect
|
85
|
+
"<PBXObjectList: #{map(&:inspect).join(', ')}>"
|
86
|
+
end
|
87
|
+
|
88
|
+
def where(attributes)
|
89
|
+
find { |o| o.matches_attributes?(attributes) }
|
90
|
+
end
|
91
|
+
|
92
|
+
# @todo is it really necessary to have an extra method for this?
|
93
|
+
def object_named(name)
|
94
|
+
where :name => name
|
95
|
+
end
|
96
|
+
|
97
|
+
# Returns a PBXObjectList instance of objects in the list.
|
98
|
+
#
|
99
|
+
# By default this list will scope the list by objects matching the
|
100
|
+
# specified class and add objects, pushed onto the list, to the parent
|
101
|
+
# list
|
102
|
+
#
|
103
|
+
# If a block is given the list instance is yielded so that the default
|
104
|
+
# callbacks can be overridden.
|
105
|
+
#
|
106
|
+
# @param [AbstractPBXObject] klass The AbstractPBXObject subclass to
|
107
|
+
# which the list should be scoped.
|
108
|
+
#
|
109
|
+
# @yield [PBXObjectList] The list instance, allowing you to
|
110
|
+
# easily override the callbacks.
|
111
|
+
#
|
112
|
+
# @return [PBXObjectList<klass>] The list of matching objects.
|
113
|
+
def list_by_class(klass)
|
114
|
+
parent = self
|
115
|
+
PBXObjectList.new(klass, @project) do |list|
|
116
|
+
list.let(:push) do |object|
|
117
|
+
# Objects added to the subselection should still use the same
|
118
|
+
# callback as this list.
|
119
|
+
parent << object
|
120
|
+
end
|
121
|
+
list.let(:uuid_scope) do
|
122
|
+
parent.uuid_scope.select do |uuid|
|
123
|
+
@project.objects_hash[uuid]['isa'] == klass.isa
|
124
|
+
end
|
125
|
+
end
|
126
|
+
yield list if block_given?
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# This only makes sense on those with a specific represented class. Not the main objects list.
|
131
|
+
def method_missing(name, *args, &block)
|
132
|
+
if @represented_class.respond_to?(name)
|
133
|
+
object = @represented_class.send(name, @project, *args)
|
134
|
+
# The callbacks are only for AbstractPBXObject instances instantiated
|
135
|
+
# from the class method that we forwarded the message to.
|
136
|
+
self << object if object.is_a?(Object::AbstractPBXObject)
|
137
|
+
object
|
138
|
+
else
|
139
|
+
super
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|