Module: Plist4r::DataMethods

Included in:
ArrayDict, PlistType
Defined in:
lib/plist4r/mixin/data_methods.rb

Constant Summary collapse

ClassesForKeyType =

Return those Class constants which the value of a Plist Key must conform to. This is class-based data validation.

{
  :string => [String], 
  :string_or_integer => [String,Integer,Fixnum], 
  :bool => [TrueClass,FalseClass],
  :bool_or_string => [TrueClass,FalseClass,String],
  :integer => [Integer,Fixnum],
  :array_of_strings => [Array],
  :array_of_hashes => [Array],
  :array => [Array],
  :array_or_integer => [Array,Integer,Fixnum],
  :array_or_hash => [Array, Hash],
  :hash_of_bools => [Hash],
  :hash_of_strings => [Hash],
  :hash_of_arrays => [Hash],
  :hash_of_arrays_of_strings => [Hash],
  :hash => [Hash],
  :bool_or_hash_of_bools => [TrueClass,FalseClass,Hash],
  :bool_or_string_or_array_of_strings => [TrueClass,FalseClass,String,Array]
}
ValidKeys =

A Hash Array of the supported plist keys for this type. These are only those plist keys recognized as belonging to a specific plist datatype. Used in validation, part of DataMethods. We usually overload this method in subclasses. To see how to use these Plist Keys, go to PlistKeyNames

Examples:

class Plist4r::PlistType::MyPlistType < PlistType
  ValidKeys =
  {
     :string => %w[PlistKeyS1 PlistKeyS2 ...],
     :bool => %w[PlistKeyB1 PlistKeyB2 ...],
     :integer => %w[PlistKeyI1 PlistKeyI2 ...],
     :method_defined => %w[CustomPlistKey1 CustomPlistKey2 ...]
  }
end

plist.plist_type :my_plist_type
plist.plist_key_s1 "some string"
plist.plist_key_b1 true
plist.plist_key_i1 08
plist.custom_plist_key1 MyClass.new(opts)

See Also:

{}
ValidKeysTemplate =

A template for creating new plist types

{
  :string => %w[
    
    ],
  :bool => %w[
    
    ],
  :integer => %w[
    
    ],
  :array_of_strings => %w[
    
    ],
  :array_of_hashes => %w[
    
    ],
  :array => %w[
    
    ],
  :hash_of_bools => %w[
    
    ],
  :hash_of_strings => %w[
    
    ],
  :hash_of_arrays => %w[
    
    ],
  :hash_of_arrays_of_strings => %w[
    
    ],
  :hash => %w[
    
    ],
  :could_be_method_defined   => %w[
    
    ]
}

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_symbol, *args, &blk) ⇒ Object

Call #set_or_return with the appropriate arguments. If Plist#strict_keys is enabled, then raise an error on any unrecognised Plist Keys.



103
104
105
# File 'lib/plist4r/mixin/data_methods.rb', line 103

def method_missing method_symbol, *args, &blk
  set_or_return method_symbol.to_s.camelcase, *args, &blk
end

Instance Method Details

#_respond_to?(method_sym) ⇒ Boolean

Defining respond_to? conflicts with rspec 1.3.0. @object.stub() blows up. To as a consequence we dont implement respond_to? for method_missing()

Returns:

  • (Boolean)

    true



97
98
99
# File 'lib/plist4r/mixin/data_methods.rb', line 97

def _respond_to? method_sym
  true
end

#set_or_return(key, value = nil) ⇒ Object

Set or return value data

Parameters:

  • key (Symbol, String)

    The plist key name, either a snake-cased symbol, or literal string

  • value (nil, Object) (defaults to: nil)

    If present, store Object under the plist key “key”. If nil, return the stored object

Returns:

  • The Object stored under key



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/plist4r/mixin/data_methods.rb', line 111

def set_or_return key, value=nil
  key = key.to_s.camelcase if key.class == Symbol

  self.class::ValidKeys.each do |key_type, valid_keys_of_those_type|
    if valid_keys_of_those_type.include?(key)
      return set_or_return_of_type key_type, key, value
    end
  end

  if (! @plist) || (@plist && @plist.strict_keys == false)
    key_type = nil
    return set_or_return_of_type key_type, key, value
  else
    raise "Unrecognized key for class: #{self.class.inspect}. Tried to set_or_return #{key.inspect}, with: #{value.inspect}"
  end
