Class: Y::Doc

Inherits:
Object
  • Object
show all
Defined in:
lib/y/doc.rb

Overview

Examples:

Create a local and remote doc and syncs the diff

local = Y::Doc.new
local_map = local.get_map("my map")
local_map[:hello] = "world"

remote = Y::Doc.new

diff = local.diff(remote.state)
remote.sync(diff)

remote_map = remote.get_map("my_map")
pp remote_map.to_h #=> {hello: "world"}

Instance Method Summary collapse

Instance Method Details

#attach(&block) ⇒ Object

Example: Attach listener to document changes

doc = described_class.new
doc.attach { |update| pp update }

text = doc.get_text("my text")
text << "1"


34
35
36
# File 'lib/y/doc.rb', line 34

def attach(&block)
  ydoc_observe_update(block)
end

#commitvoid

This method returns an undefined value.

Commit current transaction

This is a convenience method that invokes Transaction#commit on the current transaction used by this document.



44
45
46
# File 'lib/y/doc.rb', line 44

def commit
  current_transaction(&:commit)
end

#diff(state = ZERO_STATE) ⇒ ::Array<Integer>

Create a diff between this document and another document. The diff is created based on a state vector provided by the other document. It only returns the missing blocks, as binary encoded sequence.

Parameters:

  • state (::Array<Integer>) (defaults to: ZERO_STATE)

    The state to create the diff against

Returns:

  • (::Array<Integer>)

    Binary encoded diff



54
55
56
# File 'lib/y/doc.rb', line 54

def diff(state = ZERO_STATE)
  current_transaction { |tx| ydoc_encode_diff_v1(tx, state) }
end

#full_diff::Array<Integer>

Creates a full diff for the current document. It is similar to #diff, but does not take a state. Instead it creates an empty state and passes it to the encode_diff function.

Returns:

  • (::Array<Integer>)

    Binary encoded diff



63
64
65
# File 'lib/y/doc.rb', line 63

def full_diff
  diff
end

#get_array(name, values = nil) ⇒ Y::Array

Gets or creates a new array by name

If the optional values array is present, fills the array up with elements from the provided array. If the array already exists and isn’t empty, elements are pushed to the end of the array.

Parameters:

  • name (String)

    The name of the structure

  • values (::Array) (defaults to: nil)

    Optional initial values

Returns:



76
77
78
79
80
81
# File 'lib/y/doc.rb', line 76

def get_array(name, values = nil)
  array = ydoc_get_or_insert_array(name)
  array.document = self
  array.concat(values) unless values.nil?
  array
end

#get_map(name, input = nil) ⇒ Y::Map

Gets or creates a new map by name

If the optional input hash is present, fills the map up with key-value pairs from the provided input hash. If the map already exists and isn’t empty, any existing keys are overridden and new keys are added.

Parameters:

  • name (String)

    The name of the structure

  • input (Hash) (defaults to: nil)

    Optional initial map key-value pairs

Returns:



92
93
94
95
96
97
# File 'lib/y/doc.rb', line 92

def get_map(name, input = nil)
  map = ydoc_get_or_insert_map(name)
  map.document = self
  input&.each { |key, value| map[key] = value }
  map
end

#get_text(name, input = nil) ⇒ Y::Text

Gets or creates a new text by name

If the optional input string is provided, fills a new text with the string at creation time. If the text isn’t new and not empty, appends the input to the end of the text.

Parameters:

  • name (String)

    The name of the structure

  • input (String) (defaults to: nil)

    Optional initial text value

Returns:



108
109
110
111
112
113
# File 'lib/y/doc.rb', line 108

def get_text(name, input = nil)
  text = ydoc_get_or_insert_text(name)
  text.document = self
  text << input unless input.nil?
  text
end

#get_xml_element(name) ⇒ Y::XMLElement

Gets or creates a new XMLElement by name

Parameters:

  • name (String)

    The name of the structure

Returns:



119
120
121
122
123
# File 'lib/y/doc.rb', line 119

def get_xml_element(name)
  xml_element = ydoc_get_or_insert_xml_element(name)
  xml_element.document = self
  xml_element
end

#get_xml_fragment(name) ⇒ Y::XMLFragment

Gets or creates a new XMLFragment by name

Parameters:

  • name (String)

    The name of the fragment

Returns:

  • (Y::XMLFragment)


129
130
131
132
133
# File 'lib/y/doc.rb', line 129

def get_xml_fragment(name)
  xml_fragment = ydoc_get_or_insert_xml_fragment(name)
  xml_fragment.document = self
  xml_fragment
end

#get_xml_text(name, input = nil) ⇒ Y::XMLText

Gets or creates a new XMLText by name

Parameters:

  • name (String)

    The name of the structure

  • input (String) (defaults to: nil)

    Optional initial text value

Returns:



140
141
142
143
144
145
# File 'lib/y/doc.rb', line 140

def get_xml_text(name, input = nil)
  xml_text = ydoc_get_or_insert_xml_text(name)
  xml_text.document = self
  xml_text << input unless input.nil?
  xml_text
end

#restore(full_diff) ⇒ void

This method returns an undefined value.

Restores a specific document from an update that contains full state

This is doing the same as #sync, but it exists to be explicit about the intent. This is the companion to #full_diff.

Parameters:

  • full_diff (::Array<Integer>)

    Binary encoded update



170
171
172
# File 'lib/y/doc.rb', line 170

def restore(full_diff)
  current_transaction { |tx| tx.apply(full_diff) }
end

#state::Array<Integer>

Creates a state vector of this document. This can be used to compare the state of two documents with each other and to later on sync them.

Returns:

  • (::Array<Integer>)

    Binary encoded state vector



151
152
153
# File 'lib/y/doc.rb', line 151

def state
  current_transaction(&:state)
end

#sync(diff) ⇒ void

This method returns an undefined value.

Synchronizes this document with the diff from another document

Parameters:

  • diff (::Array<Integer>)

    Binary encoded update



159
160
161
# File 'lib/y/doc.rb', line 159

def sync(diff)
  current_transaction { |tx| tx.apply(diff) }
end

#transactObject

Creates a new transaction



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/y/doc.rb', line 175

def transact
  # 1. release potentially existing transaction
  if @current_transaction
    @current_transaction.free
    @current_transaction = nil
  end

  # 2. store new transaction in instance variable
  @current_transaction = ydoc_transact
  @current_transaction.document = self

  # 3. call block with reference to current_transaction
  yield @current_transaction
ensure
  @current_transaction&.free
  @current_transaction = nil
end