Class: Rod::Property::Field
Overview
This class defines the field property. A field has to define its name
and its type
.
Constant Summary collapse
- VALID_TYPES =
The valid types of fields.
[:string, :integer, :float, :ulong, :object, :json]
- VARIABLE_TYPES =
The fields with variable size.
[:string, :object, :json]
- IDENTIFIER =
The name of the field used to identify the objects.
:rod_id
Instance Attribute Summary collapse
-
#type ⇒ Object
readonly
The type of the property.
Attributes inherited from Base
Instance Method Summary collapse
-
#association? ⇒ Boolean
Predicate indicating that this property is not an association.
-
#copy(klass) ⇒ Object
Creates a copy of the field with a new
klass
. -
#default_value ⇒ Object
Returns the default value for given type of field.
-
#define_c_accessors(builder) ⇒ Object
Defines the accessor of the field’s constituents (C struct field/fields that hold the field data).
-
#define_getter ⇒ Object
Defines the getter of the Ruby class which corresponds to this field.
-
#define_setter ⇒ Object
Defines the settor of the Ruby class which corresponds to this field.
-
#dump(value) ⇒ Object
Dumps the
value
of the field according to its type. -
#field? ⇒ Boolean
Predicate indicating that this property is a field.
-
#identifier? ⇒ Boolean
Returns true if the field is used to identify the objects.
-
#initialize(klass, name, type, options = {}) ⇒ Field
constructor
Initialize the field associated with the
klass
withname
,type
andoptions
. -
#layout ⇒ Object
Returns the memory layout of the C struct fields that correspond to this field.
-
#load(value) ⇒ Object
Loads the
value
of the field according to its type. -
#metadata ⇒ Object
Returns the metadata of the field in form of a hash.
-
#seal_c_accessors ⇒ Object
Make the C accessors private.
-
#to_c_struct ⇒ Object
Converts the field to fields in a C struct.
-
#variable_size? ⇒ Boolean
Returns true if the field has a variable size.
Methods inherited from Base
#define_finders, #difference, #has_index?, #index, #reset_index
Constructor Details
#initialize(klass, name, type, options = {}) ⇒ Field
Initialize the field associated with the klass
with name
, type
and options
. The type should be one of:
-
:integer
-
:ulong
-
:float
-
:string
-
:object
(value is marshaled durign storage, and unmarshaled during read) -
:json
(value is dumped in JSON format during storage, and loaded during read. Note: some Ruby types are not unified during conversion, e.g. String and Symbol)
The valid options are:
-
:index
builds an index for the field and might be:
** :flat
simple hash index (true
works as well for backwards compatiblity) ** :segmented
index split for 1001 pieces for shorter load times (only
one piece is loaded on one look-up)
36 37 38 39 40 |
# File 'lib/rod/property/field.rb', line 36 def initialize(klass,name,type,={}) super(klass,name,) check_type(type) @type = type end |
Instance Attribute Details
#type ⇒ Object (readonly)
The type of the property.
11 12 13 |
# File 'lib/rod/property/field.rb', line 11 def type @type end |
Instance Method Details
#association? ⇒ Boolean
Predicate indicating that this property is not an association.
53 54 55 |
# File 'lib/rod/property/field.rb', line 53 def association? false end |
#copy(klass) ⇒ Object
Creates a copy of the field with a new klass
.
43 44 45 |
# File 'lib/rod/property/field.rb', line 43 def copy(klass) self.class.new(klass,@name,@type,@options) end |
#default_value ⇒ Object
Returns the default value for given type of field.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/rod/property/field.rb', line 58 def default_value case @type when :integer 0 when :ulong 0 when :float 0.0 when :string '' when :object, :json nil end end |
#define_c_accessors(builder) ⇒ Object
Defines the accessor of the field’s constituents (C struct field/fields that hold the field data).
146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/rod/property/field.rb', line 146 def define_c_accessors(builder) unless variable_size? field_reader(@name,@klass.struct_name,c_type(@type),builder) field_writer(@name,@klass.struct_name,c_type(@type),builder) else field_reader("#{@name}_length",@klass.struct_name,c_type(:ulong),builder) field_reader("#{@name}_offset",@klass.struct_name,c_type(:ulong),builder) field_writer("#{@name}_length",@klass.struct_name,c_type(:ulong),builder) field_writer("#{@name}_offset",@klass.struct_name,c_type(:ulong),builder) end end |
#define_getter ⇒ Object
Defines the getter of the Ruby class which corresponds to this field.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/rod/property/field.rb', line 172 def define_getter field = @name.to_s unless variable_size? @klass.send(:define_method,field) do value = instance_variable_get("@#{field}") if value.nil? if self.new? value = nil else value = send("_#{field}",@rod_id) end instance_variable_set("@#{field}",value) end value end else is_object = @type != :string type = @type property = self database = @klass.database @klass.send(:define_method,field) do value = instance_variable_get("@#{field}") if value.nil? # first call if self.new? return (is_object ? nil : "") else length = send("_#{field}_length", @rod_id) if length == 0 return (is_object ? nil : "") end offset = send("_#{field}_offset", @rod_id) = {} if is_object [:skip_encoding] = true end value = database.read_string(length, offset) value = property.load(value) # caching Ruby representation # don't use setter - avoid change tracking instance_variable_set("@#{field}",value) end end value end end end |
#define_setter ⇒ Object
Defines the settor of the Ruby class which corresponds to this field.
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/rod/property/field.rb', line 220 def define_setter # optimization field = @name.to_s @klass.send(:define_method,"#{field}=") do |value| old_value = send(field) send("#{field}_will_change!") unless old_value == value instance_variable_set("@#{field}",value) value end end |
#dump(value) ⇒ Object
Dumps the value
of the field according to its type.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/rod/property/field.rb', line 79 def dump(value) case @type when :object Marshal.dump(value) when :json JSON.dump([value]) when :string # TODO the encoding should be stored in the DB # or configured globally value.encode("utf-8") when :ulong raise InvalidArgument.new(value,"ulong") if value < 0 value else value end end |
#field? ⇒ Boolean
Predicate indicating that this property is a field.
48 49 50 |
# File 'lib/rod/property/field.rb', line 48 def field? true end |
#identifier? ⇒ Boolean
Returns true if the field is used to identify the objects.
114 115 116 |
# File 'lib/rod/property/field.rb', line 114 def identifier? @name == IDENTIFIER end |
#layout ⇒ Object
Returns the memory layout of the C struct fields that correspond to this field.
233 234 235 236 237 238 239 240 |
# File 'lib/rod/property/field.rb', line 233 def layout unless variable_size? "#{@name}[value:#{sizeof(@type)}]" else "#{@name}[length:#{sizeof(:ulong)}+" + "offset:#{sizeof(:ulong)}]" end end |
#load(value) ⇒ Object
Loads the value
of the field according to its type.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/rod/property/field.rb', line 98 def load(value) return value unless variable_size? case @type when :object value.force_encoding("ascii-8bit") value = Marshal.load(value) rescue nil when :json value.force_encoding("ascii-8bit") value = JSON.load(value).first rescue nil when :string value.force_encoding("utf-8") end value end |
#metadata ⇒ Object
Returns the metadata of the field in form of a hash.
119 120 121 |
# File 'lib/rod/property/field.rb', line 119 def @options.merge({:type => @type}) end |
#seal_c_accessors ⇒ Object
Make the C accessors private.
159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/rod/property/field.rb', line 159 def seal_c_accessors unless variable_size? @klass.send(:private,"_#{@name}") @klass.send(:private,"_#{@name}=") else @klass.send(:private,"_#{@name}_length") @klass.send(:private,"_#{@name}_length=") @klass.send(:private,"_#{@name}_offset") @klass.send(:private,"_#{@name}_offset=") end end |
#to_c_struct ⇒ Object
Converts the field to fields in a C struct.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rod/property/field.rb', line 124 def to_c_struct unless variable_size? str = <<-SUBEND |#ifdef __BYTE_ORDER |# if __BYTE_ORDER == __BIG_ENDIAN | uint64_t #{@name}; |# else | #{c_type(@type)} #{@name}; |# endif |#else | #{c_type(@type)} #{@name}; |#endif SUBEND str.margin else " #{c_type(:ulong)} #{@name}_length;\n" + " #{c_type(:ulong)} #{@name}_offset;\n" end end |
#variable_size? ⇒ Boolean
Returns true if the field has a variable size.
74 75 76 |
# File 'lib/rod/property/field.rb', line 74 def variable_size? VARIABLE_TYPES.include?(@type) end |