Class: Fix::Protocol::MessagePart
- Inherits:
-
Object
- Object
- Fix::Protocol::MessagePart
- Extended by:
- Forwardable
- Defined in:
- lib/fix/protocol/message_part.rb
Overview
Basic building block for messages. Message parts can define fields, sub-parts and collections
Direct Known Subclasses
Message, Fix::Protocol::Messages::Instrument, Fix::Protocol::Messages::MdEntry, Fix::Protocol::Messages::MdEntryType, RepeatingMessagePart, UnorderedPart
Instance Attribute Summary collapse
-
#delegations ⇒ Object
Returns the value of attribute delegations.
-
#name ⇒ Object
Returns the value of attribute name.
-
#parse_failure ⇒ Object
Returns the value of attribute parse_failure.
Class Method Summary collapse
-
.collection(name, opts = {}) ⇒ Object
Defines a collection as a part of this message part, collections typically have a counter and a repeating element.
-
.field(name, opts) ⇒ Object
Defines a field as part of the structure for this class.
-
.inherited(klass) ⇒ Object
Inherits the @structure class instance variable but allows the child to modify it without impacting the parent, this allows for message structure refinement.
-
.parent_delegate(*args) ⇒ Object
Defines the attributes that should be accessible from the parent node.
-
.parse(str) ⇒ Object
Class-level shortcut to directly parse an instance of a specific message part subclass.
-
.part(name, opts = {}, &block) ⇒ Object
Defines a reusable message part as element of this particular class.
-
.structure ⇒ Array
Returns this message part class’ structure.
-
.unordered(name, opts = {}, &block) ⇒ Object
Defines an unordered fields collection.
Instance Method Summary collapse
-
#dump ⇒ String
Dumps this message part as a FIX message fragment.
-
#errors ⇒ Array
Returns the errors for this instance.
-
#initialize(opts = {}) ⇒ MessagePart
constructor
A new instance of MessagePart.
-
#initialize_node(node) ⇒ Object
Initializes a node depending on its type, this is called when initializing a message part instance by the constructor.
-
#node_for_name(n) ⇒ Object
Searches the immediate hierarchy by node name to return the requested node.
-
#nodes ⇒ Array
The message part nodes, they’ll be either a
FP::Field
, anFP::RepeatingMessagePart
or aFP::MessagePart
. -
#parse(str) ⇒ String
Parses a full or partial FIX message string into the message part nodes.
Constructor Details
#initialize(opts = {}) ⇒ MessagePart
Returns a new instance of MessagePart.
16 17 18 19 |
# File 'lib/fix/protocol/message_part.rb', line 16 def initialize(opts = {}) self.name = opts[:name] self.class.structure.each { |node| initialize_node(node) } end |
Instance Attribute Details
#delegations ⇒ Object
Returns the value of attribute delegations.
14 15 16 |
# File 'lib/fix/protocol/message_part.rb', line 14 def delegations @delegations end |
#name ⇒ Object
Returns the value of attribute name.
14 15 16 |
# File 'lib/fix/protocol/message_part.rb', line 14 def name @name end |
#parse_failure ⇒ Object
Returns the value of attribute parse_failure.
14 15 16 |
# File 'lib/fix/protocol/message_part.rb', line 14 def parse_failure @parse_failure end |
Class Method Details
.collection(name, opts = {}) ⇒ Object
Defines a collection as a part of this message part, collections typically have a counter and a repeating element
115 116 117 118 119 120 121 122 123 |
# File 'lib/fix/protocol/message_part.rb', line 115 def self.collection(name, opts = {}) structure << { node_type: :collection, name: name, counter_tag: opts[:counter_tag], klass: opts[:klass] } define_method(name) do node_for_name(name) end parent_delegate(name) end |
.field(name, opts) ⇒ Object
Defines a field as part of the structure for this class
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 |
# File 'lib/fix/protocol/message_part.rb', line 177 def self.field(name, opts) structure << { node_type: :field, name: name }.merge(opts) # Getter define_method(name) do node_for_name(name).value end # Setter define_method("#{name}=") do |val| node_for_name(name).value = val end if opts[:mapping] define_method("raw_#{name}") do node_for_name(name).raw_value end define_method("raw_#{name}=") do |val| node_for_name(name).raw_value = val end end # Delegate getter and setter from parent node parent_delegate(name, "#{name}=") end |
.inherited(klass) ⇒ Object
Inherits the @structure class instance variable but allows the child to modify it without impacting the parent, this allows for message structure refinement
26 27 28 |
# File 'lib/fix/protocol/message_part.rb', line 26 def self.inherited(klass) klass.send(:instance_variable_set, :@structure, structure.dup) end |
.parent_delegate(*args) ⇒ Object
Defines the attributes that should be accessible from the parent node
104 105 106 107 |
# File 'lib/fix/protocol/message_part.rb', line 104 def self.parent_delegate(*args) @delegations ||= [] args.each { |a| @delegations << a } end |
.parse(str) ⇒ Object
Class-level shortcut to directly parse an instance of a specific message part subclass
93 94 95 96 97 |
# File 'lib/fix/protocol/message_part.rb', line 93 def self.parse(str) instce = new instce.parse(str) instce end |
.part(name, opts = {}, &block) ⇒ Object
Defines a reusable message part as element of this particular class
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/fix/protocol/message_part.rb', line 131 def self.part(name, opts = {}, &block) = { node_type: :part, name: name, delegate: true }.merge(opts) klass = [:klass] # If a block is given it overrides the +:klass+ option if block_given? names = (to_s + name.to_s.split(/\_/).map(&:capitalize).join).split('::') klass = names.pop parent_klass = ([:node_type] == :part) ? MessagePart : UnorderedPart klass = names.inject(Object) { |mem, obj| mem = mem.const_get(obj) }.const_set(klass, Class.new(parent_klass)) klass.instance_eval(&block) .merge!({ klass: klass }) elsif [:klass] parent_delegate(name) end # Do we need to delegate some methods from the parent node ? delegations = klass.instance_variable_get(:@delegations) if delegations && !delegations.empty? && [:delegate] def_delegators(name, *delegations) parent_delegate(*delegations) end structure << .merge(opts) define_method(name) do node_for_name(name) end end |
.structure ⇒ Array
Returns this message part class’ structure
209 210 211 |
# File 'lib/fix/protocol/message_part.rb', line 209 def self.structure @structure ||= [] end |
.unordered(name, opts = {}, &block) ⇒ Object
Defines an unordered fields collection
167 168 169 |
# File 'lib/fix/protocol/message_part.rb', line 167 def self.unordered(name, opts = {}, &block) part(name, opts.merge({ node_type: :unordered }), &block) end |
Instance Method Details
#dump ⇒ String
Dumps this message part as a FIX message fragment
35 36 37 |
# File 'lib/fix/protocol/message_part.rb', line 35 def dump nodes.map(&:dump).join end |
#errors ⇒ Array
Returns the errors for this instance
218 219 220 |
# File 'lib/fix/protocol/message_part.rb', line 218 def errors [nodes.map(&:errors), nodes.map(&:parse_failure)].flatten.compact end |
#initialize_node(node) ⇒ Object
Initializes a node depending on its type, this is called when initializing a message part instance by the constructor. Usually one node is initialized for each structure element
61 62 63 64 65 66 67 68 69 |
# File 'lib/fix/protocol/message_part.rb', line 61 def initialize_node(node) if [:unordered, :part].include?(node[:node_type]) nodes << node[:klass].new(node) elsif node[:node_type] == :field nodes << FP::Field.new(node) elsif node[:node_type] == :collection nodes << FP::RepeatingMessagePart.new(node) end end |
#node_for_name(n) ⇒ Object
Searches the immediate hierarchy by node name to return the requested node
86 87 88 |
# File 'lib/fix/protocol/message_part.rb', line 86 def node_for_name(n) nodes.find { |node| node.name.to_s == n.to_s } end |
#nodes ⇒ Array
The message part nodes, they’ll be either a FP::Field
, an FP::RepeatingMessagePart
or a FP::MessagePart
76 77 78 |
# File 'lib/fix/protocol/message_part.rb', line 76 def nodes @nodes ||= [] end |
#parse(str) ⇒ String
Parses a full or partial FIX message string into the message part nodes
44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/fix/protocol/message_part.rb', line 44 def parse(str) left_to_parse = str nodes.each do |node| unless parse_failure left_to_parse = node.parse(left_to_parse) self.parse_failure = node.parse_failure end end left_to_parse end |