dm-ldap-adapter 0.3.5 → 0.4.0.alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.project +11 -0
- data/.yardoc +0 -0
- data/Manifest.txt +5 -2
- data/README-example.markdown +0 -1
- data/README.txt +15 -15
- data/Rakefile +4 -3
- data/env.sh +2 -0
- data/example/identity_map.rb +10 -10
- data/example/posix.rb +9 -9
- data/ldap-commands.txt +3 -0
- data/lib/adapters/ldap_adapter.rb +155 -118
- data/lib/adapters/noop_transaction.rb +16 -0
- data/lib/dummy_ldap_resource.rb +6 -6
- data/lib/ldap/array.rb +96 -12
- data/lib/ldap/conditions_2_filter.rb +95 -0
- data/lib/ldap/digest.rb +3 -3
- data/lib/ldap/net_ldap_facade.rb +28 -110
- data/lib/ldap/ruby_ldap_facade.rb +31 -116
- data/lib/ldap/version.rb +1 -1
- data/lib/ldap_resource.rb +113 -26
- data/spec/assiociations_ldap_adapter_spec.rb +129 -130
- data/spec/authentication_ldap_adapter_spec.rb +1 -6
- data/spec/ldap_adapter_spec.rb +164 -177
- data/spec/multi_repository_spec.rb +41 -5
- data/spec/multi_value_attributes_spec.rb +64 -31
- data/spec/sorting_spec.rb +16 -15
- data/spec/spec_helper.rb +34 -20
- metadata +67 -27
- data/lib/adapters/memory_adapter.rb +0 -79
- data/lib/adapters/simple_adapter.rb +0 -198
@@ -1,19 +1,21 @@
|
|
1
|
-
require
|
1
|
+
require "dm-core"
|
2
|
+
require 'slf4r'
|
3
|
+
# require 'adapters/noop_transaction'
|
2
4
|
|
3
5
|
module Ldap
|
4
6
|
|
5
7
|
# the class provides two ways of getting a LdapFacade. either
|
6
8
|
# one which is put on the current Thread or a new one
|
7
9
|
class LdapConnection
|
8
|
-
|
10
|
+
|
9
11
|
include ::Slf4r::Logger
|
10
12
|
|
11
|
-
def initialize(
|
12
|
-
if
|
13
|
+
def initialize(options)
|
14
|
+
if options[:facade].nil?
|
13
15
|
require 'ldap/net_ldap_facade'
|
14
16
|
@facade = ::Ldap::NetLdapFacade
|
15
17
|
else
|
16
|
-
case
|
18
|
+
case options[:facade].to_sym
|
17
19
|
when :ruby_ldap
|
18
20
|
require 'ldap/ruby_ldap_facade'
|
19
21
|
@facade = ::Ldap::RubyLdapFacade
|
@@ -26,19 +28,19 @@ module Ldap
|
|
26
28
|
end
|
27
29
|
logger.info("using #{@facade}")
|
28
30
|
@ldaps = { }
|
29
|
-
auth = {
|
31
|
+
auth = {
|
30
32
|
:method => :simple,
|
31
|
-
:username =>
|
32
|
-
:password =>
|
33
|
-
}
|
34
|
-
@config = {
|
35
|
-
:host =>
|
36
|
-
:port =>
|
37
|
-
:auth => auth,
|
38
|
-
:base =>
|
33
|
+
:username => options[:bind_name],
|
34
|
+
:password => options[:password]
|
35
|
+
}
|
36
|
+
@config = {
|
37
|
+
:host => options[:host],
|
38
|
+
:port => options[:port].to_i,
|
39
|
+
:auth => auth,
|
40
|
+
:base => options[:base]
|
39
41
|
}
|
40
42
|
end
|
41
|
-
|
43
|
+
|
42
44
|
# puts a LdapFacade into the current thread and executes the
|
43
45
|
# given block.
|
44
46
|
def open
|
@@ -48,10 +50,10 @@ module Ldap
|
|
48
50
|
yield
|
49
51
|
end
|
50
52
|
ensure
|
51
|
-
@ldaps[Thread.current] = nil
|
53
|
+
@ldaps[Thread.current] = nil
|
52
54
|
end
|
53
55
|
end
|
54
|
-
|
56
|
+
|
55
57
|
# @return [Ldap::LdapFacade]
|
56
58
|
# either the one from the current Thread or a new one
|
57
59
|
def current
|
@@ -67,10 +69,32 @@ end
|
|
67
69
|
|
68
70
|
require "dm-core"
|
69
71
|
module DataMapper
|
72
|
+
class Query
|
73
|
+
|
74
|
+
class SortCaseInsensitive < Sort
|
75
|
+
def initialize(value, ascending = true)
|
76
|
+
if(value && value.is_a?(String))
|
77
|
+
super(value.upcase, ascending)
|
78
|
+
else
|
79
|
+
super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def sort_records_case_insensitive(records)
|
85
|
+
sort_order = order.map { |direction| [ direction.target, direction.operator == :asc ] }
|
86
|
+
|
87
|
+
records.sort_by do |record|
|
88
|
+
sort_order.map do |(property, ascending)|
|
89
|
+
SortCaseInsensitive.new(record_value(record, property), ascending)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
70
94
|
module Adapters
|
71
|
-
class LdapAdapter <
|
95
|
+
class LdapAdapter < AbstractAdapter
|
72
96
|
|
73
|
-
# @return [Ldap::LdapFacade]
|
97
|
+
# @return [Ldap::LdapFacade]
|
74
98
|
# ready to use LdapFacade
|
75
99
|
def ldap
|
76
100
|
@ldap_connection.current
|
@@ -81,25 +105,25 @@ module DataMapper
|
|
81
105
|
end
|
82
106
|
|
83
107
|
def key_properties(resource)
|
84
|
-
resource.
|
108
|
+
resource.model.key.first
|
85
109
|
end
|
86
110
|
|
87
111
|
COMPARATORS = { "=" => :eql, ">=" => :gte, "<=" => :lte, "like" => :like }
|
88
112
|
|
89
113
|
# helper to remove datamapper specific classes from the conditions
|
90
|
-
# @param [Array] conditions
|
114
|
+
# @param [Array] conditions
|
91
115
|
# array of tuples: (action, property, new value)
|
92
|
-
# @return [Array]
|
116
|
+
# @return [Array]
|
93
117
|
# tuples: (action, attribute name, new value)
|
94
118
|
def to_ldap_conditions(query)
|
95
119
|
conditions = query.conditions
|
96
120
|
ldap_conditions = []
|
97
|
-
conditions.each do |c|
|
98
|
-
if c
|
121
|
+
conditions.operands.each do |c|
|
122
|
+
if c.is_a? Array
|
99
123
|
props = {}
|
100
124
|
query.fields.each{ |f| props[f.name] = f.field}
|
101
125
|
or_conditions = []
|
102
|
-
c[
|
126
|
+
c[0].split('or').each do |e|
|
103
127
|
e.strip!
|
104
128
|
match = e.match("=|<=|>=|like")
|
105
129
|
or_conditions << [COMPARATORS[match.values_at(0)[0]],
|
@@ -108,23 +132,57 @@ module DataMapper
|
|
108
132
|
end
|
109
133
|
ldap_conditions << [:or_operator, or_conditions, nil]
|
110
134
|
else
|
111
|
-
|
135
|
+
comparator = c.slug
|
136
|
+
case comparator
|
137
|
+
when :raw
|
138
|
+
when :not
|
139
|
+
# TODO proper recursion !!!
|
140
|
+
ldap_conditions << [comparator, c.operands.first.subject.field, c.operands.first.send(:dumped_value)]
|
141
|
+
when :in
|
142
|
+
ldap_conditions << [:eql, c.subject.field, c.send(:dumped_value)]
|
143
|
+
else
|
144
|
+
ldap_conditions << [comparator, c.subject.field, c.send(:dumped_value)]
|
112
145
|
end
|
113
146
|
end
|
147
|
+
end
|
114
148
|
ldap_conditions
|
115
149
|
end
|
116
150
|
|
151
|
+
include ::Slf4r::Logger
|
152
|
+
|
153
|
+
# @see AbstractAdapter
|
154
|
+
# def transaction_primitive
|
155
|
+
# NoopTransaction.new
|
156
|
+
# end
|
157
|
+
|
117
158
|
public
|
118
159
|
|
119
|
-
def initialize(name,
|
120
|
-
super(name,
|
121
|
-
@ldap_connection = ::Ldap::LdapConnection.new(@
|
160
|
+
def initialize(name, options)
|
161
|
+
super(name, options)
|
162
|
+
@ldap_connection = ::Ldap::LdapConnection.new(@options)
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
def create(resources)
|
167
|
+
resources.select do |resource|
|
168
|
+
|
169
|
+
create_resource(resource)
|
170
|
+
|
171
|
+
end.size # just return the number of create resources
|
122
172
|
end
|
123
173
|
|
174
|
+
def update(attributes, collection)
|
175
|
+
collection.each do |resource|
|
176
|
+
#puts "update"
|
177
|
+
#p resource
|
178
|
+
update_resource(resource, attributes)
|
179
|
+
|
180
|
+
end.size
|
181
|
+
end
|
124
182
|
# @param [DataMapper::Resource] resource
|
125
183
|
# to be created
|
126
184
|
# @see SimpleAdapter#create_resource
|
127
|
-
# @return [Fixnum]
|
185
|
+
# @return [Fixnum]
|
128
186
|
# value for the primary key or nil
|
129
187
|
def create_resource(resource)
|
130
188
|
logger.debug { resource.inspect }
|
@@ -133,8 +191,8 @@ module DataMapper
|
|
133
191
|
key = nil
|
134
192
|
resource.send(:properties).each do |prop|
|
135
193
|
value = prop.get!(resource)
|
136
|
-
if prop.
|
137
|
-
props[prop.field.to_sym] = value
|
194
|
+
if prop.class == ::Ldap::LdapArray
|
195
|
+
props[prop.field.to_sym] = value unless value.nil? or value.size == 0
|
138
196
|
else
|
139
197
|
props[prop.field.to_sym] = value.to_s unless value.nil?
|
140
198
|
end
|
@@ -156,14 +214,14 @@ module DataMapper
|
|
156
214
|
end
|
157
215
|
logger.debug { "resource #{resource.inspect} key value: #{key_value.inspect}" + ", multivalue_field: " + resource.model.multivalue_field.to_s }
|
158
216
|
if key_value and !key.nil?
|
159
|
-
key.set!(resource, key_value.to_i)
|
217
|
+
key.set!(resource, key_value.to_i)
|
160
218
|
resource
|
161
219
|
elsif resource.model.multivalue_field
|
162
220
|
multivalue_prop = resource.send(:properties).detect do |prop|
|
163
221
|
prop.field.to_sym == resource.model.multivalue_field
|
164
222
|
end
|
165
|
-
update_resource(resource,
|
166
|
-
{ multivalue_prop =>
|
223
|
+
update_resource(resource,
|
224
|
+
{ multivalue_prop =>
|
167
225
|
resource.send(multivalue_prop.name.to_sym)})
|
168
226
|
else
|
169
227
|
nil
|
@@ -179,18 +237,21 @@ module DataMapper
|
|
179
237
|
actions = []
|
180
238
|
attributes.each do |property, value|
|
181
239
|
field = property.field.to_sym #TODO sym needed or string ???
|
182
|
-
if property.
|
183
|
-
|
184
|
-
|
240
|
+
if property.class == ::Ldap::LdapArray
|
241
|
+
value = property.load(value)
|
242
|
+
if resource.original_attributes[property].nil?
|
243
|
+
value.each do |v|
|
244
|
+
actions << [:add, field, v]
|
245
|
+
end
|
185
246
|
else
|
186
247
|
array_actions = []
|
187
|
-
resource.
|
248
|
+
resource.original_attributes[property].each do |ov|
|
188
249
|
unless value.member? ov
|
189
250
|
actions << [:delete, field, ov.to_s]
|
190
251
|
end
|
191
252
|
end
|
192
253
|
value.each do |v|
|
193
|
-
unless resource.
|
254
|
+
unless resource.original_attributes[property].member? v
|
194
255
|
actions << [:add, field, v.to_s]
|
195
256
|
end
|
196
257
|
end
|
@@ -199,119 +260,93 @@ module DataMapper
|
|
199
260
|
else
|
200
261
|
if resource.model.multivalue_field == property.field.to_sym
|
201
262
|
if value.nil?
|
202
|
-
actions << [:delete, field, resource.
|
263
|
+
actions << [:delete, field, resource.original_attributes[property].to_s]
|
203
264
|
else
|
204
265
|
actions << [:add, field, value.to_s]
|
205
266
|
end
|
206
267
|
elsif value.nil?
|
207
268
|
actions << [:delete, field, []]
|
208
|
-
elsif resource.
|
269
|
+
elsif resource.original_attributes[property].nil?
|
209
270
|
actions << [:add, field, value.to_s]
|
210
271
|
else
|
211
272
|
actions << [:replace, field, value.to_s]
|
212
273
|
end
|
213
274
|
end
|
214
275
|
end
|
215
|
-
#
|
216
|
-
#
|
276
|
+
#puts "actions"
|
277
|
+
#p actions
|
217
278
|
#puts
|
218
|
-
ldap.update_object(resource.model.dn_prefix(resource),
|
219
|
-
resource.model.treebase,
|
279
|
+
ldap.update_object(resource.model.dn_prefix(resource),
|
280
|
+
resource.model.treebase,
|
220
281
|
actions)
|
221
282
|
end
|
222
283
|
|
223
|
-
# @
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
284
|
+
# @see AbstractAdapter#delete
|
285
|
+
def delete(collection)
|
286
|
+
collection.each do |resource|
|
287
|
+
if resource.model.multivalue_field
|
288
|
+
multivalue_prop = resource.send(:properties).detect do |prop|
|
289
|
+
prop.field.to_sym == resource.model.multivalue_field
|
290
|
+
end
|
291
|
+
# set the original value so update does the right thing
|
292
|
+
resource.send("#{multivalue_prop.name}=".to_sym, nil)
|
293
|
+
update_resource(resource,
|
294
|
+
{ multivalue_prop => nil })
|
295
|
+
else
|
296
|
+
ldap.delete_object(resource.model.dn_prefix(resource),
|
297
|
+
resource.model.treebase)
|
230
298
|
end
|
231
|
-
# set the original value so update does the right thing
|
232
|
-
resource.send("#{multivalue_prop.name}=".to_sym, nil)
|
233
|
-
update_resource(resource,
|
234
|
-
{ multivalue_prop => nil })
|
235
|
-
else
|
236
|
-
ldap.delete_object(resource.model.dn_prefix(resource),
|
237
|
-
resource.model.treebase)
|
238
299
|
end
|
239
300
|
end
|
240
|
-
|
241
|
-
# @
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
query.model.key.collect { |k| k.field},
|
250
|
-
to_ldap_conditions(query),
|
251
|
-
field_names)
|
252
|
-
if query.model.multivalue_field
|
253
|
-
resource = result.detect do |item|
|
254
|
-
# run over all values of the multivalue field
|
255
|
-
item[query.model.multivalue_field].any? do |value|
|
256
|
-
values = query.fields.collect do |f|
|
257
|
-
if query.model.multivalue_field == f.field.to_sym
|
258
|
-
value
|
259
|
-
else
|
260
|
-
val = item[f.field.to_sym].first
|
261
|
-
f.primitive == Integer ? val.to_i : val
|
262
|
-
end
|
263
|
-
end
|
264
|
-
resource = query.model.load(values, query)
|
265
|
-
return resource if filter_resource(resource, query.conditions)
|
266
|
-
end
|
267
|
-
end
|
268
|
-
else
|
269
|
-
values = result.first
|
270
|
-
if values
|
271
|
-
query.fields.collect do |f|
|
272
|
-
val = values[f.field.to_sym]
|
273
|
-
if f.type == DataMapper::Types::LdapArray
|
274
|
-
val if val
|
275
|
-
elsif val
|
276
|
-
f.primitive == Integer ? val.first.to_i : val.first
|
277
|
-
end
|
278
|
-
end
|
301
|
+
|
302
|
+
# @see AbstractAdapter#read
|
303
|
+
def read(query)
|
304
|
+
result = []
|
305
|
+
resources = read_resources(query)
|
306
|
+
resources.each do |resource|
|
307
|
+
map = {}
|
308
|
+
query.fields.each_with_index do |property, idx|
|
309
|
+
map[property.field] = property.typecast(resource[idx])
|
279
310
|
end
|
311
|
+
result << map
|
280
312
|
end
|
313
|
+
|
314
|
+
#puts "read_many"
|
315
|
+
#p result.size
|
316
|
+
result = result.uniq if query.unique?
|
317
|
+
result = query.match_records(result) if query.model.multivalue_field
|
318
|
+
result = query.sort_records_case_insensitive(result)
|
319
|
+
result = query.limit_records(result)
|
320
|
+
result
|
281
321
|
end
|
282
|
-
|
283
|
-
# @param [DataMapper::Query] query
|
284
|
-
# the search criteria
|
285
|
-
# @return [Array<DataMapper::Resource]
|
286
|
-
# the array of found resources
|
287
|
-
# @see SimpleAdapter#read_resources
|
322
|
+
|
288
323
|
def read_resources(query)
|
289
|
-
order_by = query.order.first.
|
324
|
+
order_by = query.order.first.target.field
|
290
325
|
order_by_sym = order_by.to_sym
|
291
326
|
field_names = query.fields.collect {|f| f.field }
|
292
|
-
result = ldap.read_objects(query.model.treebase,
|
293
|
-
query.model.key.collect { |k| k.field },
|
327
|
+
result = ldap.read_objects(query.model.treebase,
|
328
|
+
query.model.key.collect { |k| k.field },
|
294
329
|
to_ldap_conditions(query),
|
295
|
-
field_names, order_by)
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
330
|
+
field_names, order_by)
|
331
|
+
#.sort! do |u1, u2|
|
332
|
+
# value1 = u1[order_by_sym].first.upcase rescue ""
|
333
|
+
# value2 = u2[order_by_sym].first.upcase rescue ""
|
334
|
+
# value1 <=> value2
|
335
|
+
# end
|
300
336
|
if query.model.multivalue_field
|
301
337
|
props_result = []
|
302
338
|
result.each do |props|
|
303
339
|
# run over all values of the multivalue field
|
304
340
|
(props[query.model.multivalue_field] || []).each do |value|
|
305
341
|
values = query.fields.collect do |f|
|
306
|
-
if query.model.multivalue_field == f.field.to_sym
|
342
|
+
if query.model.multivalue_field == f.field.to_sym
|
307
343
|
value
|
308
|
-
else
|
344
|
+
else
|
309
345
|
prop = props[f.field.to_sym].first
|
310
346
|
f.primitive == Integer ? prop.to_i : prop
|
311
347
|
end
|
312
348
|
end
|
313
|
-
|
314
|
-
props_result << resource if filter_resource(resource, query.conditions)
|
349
|
+
props_result << values
|
315
350
|
end
|
316
351
|
end
|
317
352
|
props_result
|
@@ -319,7 +354,7 @@ module DataMapper
|
|
319
354
|
result.collect do |props|
|
320
355
|
query.fields.collect do |f|
|
321
356
|
prop = props[f.field.to_sym]
|
322
|
-
if f.
|
357
|
+
if f.class == Ldap::LdapArray
|
323
358
|
prop if prop
|
324
359
|
elsif prop
|
325
360
|
f.primitive == Integer ? prop.first.to_i : prop.first
|
@@ -328,6 +363,8 @@ module DataMapper
|
|
328
363
|
end
|
329
364
|
end
|
330
365
|
end
|
366
|
+
|
367
|
+
# include ::DataMapper::Transaction::Adapter
|
331
368
|
end
|
332
369
|
end
|
333
370
|
end
|
data/lib/dummy_ldap_resource.rb
CHANGED
@@ -4,9 +4,9 @@ require 'ldap/digest'
|
|
4
4
|
# dummy implementation which turns the extra ldap configuration noops
|
5
5
|
module DataMapper
|
6
6
|
module Resource
|
7
|
-
|
7
|
+
|
8
8
|
module ClassMethods
|
9
|
-
|
9
|
+
|
10
10
|
include ::Slf4r::Logger
|
11
11
|
|
12
12
|
def ldap_properties(resource = nil, &block)
|
@@ -21,7 +21,7 @@ module DataMapper
|
|
21
21
|
logger.debug { "ldap_properties=#{@ldap_properties.inspect}" }
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def treebase(resource = nil, &block)
|
26
26
|
if block
|
27
27
|
@treebase = block
|
@@ -34,7 +34,7 @@ module DataMapper
|
|
34
34
|
logger.debug { "treebase=#{@treebase}" }
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def dn_prefix(resource = nil, &block)
|
39
39
|
if block
|
40
40
|
@dn_prefix = block
|
@@ -47,12 +47,12 @@ module DataMapper
|
|
47
47
|
logger.debug { "dn_prefix=#{dn_prefix}" }
|
48
48
|
end
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
def multivalue_field(field = nil)
|
52
52
|
logger.debug { "multivalue_field = #{field}" } if field
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def authenticate(password)
|
57
57
|
raise "NotImplemented"
|
58
58
|
end
|
data/lib/ldap/array.rb
CHANGED
@@ -1,18 +1,102 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
primitive Array
|
5
|
-
default Proc.new { Array.new }
|
1
|
+
require 'dm-core'
|
2
|
+
module Ldap
|
3
|
+
class Array < ::Array
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
def initialize(resource, property, *args)
|
6
|
+
setup(resource, property)
|
7
|
+
super(args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup(resource, property)
|
11
|
+
@resource = resource
|
12
|
+
@property = property
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :push! :push
|
17
|
+
|
18
|
+
def []=(k, v)
|
19
|
+
result = super
|
20
|
+
@resource.send("#{@property.name}=".to_sym, self)
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def <<(element)
|
26
|
+
push(element)
|
27
|
+
end
|
28
|
+
|
29
|
+
def push(element)
|
30
|
+
result = super
|
31
|
+
@resource.send("#{@property.name}=".to_sym, self)
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
alias :delete! :delete
|
36
|
+
|
37
|
+
def delete(element)
|
38
|
+
result = super
|
39
|
+
@resource.send(:"#{@property.name}=", self)
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class LdapArray < ::DataMapper::Property::Text
|
45
|
+
|
46
|
+
default Proc.new { |r,p| Ldap::Array.new(r,p) }
|
47
|
+
|
48
|
+
def custom?
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
def primitive?(value)
|
53
|
+
super || value.kind_of?(::Array)
|
54
|
+
end
|
55
|
+
|
56
|
+
def load(value)
|
57
|
+
result = case value
|
58
|
+
when ::String then value.gsub(/^.|.$/,'').split('","').to_a.freeze
|
59
|
+
when ::Array then value.freeze
|
60
|
+
else
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def dump(value)
|
66
|
+
result = case value
|
67
|
+
when LdapArray then '"' + value.join('","') + '"'
|
68
|
+
when ::Array then '"' + value.join('","') + '"'
|
69
|
+
when ::String then '"' + value.to_s + '"'
|
70
|
+
else
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end
|
10
74
|
|
11
|
-
|
12
|
-
|
13
|
-
|
75
|
+
def initialize(*args)
|
76
|
+
super
|
77
|
+
model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
78
|
+
def #{name.to_s}=(v)
|
79
|
+
case v
|
80
|
+
when Ldap::Array
|
81
|
+
v.setup(self, properties[:#{name}])
|
82
|
+
else
|
83
|
+
vv = Ldap::Array.new(self, properties[:#{name}])
|
84
|
+
vv.replace(v)
|
85
|
+
end
|
86
|
+
attribute_set(:#{name}, v)
|
87
|
+
end
|
14
88
|
|
89
|
+
def #{name.to_s}
|
90
|
+
v = attribute_get(:#{name})
|
91
|
+
case v
|
92
|
+
when Ldap::Array
|
93
|
+
v.setup(self, properties[:#{name}])
|
94
|
+
else
|
95
|
+
vv = Ldap::Array.new(self, properties[:#{name}])
|
96
|
+
vv.replace(v)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
RUBY
|
15
100
|
end
|
16
101
|
end
|
17
|
-
Property::TYPES << Types::LdapArray unless Property::TYPES.member? Types::LdapArray
|
18
102
|
end
|