end

#set_or_return_of_type(key_type, key, value = nil) ⇒ Object

Set or return a plist key, value pair, and verify the value type If key_type is set to nil, then skip value data check

Examples:

plist.set_or_return_of_type :string, "CFBundleIdentifier", "com.apple.myapp"

plist.set_or_return_of_type nil, "SomeUnknownKey", [[0],1,2,{ 3 => true}]
# Skips validation

Parameters:

  • key_type (Symbol, nil)

    The type of class which the value of the key must belong to. Used for validity check.

Returns:

  • the key’s value

See Also:



219
220
221
222
223
224
225
226
227
# File 'lib/plist4r/mixin/data_methods.rb', line 219

def set_or_return_of_type key_type, key, value=nil
  case value
  when nil
    @orig[key]
  else
    validate_value key_type, key, value if ClassesForKeyType.keys.include?(key_type)
    @hash[key] = value
  end
end

#validate_value(key_type, key, value) ⇒ Object

This method is called when setting a value to a plist key. (or some value within a nested plist sub-structure).

Examples:

plist.validate_value :string, "CFBundleIdentifier", "com.apple.myapp"
# => Okay, no error raised
plist.validate_value :string, "CFBundleIdentifier", ["com.apple.myapp"]
# => Raises Class mismatch. Value is of type Array, should be String

Parameters:

  • key_type (Symbol)

    This Symbol is resolved to a class constant, by looking it up in ClassesForKeyType

  • value

    The value to validate. We just check that the value conforms to key_type.

Raises:

  • Class mistmatch

See Also:



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/plist4r/mixin/data_methods.rb', line 138

def validate_value key_type, key, value
  unless ClassesForKeyType[key_type].include?(value.class)
    raise "Key: #{key}, value: #{value.inspect} is of type #{value.class}. Should be: #{ClassesForKeyType[key_type].join ", "}"
  end
  case key_type
  when :array_of_strings, :bool_or_string_or_array_of_strings
    if value.class == Array
      value.each_index do |i|
        unless value[i].class == String
          raise "Element: #{key}[#{i}], value: #{value[i].inspect} is of type #{value[i].class}. Should be: #{ClassesForKeyType[:string].join ", "}"
        end
      end
    end
  when :array_of_hashes
    value.each_index do |i|
      unless value[i].class == Hash
        raise "Element: #{key}[#{i}], value: #{value[i].inspect} is of type #{value[i].class}. Should be: #{ClassesForKeyType[:hash].join ", "}"
      end
    end
  when :hash_of_bools
    value.each do |k,v|
      unless [TrueClass,FalseClass].include? v.class
        raise "Key: #{key}[#{k}], value: #{v.inspect} is of type #{v.class}. Should be: #{ClassesForKeyType[:bool].join ", "}"
      end
    end
  when :hash_of_strings
    value.each do |k,v|
      unless v.class == String
        raise "Key: #{key}[#{k}], value: #{v.inspect} is of type #{v.class}. Should be: #{ClassesForKeyType[:string].join ", "}"
      end
    end
  when :hash_of_arrays
    value.each do |k,v|
      unless v.class == Array
        raise "Key: #{key}[#{k}], value: #{v.inspect} is of type #{v.class}. Should be: #{ClassesForKeyType[:array].join ", "}"
      end
    end
  when :hash_of_arrays_of_strings
    value.each do |k,v|
      unless v.class == Array
        raise "Key: #{key}[#{k}], value: #{v.inspect} is of type #{v.class}. Should be: #{ClassesForKeyType[:array].join ", "}"
      end
      v.each_index do |i|
        unless v[i].class == String
          raise "Element: #{key}[#{k}][#{i}], value: #{v[i].inspect} is of type #{v[i].class}. Should be: #{ClassesForKeyType[:string].join ", "}"
        end
      end
    end
  end
end