@@ -71,14 +71,9 @@ class LDAP
7171 #
7272 class Entry
7373 # This constructor is not generally called by user code.
74- #--
75- # Originally, myhash took a block so we wouldn't have to
76- # make sure its elements returned empty arrays when necessary.
77- # Got rid of that to enable marshalling of Entry objects,
78- # but that doesn't work anyway, because Entry objects have
79- # singleton methods. So we define a custom dump and load.
74+ #
8075 def initialize dn = nil # :nodoc:
81- @myhash = { } # originally: Hash.new {|k,v| k[v] = [] }
76+ @myhash = { }
8277 @myhash [ :dn ] = [ dn ]
8378 end
8479
@@ -95,20 +90,18 @@ def _load entry
9590 #--
9691 # Discovered bug, 26Aug06: I noticed that we're not converting the
9792 # incoming value to an array if it isn't already one.
98- def []= name , value # :nodoc:
99- sym = name . to_s . downcase . intern
93+ def []=( name , value ) # :nodoc:
94+ sym = attribute_name ( name )
10095 value = [ value ] unless value . is_a? ( Array )
10196 @myhash [ sym ] = value
10297 end
10398
104-
10599 #--
106- # We have to deal with this one as we do with []=
107- # because this one and not the other one gets called
108- # in formulations like entry["CN"] << cn.
100+ # We have to deal with this one as we do with []= because this one and not
101+ # the other one gets called in formulations like entry["CN"] << cn.
109102 #
110- def [] name # :nodoc:
111- name = name . to_s . downcase . intern unless name . is_a? ( Symbol )
103+ def []( name ) # :nodoc:
104+ name = attribute_name ( name ) unless name . is_a? ( Symbol )
112105 @myhash [ name ] || [ ]
113106 end
114107
@@ -139,8 +132,6 @@ def each
139132
140133 alias_method :each_attribute , :each
141134
142-
143-
144135 # Converts the Entry to a String, representing the
145136 # Entry's attributes in LDIF format.
146137 #--
@@ -166,24 +157,15 @@ def to_ldif
166157
167158 #--
168159 # TODO, doesn't support broken lines.
169- # It generates a SINGLE Entry object from an incoming LDIF stream
170- # which is of course useless for big LDIF streams that encode
171- # many objects.
160+ # It generates a SINGLE Entry object from an incoming LDIF stream which is
161+ # of course useless for big LDIF streams that encode many objects.
162+ #
172163 # DO NOT DOCUMENT THIS METHOD UNTIL THESE RESTRICTIONS ARE LIFTED.
173- # As it is, it's useful for unmarshalling objects that we create,
174- # but not for reading arbitrary LDIF files.
175- # Eventually, we should have a class method that parses large LDIF
176- # streams into individual LDIF blocks (delimited by blank lines)
177- # and passes them here.
178164 #
179- # There is one oddity, noticed by Matthias Tarasiewicz: as originally
180- # written, this code would return an Entry object in which the DN
181- # attribute consisted of a two-element array, and the first element was
182- # nil. That's because Entry#initialize doesn't like to create an object
183- # without a DN attribute so it adds one: nil. The workaround here is
184- # to wipe out the nil DN after creating the Entry object, and trust the
185- # LDIF string to fill it in. If it doesn't we return a nil at the end.
186- # (30Sep06, FCianfrocca)
165+ # As it is, it's useful for unmarshalling objects that we create, but not
166+ # for reading arbitrary LDIF files. Eventually, we should have a class
167+ # method that parses large LDIF streams into individual LDIF blocks
168+ # (delimited by blank lines) and passes them here.
187169 #
188170 class << self
189171 def from_single_ldif_string ldif
@@ -202,35 +184,42 @@ def from_single_ldif_string ldif
202184 entry . dn ? entry : nil
203185 end
204186 end
187+
188+ #--
189+ # Part of the support for getter and setter style access to attributes.
190+ #
191+ def respond_to? ( sym )
192+ name = attribute_name ( sym )
193+ return true if valid_attribute? ( name )
194+ return super
195+ end
205196
206197 #--
207- # Convenience method to convert unknown method names
208- # to attribute references. Of course the method name
209- # comes to us as a symbol, so let's save a little time
210- # and not bother with the to_s.downcase two-step.
211- # Of course that means that a method name like mAIL
212- # won't work, but we shouldn't be encouraging that
213- # kind of bad behavior in the first place.
214- # Maybe we should thow something if the caller sends
215- # arguments or a block...
198+ # Supports getter and setter style access for all the attributes that this
199+ # entry holds.
216200 #
217- def method_missing *args , &block # :nodoc:
218- s = args [ 0 ] . to_s . downcase . intern
219- if attribute_names . include? ( s )
220- self [ s ]
221- elsif s . to_s [ -1 ] == 61 and s . to_s . length > 1
222- value = args [ 1 ] or raise RuntimeError . new ( "unable to set value" )
223- value = [ value ] unless value . is_a? ( Array )
224- name = s . to_s [ 0 ..-2 ] . intern
225- self [ name ] = value
226- else
227- raise NoMethodError . new ( "undefined method '#{ s } '" )
201+ def method_missing sym , *args , &block # :nodoc:
202+ name = attribute_name ( sym )
203+
204+ if valid_attribute? name
205+ if setter? ( sym ) && args . size == 1
206+ value = args . first
207+ value = [ value ] unless value . instance_of? ( Array )
208+ self [ name ] = value
209+
210+ return value
211+ elsif args . empty?
212+ return self [ name ]
213+ end
228214 end
215+
216+ super
229217 end
230218
231219 def write
232220 end
233221
222+ private
234223
235224 #--
236225 # Internal convenience method. It seems like the standard
@@ -249,8 +238,27 @@ def is_attribute_value_binary? value
249238 end
250239 false
251240 end
252- private :is_attribute_value_binary?
253-
241+
242+ # Returns the symbol that can be used to access the attribute that
243+ # sym_or_str designates.
244+ #
245+ def attribute_name ( sym_or_str )
246+ str = sym_or_str . to_s . downcase
247+
248+ # Does str match 'something='? Still only returns :something
249+ return str [ 0 ...-1 ] . to_sym if str . size >1 && str [ -1 ] == ?=
250+ return str . to_sym
251+ end
252+
253+ # Given a valid attribute symbol, returns true.
254+ #
255+ def valid_attribute? ( attr_name )
256+ attribute_names . include? ( attr_name )
257+ end
258+
259+ def setter? ( sym )
260+ sym . to_s [ -1 ] == ?=
261+ end
254262 end # class Entry
255263
256264
0 commit comments