### Install Diagrams Gem Source: https://github.com/seuros/diagram-ruby/blob/master/README.md Instructions on how to add the Diagrams gem to your Ruby project's Gemfile or install it directly via the command line. ```ruby gem 'diagram', '~> 0.3.0' # Or appropriate version constraint ``` ```bash bundle install ``` ```bash gem install diagram ``` -------------------------------- ### Ruby Gem Local Installation and Release Workflow Source: https://github.com/seuros/diagram-ruby/blob/master/README.md Outlines the shell commands for installing the `diagram-ruby` gem onto a local machine and the process for releasing a new version, including updating the version number and pushing to rubygems.org. ```Shell bundle exec rake install # To release a new version: # 1. Update the version number in lib/diagrams/version.rb # 2. Run the release command: bundle exec rake release ``` -------------------------------- ### Creating, Serializing, and Deserializing a Gantt Diagram in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/gantt_diagram.md This example demonstrates creating a Gantt chart for a small project, including sections, tasks with different statuses (done, active, future), and dependencies, then serializing and deserializing it. It covers grouping tasks into sections, defining tasks with labels, statuses (`:done`, `:active`, or future implied), specifying start times using absolute dates (`2024-01-01`) or relative dependencies (`after task_id`, `after task_id1, task_id2`), specifying durations (e.g., `7d`, `10d`), and the standard serialization and deserialization workflow. ```Ruby require 'diagrams' # Assuming the gem is loaded require 'json' # For JSON serialization/deserialization require 'pp' # For pretty printing hashes # 1. Create a new Gantt diagram # Note: Date formats and axis formatting are typically handled by rendering tools. # This structure focuses on the task data. diagram = Diagrams::GanttDiagram.new(version: '0.5') # 2. Add sections and tasks # Sections group related tasks. diagram.add_section('Planning Phase') # Tasks require an ID, label, status, and start/duration information. # Status can be :done, :active, or inferred as future if start is later. # Start/duration can be dates, IDs (for dependencies), or relative terms. task1 = diagram.add_task(id: 'task1', label: 'Market Research', status: :done, start: '2024-01-01', duration: '7d') task2 = diagram.add_task(id: 'task2', label: 'Define Requirements', status: :done, start: 'after task1', duration: '5d') # Dependency task3 = diagram.add_task(id: 'task3', label: 'Create Mockups', status: :active, start: 'after task2', duration: '10d') diagram.add_section('Development Phase') task4 = diagram.add_task(id: 'task4', label: 'Setup Environment', status: :active, start: 'after task2', duration: '3d') # Parallel to task3 task5 = diagram.add_task(id: 'task5', label: 'Implement Core Features', start: 'after task3, task4', duration: '20d') # Depends on two tasks task6 = diagram.add_task(id: 'task6', label: 'Testing', start: 'after task5', duration: '10d') # 3. Serialize to Hash diagram_hash = diagram.to_h puts "Serialized Hash:" pp diagram_hash # Output will be a hash like: # {:type=>"gantt_diagram", # :version=>"0.5", # :checksum=>"...", # :data=> # {:sections=> # [{:title=>"Planning Phase", # :tasks=> # [{:id=>"task1", :label=>"Market Research", :status=>:done, :start=>"2024-01-01", :duration=>"7d"}, # {:id=>"task2", :label=>"Define Requirements", :status=>:done, :start=>"after task1", :duration=>"5d"}, # {:id=>"task3", :label=>"Create Mockups", :status=>:active, :start=>"after task2", :duration=>"10d"}]}, # {:title=>"Development Phase", # :tasks=> # [{:id=>"task4", :label=>"Setup Environment", :status=>:active, :start=>"after task2", :duration=>"3d"}, # {:id=>"task5", :label=>"Implement Core Features", :start=>"after task3, task4", :duration=>"20d"}, # {:id=>"task6", :label=>"Testing", :start=>"after task5", :duration=>"10d"}]}]}} # 4. Deserialize from Hash reloaded_diagram = Diagrams::Base.from_hash(diagram_hash) # 5. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Access data from reloaded diagram puts "Number of sections: #{reloaded_diagram.sections.size}" # => 2 puts "First task label: #{reloaded_diagram.sections[0].tasks[0].label}" # => Market Research puts "Status of Create Mockups: #{reloaded_diagram.sections[0].tasks[2].status}" # => :active puts "Start dependency of Testing task: #{reloaded_diagram.sections[1].tasks[2].start}" # => after task5 ``` -------------------------------- ### Create, Serialize, and Deserialize a Ruby State Diagram Source: https://github.com/seuros/diagram-ruby/blob/master/docs/state_diagram.md This example demonstrates creating a state diagram for a simple video player, including composite states, forks/joins (for concurrency), notes, and transitions, then serializing and deserializing it. It covers defining states, transitions between them, and the standard serialization/deserialization workflow. ```Ruby require 'diagrams' # Assuming the gem is loaded require 'json' # For JSON serialization/deserialization require 'pp' # For pretty printing hashes # 1. Create a new State diagram diagram = Diagrams::StateDiagram.new(version: '1.2') # 2. Define states # Use state IDs for transitions. Labels are for display. idle = Diagrams::Elements::State.new(id: 'Idle', label: 'Idle') loading = Diagrams::Elements::State.new(id: 'Loading', label: 'Loading') playing = Diagrams::Elements::State.new(id: 'Playing', label: 'Playing') paused = Diagrams::Elements::State.new(id: 'Paused', label: 'Paused') start = Diagrams::Elements::State.new(id: '[*]', label: '[*]') diagram.add_state(idle) diagram.add_state(loading) diagram.add_state(playing) diagram.add_state(paused) diagram.add_state(start) # 3. Define top-level transitions between states diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: '[*]', target_state_id: 'Idle')) # Initial state diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Idle', target_state_id: 'Loading', label: 'Play clicked')) diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Loading', target_state_id: 'Playing', label: 'Video loaded')) diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Loading', target_state_id: 'Idle', label: 'Error loading')) diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Playing', target_state_id: 'Paused', label: 'Pause clicked')) diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Playing', target_state_id: 'Idle', label: 'Stop clicked')) diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Paused', target_state_id: 'Playing', label: 'Play clicked')) diagram.add_transition(Diagrams::Elements::Transition.new(source_state_id: 'Paused', target_state_id: 'Idle', label: 'Stop clicked')) # 4. Serialize to Hash diagram_hash = diagram.to_h puts "Serialized Hash:" pp diagram_hash # 6. Deserialize from Hash reloaded_diagram = Diagrams::Base.from_hash(diagram_hash) # 7. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Access data from reloaded diagram puts "Number of top-level states: #{reloaded_diagram.states.size}" # => 4 puts "First transition label: #{reloaded_diagram.transitions[1].label}" # => Play clicked ``` -------------------------------- ### Serialize and Deserialize Diagrams to Hash/JSON Source: https://github.com/seuros/diagram-ruby/blob/master/README.md Shows how to convert diagram objects into Hash or JSON formats for persistence or transfer, and how to load them back into Ruby objects. Includes an example of content equality checking. ```ruby # Serialization flowchart_hash = flowchart.to_h flowchart_json = flowchart.to_json puts flowchart_json # => {"type":"FlowchartDiagram","version":"1.0","checksum":"...","data":{"nodes":[...],"edges":[...]}} # Deserialization (using the Base class factory) loaded_flowchart = Diagrams::Base.from_json(flowchart_json) # or # loaded_flowchart = Diagrams::Base.from_hash(flowchart_hash) puts "Loaded diagram type: #{loaded_flowchart.class}" # => Loaded diagram type: Diagrams::FlowchartDiagram puts "Loaded diagram version: #{loaded_flowchart.version}" # => Loaded diagram version: 1.0 # Verify content equality (ignores version) original_flowchart = Diagrams::FlowchartDiagram.new( nodes: [node1, node2, node3], edges: [edge1, edge2], version: 'Different Version' # Version doesn't affect equality check ) puts "Diagrams have same content? #{loaded_flowchart == original_flowchart}" # => Diagrams have same content? true ``` -------------------------------- ### Usage Example for Custom Diagram Type in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/creating_custom_diagrams.md This Ruby code demonstrates how to instantiate and use a custom diagram type (`MyCustomDiagram`) along with its custom elements (`MyCustomElement`). It shows how to add data points and serialize the diagram to JSON. ```ruby require 'diagrams' # Ensure your custom files are loaded if not using Zeitwerk correctly # require_relative 'path/to/diagrams/my_custom_diagram' # require_relative 'path/to/diagrams/elements/my_custom_element' # Create instance my_diagram = Diagrams::MyCustomDiagram.new(title: 'My Data') point1 = Diagrams::Elements::MyCustomElement.new(name: 'Point A', value: 100) my_diagram.add_data_point(point1) # Serialize json_data = my_diagram.to_json puts json_data # => {"type":"MyCustomDiagram","version":1,"checksum":"...","data":{"title":"My Data","custom_data_points":[{"name":"Point A","value":100}]}} ``` -------------------------------- ### Create, Serialize, and Deserialize a Pie Diagram in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/pie_diagram.md This example demonstrates the full lifecycle of a `Diagrams::PieDiagram` in Ruby. It covers initializing a new diagram with a title, adding data slices (labels and values), calculating an 'Others' category, and then performing serialization to a hash and deserialization back into a `Diagrams` object. Verification steps are included to ensure data integrity after the round-trip serialization process. ```ruby require 'diagrams' # Assuming the gem is loaded require 'json' # For JSON serialization/deserialization require 'pp' # For pretty printing hashes # 1. Create a new Pie diagram diagram = Diagrams::PieDiagram.new(title: 'Browser Market Share - Q1 2025', version: '3.0') # 2. Add data slices # Each slice needs a label (String) and a value (Numeric). chrome = Diagrams::Elements::Slice.new(label: 'Chrome', value: 65.8) safari = Diagrams::Elements::Slice.new(label: 'Safari', value: 18.5) edge = Diagrams::Elements::Slice.new(label: 'Edge', value: 5.2) firefox = Diagrams::Elements::Slice.new(label: 'Firefox', value: 3.1) # Add a slice representing multiple smaller browsers others = Diagrams::Elements::Slice.new(label: 'Others', value: 100 - (65.8 + 18.5 + 5.2 + 3.1)) diagram.add_slice(chrome) diagram.add_slice(safari) diagram.add_slice(edge) diagram.add_slice(firefox) diagram.add_slice(others) # 3. Serialize to Hash diagram_hash = diagram.to_h puts "Serialized Hash:" pp diagram_hash # Output will be a hash like: # {:type=>"pie_diagram", # :version=>"3.0", # :checksum=>"...", # :data=> # {:title=>"Browser Market Share - Q1 2025", # :slices=> # [{:label=>"Chrome", :value=>65.8}, # {:label=>"Safari", :value=>18.5}, # {:label=>"Edge", :value=>5.2}, # {:label=>"Firefox", :value=>3.1}, # {:label=>"Others", :value=>7.399999999999991}]}} # Note potential floating point inaccuracies # 4. Deserialize from Hash reloaded_diagram = Diagrams::Base.from_hash(diagram_hash) # 5. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Access data from reloaded diagram puts "Reloaded title: #{reloaded_diagram.title}" # => Browser Market Share - Q1 2025 puts "Number of slices: #{reloaded_diagram.slices.size}" # => 5 # Find a specific slice edge_slice = reloaded_diagram.slices.find { |s| s.label == 'Edge' } puts "Value for Edge: #{edge_slice.value if edge_slice}" # => 5.2 ``` -------------------------------- ### Creating and Managing an ER Diagram with Ruby Diagrams Gem Source: https://github.com/seuros/diagram-ruby/blob/master/docs/er_diagram.md This Ruby example demonstrates the full lifecycle of creating an Entity Relationship Diagram (ERD) for an online store. It covers defining entities with various attribute types (PK, FK, UK), establishing identifying and non-identifying relationships with specific cardinalities (Crow's Foot notation), and then serializing the diagram to a hash and deserializing it back for verification. ```Ruby require 'diagrams' # Assuming the gem is loaded require 'json' # For JSON serialization/deserialization require 'pp' # For pretty printing hashes # 1. Create a new ER diagram diagram = Diagrams::ERDiagram.new(version: '1.0') # 2. Add entities with attributes (type, name, keys, comment) diagram.add_entity(name: 'CUSTOMER', attributes: [ { type: 'int', name: 'id', keys: [:PK], comment: 'Unique customer ID' }, { type: 'varchar(100)', name: 'name' }, { type: 'varchar(255)', name: 'email', keys: [:UK], comment: 'Unique email' }, { type: 'timestamp', name: 'created_at' } ]) diagram.add_entity(name: 'ADDRESS', attributes: [ { type: 'int', name: 'id', keys: [:PK] }, { type: 'int', name: 'customer_id', keys: [:FK] }, { type: 'varchar(50)', name: 'type', comment: 'e.g., Billing, Shipping' }, { type: 'varchar(255)', name: 'street' }, { type: 'varchar(100)', name: 'city' }, { type: 'varchar(10)', name: 'zip_code' } ]) diagram.add_entity(name: 'ORDER', attributes: [ { type: 'int', name: 'id', keys: [:PK] }, { type: 'int', name: 'customer_id', keys: [:FK] }, { type: 'int', name: 'shipping_address_id', keys: [:FK] }, { type: 'timestamp', name: 'order_date' }, { type: 'decimal(10,2)', name: 'total_amount' } ]) diagram.add_entity(name: 'ORDER_ITEM', attributes: [ { type: 'int', name: 'order_id', keys: [:PK, :FK] }, # Composite PK { type: 'int', name: 'product_id', keys: [:PK, :FK] }, # Composite PK { type: 'int', name: 'quantity' }, { type: 'decimal(10,2)', name: 'price_per_unit' } ]) diagram.add_entity(name: 'PRODUCT', attributes: [ { type: 'int', name: 'id', keys: [:PK] }, { type: 'varchar(20)', name: 'sku', keys: [:UK] }, { type: 'varchar(255)', name: 'name' }, { type: 'text', name: 'description' }, { type: 'decimal(10,2)', name: 'current_price' } ]) # 3. Add relationships # Customer ||--|{ Address : "has" (One Customer has Zero or More Addresses) diagram.add_relationship( entity1: 'CUSTOMER', entity2: 'ADDRESS', cardinality1: :ONE_ONLY, cardinality2: :ZERO_OR_MORE, label: 'has' # identifying: false (default) ) # Customer ||--o{ Order : "places" (One Customer places Zero or More Orders) diagram.add_relationship( entity1: 'CUSTOMER', entity2: 'ORDER', cardinality1: :ONE_ONLY, cardinality2: :ZERO_OR_MORE, label: 'places' ) # Order ||--|{ Order_Item : "contains" (One Order contains One or More Order Items - Identifying) diagram.add_relationship( entity1: 'ORDER', entity2: 'ORDER_ITEM', cardinality1: :ONE_ONLY, cardinality2: :ONE_OR_MORE, identifying: true, label: 'contains' ) # Product ||--o{ Order_Item : "appears in" (One Product appears in Zero or More Order Items - Identifying) diagram.add_relationship( entity1: 'PRODUCT', entity2: 'ORDER_ITEM', cardinality1: :ONE_ONLY, cardinality2: :ZERO_OR_MORE, identifying: true, label: 'appears in' ) # Order }o..o| Address : "ships to" (One Order ships to Zero or One Addresses - Non-identifying, Optional) diagram.add_relationship( entity1: 'ORDER', entity2: 'ADDRESS', cardinality1: :ZERO_OR_MORE, cardinality2: :ZERO_OR_ONE, identifying: false, label: 'ships to' ) # 4. Serialize to Hash diagram_hash = diagram.to_h puts "Serialized Hash:" pp diagram_hash # Output will be a hash representing the ERD structure. # 5. Deserialize from Hash reloaded_diagram = Diagrams::Base.from_hash(diagram_hash) # 6. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" ``` -------------------------------- ### Create, Serialize, and Deserialize a Ruby Flowchart Diagram Source: https://github.com/seuros/diagram-ruby/blob/master/docs/flowchart_diagram.md This example demonstrates creating a flowchart for a simple login process using the `diagrams` gem in Ruby. It covers adding nodes with unique IDs and labels, connecting them with edges (including labeled decision branches), and then serializing the diagram to a hash and deserializing it back. The verification steps confirm the integrity of the reloaded diagram. ```ruby require 'diagrams' # Assuming the gem is loaded require 'json' # For JSON serialization/deserialization require 'pp' # For pretty printing hashes # 1. Create a new Flowchart diagram diagram = Diagrams::FlowchartDiagram.new(version: '2.1') # 2. Add nodes with different labels # Node shapes are typically handled by the rendering tool (like Mermaid), # but we can represent the *intent* in the label or use specific node types if defined. # Here, we create `Node` objects first and then add them to the diagram. start_node = Diagrams::Elements::Node.new(id: 'start', label: 'Start') input_node = Diagrams::Elements::Node.new(id: 'input', label: 'Enter Credentials') decision_node = Diagrams::Elements::Node.new(id: 'check', label: 'Credentials Valid?') success_node = Diagrams::Elements::Node.new(id: 'success', label: 'Login Successful') fail_node = Diagrams::Elements::Node.new(id: 'fail', label: 'Login Failed') end_node = Diagrams::Elements::Node.new(id: 'end', label: 'End') diagram.add_node(start_node) diagram.add_node(input_node) diagram.add_node(decision_node) diagram.add_node(success_node) diagram.add_node(fail_node) diagram.add_node(end_node) # 3. Add edges connecting the nodes, with labels for decisions diagram.add_edge(Diagrams::Elements::Edge.new(source_id: start_node.id, target_id: input_node.id)) diagram.add_edge(Diagrams::Elements::Edge.new(source_id: input_node.id, target_id: decision_node.id)) diagram.add_edge(Diagrams::Elements::Edge.new(source_id: decision_node.id, target_id: success_node.id, label: 'Yes')) diagram.add_edge(Diagrams::Elements::Edge.new(source_id: decision_node.id, target_id: fail_node.id, label: 'No')) diagram.add_edge(Diagrams::Elements::Edge.new(source_id: success_node.id, target_id: end_node.id)) diagram.add_edge(Diagrams::Elements::Edge.new(source_id: fail_node.id, target_id: end_node.id)) # 4. Serialize to Hash diagram_hash = diagram.to_h puts "Serialized Hash:" pp diagram_hash # Output will be a hash like: # {:type=>"flowchart_diagram", # :version=>"2.1", # :checksum=>"...", # :data=> # {:nodes=> # [{:id=>"start", :label=>"Start"}, # {:id=>"input", :label=>"Enter Credentials"}, # {:id=>"check", :label=>"Credentials Valid?"}, # {:id=>"success", :label=>"Login Successful"}, # {:id=>"fail", :label=>"Login Failed"}, # {:id=>"end", :label=>"End"}], # :edges=> # [{:source_id=>"start", :target_id=>"input"}, # {:source_id=>"input", :target_id=>"check"}, # {:source_id=>"check", :target_id=>"success", :label=>"Yes"}, # {:source_id=>"check", :target_id=>"fail", :label=>"No"}, # {:source_id=>"success", :target_id=>"end"}, # {:source_id=>"fail", :target_id=>"end"}]}} # 5. Deserialize from Hash reloaded_diagram = Diagrams::Base.from_hash(diagram_hash) # 6. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Access data from reloaded diagram puts "Number of nodes: #{reloaded_diagram.nodes.size}" # => 6 puts "Decision node label: #{reloaded_diagram.find_node('check').label}" # => Credentials Valid? puts "Edge from decision to success label: #{reloaded_diagram.edges.find { |e| e.source_id == 'check' && e.target_id == 'success'}.label}" # => Yes ``` -------------------------------- ### Ruby: Create, Serialize, and Deserialize Gitgraph Diagram Source: https://github.com/seuros/diagram-ruby/blob/master/docs/gitgraph_diagram.md This example demonstrates creating a simple Git history using `Diagrams::GitgraphDiagram`, adding commits, branches, and merges. It then shows how to serialize the diagram object to a Ruby hash and deserialize it back, verifying data integrity. The `Diagrams::Base.from_json` method is also mentioned as an alternative for JSON string representations. ```ruby require 'diagrams' # Assuming the gem is loaded # 1. Create a new Gitgraph diagram diagram = Diagrams::GitgraphDiagram.new(version: '1.1') # 2. Add commits and branches c1 = diagram.commit(id: 'C1', message: 'Initial commit') diagram.branch(name: 'develop') # Creates 'develop' and checks it out c2 = diagram.commit(id: 'D1', message: 'Feature work on develop') diagram.checkout(name: 'master') c3 = diagram.commit(id: 'C2', message: 'Hotfix on master') merge_commit = diagram.merge(from_branch_name: 'develop', id: 'M1', tag: 'v1.0-merge') c4 = diagram.commit(id: 'C3', message: 'Post-merge commit') # 3. Serialize to Hash diagram_hash = diagram.to_h puts "Serialized Hash:" pp diagram_hash # Output will be a hash like: # {:type=>"gitgraph_diagram", # :version=>"1.1", # :checksum=>"...", # :data=> # {:commits=> # [{:id=>"C1", :parent_ids=>[], :branch_name=>"master", :type=>:NORMAL, :message=>"Initial commit"}, # {:id=>"D1", :parent_ids=>["C1"], :branch_name=>"develop", :type=>:NORMAL, :message=>"Feature work on develop"}, # {:id=>"C2", :parent_ids=>["C1"], :branch_name=>"master", :type=>:NORMAL, :message=>"Hotfix on master"}, # {:id=>"M1", :parent_ids=>["C2", "D1"], :branch_name=>"master", :type=>:MERGE, :tag=>"v1.0-merge", :message=>"Merge branch 'develop' into master"}, # {:id=>"C3", :parent_ids=>["M1"], :branch_name=>"master", :type=>:NORMAL, :message=>"Post-merge commit"}], # :branches=> # [{:name=>"master", :start_commit_id=>"C1", :head_commit_id=>"C3"}, # {:name=>"develop", :start_commit_id=>"C1", :head_commit_id=>"D1"}], # :commit_order=>["C1", "D1", "C2", "M1", "C3"], # :current_branch_name=>"master"}} # 4. Deserialize from Hash reloaded_diagram = Diagrams::Base.from_hash(diagram_hash) # 5. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Uses checksum and class for equality # Access data from reloaded diagram puts "Reloaded commit M1 tag: #{reloaded_diagram.commits['M1'].tag}" puts "Reloaded master head: #{reloaded_diagram.branches['master'].head_commit_id}" ``` -------------------------------- ### Ruby: Create, Serialize, and Deserialize Timeline Diagram Source: https://github.com/seuros/diagram-ruby/blob/master/docs/timeline_diagram.md This example demonstrates creating a `TimelineDiagram` instance, populating it with chronological events related to Donald Trump's political career and the MAGA movement, including hypothetical future events. It then shows how to serialize the diagram object to a JSON string and deserialize it back into a `Diagrams::Base` object, verifying data integrity using checksums. ```ruby require 'diagrams' require 'json' require 'pp' # 1. Create a new Timeline diagram diagram = Diagrams::TimelineDiagram.new(title: 'Timeline Example: Trump Political Career & MAGA Movement', version: '1.1') # 2. Add sections and periods/events chronologically diagram.add_section('Campaign & Election') diagram.add_period(period_label: '2015', events: 'Announces presidential campaign') diagram.add_period(period_label: '2016', events: 'Wins presidential election') diagram.add_section('Presidency') diagram.add_period(period_label: '2017', events: [ 'Inaugurated as 45th President', 'Signs EO 13769 (Travel Ban)', 'Tax Cuts and Jobs Act signed' ]) diagram.add_period(period_label: '2019', events: 'House initiates impeachment inquiry') diagram.add_period(period_label: '2020', events: ['Addresses COVID-19 pandemic response', 'Presidential election held']) diagram.add_period(period_label: 'Jan 2021', events: ['January 6th events at US Capitol', 'Presidency concludes']) diagram.add_section('Post-Presidency & Future') diagram.add_period(period_label: '2021-2024', events: ['Continued political activity', 'MAGA movement remains influential']) # Hypothetical future event for example purposes diagram.add_period(period_label: 'Jan 2025', events: 'Inaugurated as 47th President (Hypothetical)') # 3. Serialize to JSON json_string = diagram.to_json puts "Serialized JSON:" puts JSON.pretty_generate(JSON.parse(json_string)) # 4. Deserialize from JSON reloaded_diagram = Diagrams::Base.from_json(json_string) # 5. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Access data from reloaded diagram puts "Reloaded title: #{reloaded_diagram.title}" puts "Number of sections: #{reloaded_diagram.sections.size}" puts "Events in Jan 2025: #{reloaded_diagram.sections.last.periods.last.events.map(&:description)}" ``` -------------------------------- ### Create, Serialize, and Deserialize Class Diagram in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/class_diagram.md This example demonstrates creating a class diagram with multiple classes, attributes, methods, inheritance, and association using the `Diagrams` gem. It shows how to define `ClassEntity` objects for `Vehicle`, `Car`, `Engine`, and `Driver`, and then add `inheritance`, `composition`, and `association` relationships. The diagram is then serialized to JSON, pretty-printed, and subsequently deserialized for verification. The expected JSON output structure is also provided. ```ruby require 'diagrams' # Assuming the gem is loaded require 'json' # For JSON serialization/deserialization require 'pp' # For pretty printing hashes # 1. Create a new Class diagram diagram = Diagrams::ClassDiagram.new(version: '1.0') # 2. Add classes with attributes and methods vehicle = Diagrams::Elements::ClassEntity.new( name: 'Vehicle', attributes: ['+max_speed: int', '-current_speed: int'], methods: ['+start()', '+stop()', '#accelerate(amount: int)'] ) car = Diagrams::Elements::ClassEntity.new( name: 'Car', attributes: ['-num_doors: int'], methods: ['+open_trunk()'] ) engine = Diagrams::Elements::ClassEntity.new( name: 'Engine', attributes: ['~horsepower: int'], methods: ['+ignite()'] ) driver = Diagrams::Elements::ClassEntity.new( name: 'Driver', attributes: ['+name: string'], methods: ['+drive(vehicle: Vehicle)'] ) diagram.add_class(vehicle) diagram.add_class(car) diagram.add_class(engine) diagram.add_class(driver) # 3. Add relationships # Inheritance (Car -> Vehicle) diagram.add_relationship( Diagrams::Elements::Relationship.new( type: 'inheritance', source_class_name: car.name, # Use class name as ID target_class_name: vehicle.name ) ) # Composition (Car has an Engine) diagram.add_relationship( Diagrams::Elements::Relationship.new( type: 'composition', source_class_name: car.name, target_class_name: engine.name, label: '1' # Cardinality (Car has 1 Engine) ) ) # Association (Driver drives a Vehicle) diagram.add_relationship( Diagrams::Elements::Relationship.new( type: 'association', source_class_name: driver.name, target_class_name: vehicle.name, label: 'drives >' # Label and direction ) ) # 4. Serialize to JSON json_string = diagram.to_json puts "Serialized JSON:" puts JSON.pretty_generate(JSON.parse(json_string)) # Output will be a JSON string representing the class diagram structure. # 5. Deserialize from JSON reloaded_diagram = Diagrams::Base.from_json(json_string) # 6. Verify puts "\nVerification:" puts "Reloaded diagram class: #{reloaded_diagram.class}" puts "Original checksum: #{diagram.checksum}" puts "Reloaded checksum: #{reloaded_diagram.checksum}" puts "Checksums match? #{diagram.checksum == reloaded_diagram.checksum}" puts "Diagrams equal? #{diagram == reloaded_diagram}" # Access data from reloaded diagram puts "Number of classes: #{reloaded_diagram.classes.size}" # => 4 puts "Car attributes: #{reloaded_diagram.find_class('Car').attributes}" # => ["-num_doors: int"] puts "Number of relationships: #{reloaded_diagram.relationships.size}" # => 3 puts "Driver relationship type: #{reloaded_diagram.relationships.last.type}" # => :association ``` ```json { "type": "class_diagram", "version": "1.0", "checksum": "...", "data": { "classes": [ { "name": "Vehicle", "attributes": ["+max_speed: int", "-current_speed: int"], "methods": ["+start()", "+stop()", "#accelerate(amount: int)"] }, { "name": "Car", "attributes": ["-num_doors: int"], "methods": ["+open_trunk()"] }, { "name": "Engine", "attributes": ["~horsepower: int"], "methods": ["+ignite()"] }, { "name": "Driver", "attributes": ["+name: string"], "methods": ["+drive(vehicle: Vehicle)"] } ], "relationships": [ { "type": "inheritance", "source_class_name": "Car", "target_class_name": "Vehicle" }, { "type": "composition", "source_class_name": "Car", "target_class_name": "Engine", "label": "1" }, { "type": "association", "source_class_name": "Driver", "target_class_name": "Vehicle", "label": "drives >" } ] } } ``` -------------------------------- ### Ruby Gem Development and Testing Commands Source: https://github.com/seuros/diagram-ruby/blob/master/README.md Provides shell commands for setting up the development environment, running tests, and accessing an interactive console for the `diagram-ruby` gem. ```Shell bin/setup bundle exec rake test bin/console ``` -------------------------------- ### Create and Populate Various Diagram Types Source: https://github.com/seuros/diagram-ruby/blob/master/README.md Demonstrates how to instantiate and populate different diagram types, including Flowcharts, Class Diagrams, and Pie Charts, using the Diagrams gem's API for nodes, edges, classes, relationships, and slices. ```ruby require 'diagram' # --- Flowchart Example --- flowchart = Diagrams::FlowchartDiagram.new(version: '1.0') # Create nodes (using Diagrams::Elements::Node) node1 = Diagrams::Elements::Node.new(id: 'start', label: 'Start Process') node2 = Diagrams::Elements::Node.new(id: 'step1', label: 'Do Something') node3 = Diagrams::Elements::Node.new(id: 'end', label: 'End Process') # Add nodes to the diagram flowchart.add_node(node1) flowchart.add_node(node2) flowchart.add_node(node3) # Create and add edges (using Diagrams::Elements::Edge) edge1 = Diagrams::Elements::Edge.new(source_id: 'start', target_id: 'step1') edge2 = Diagrams::Elements::Edge.new(source_id: 'step1', target_id: 'end', label: 'Finished') flowchart.add_edge(edge1) flowchart.add_edge(edge2) puts "Flowchart Nodes: #{flowchart.nodes.map(&:id)}" # => Flowchart Nodes: ["start", "step1", "end"] # --- Class Diagram Example --- class_diagram = Diagrams::ClassDiagram.new(version: 2) # Create class entities (using Diagrams::Elements::ClassEntity) user_class = Diagrams::Elements::ClassEntity.new( name: 'User', attributes: ['id: Integer', 'email: String'], methods: ['authenticate(password: String): Boolean'] ) order_class = Diagrams::Elements::ClassEntity.new( name: 'Order', attributes: ['order_id: Integer', 'amount: Float'] ) # Add classes class_diagram.add_class(user_class) class_diagram.add_class(order_class) # Create and add relationships (using Diagrams::Elements::Relationship) rel = Diagrams::Elements::Relationship.new( source_class_name: 'User', target_class_name: 'Order', type: 'has_many', label: 'places' ) class_diagram.add_relationship(rel) puts "Class Diagram Classes: #{class_diagram.classes.map(&:name)}" # => Class Diagram Classes: ["User", "Order"] # --- Pie Chart Example --- pie_chart = Diagrams::PieDiagram.new(title: 'Browser Share', version: '2024-Q1') # Create and add slices (using Diagrams::Elements::Slice) slice1 = Diagrams::Elements::Slice.new(label: 'Chrome', value: 65.5) slice2 = Diagrams::Elements::Slice.new(label: 'Firefox', value: 15.0) slice3 = Diagrams::Elements::Slice.new(label: 'Safari', value: 10.5) slice4 = Diagrams::Elements::Slice.new(label: 'Edge', value: 5.0) # slice5 = Diagrams::Elements::Slice.new(label: 'Other', value: 4.0) # Total must be <= 100 pie_chart.add_slice(slice1) pie_chart.add_slice(slice2) pie_chart.add_slice(slice3) pie_chart.add_slice(slice4) # pie_chart.add_slice(slice5) puts "Pie Chart Total: #{pie_chart.total_value}%" # => Pie Chart Total: 96.0% # (Examples for Gantt and State diagrams can be added similarly) ``` -------------------------------- ### Diagram Object Versioning and Checksum Fields Source: https://github.com/seuros/diagram-ruby/blob/master/README.md Documents the `version` and `checksum` fields of a diagram object, explaining their purpose, how the checksum is calculated and updated, and how the `==` operator uses the checksum for content comparison. ```APIDOC Diagram Object Fields: #version: A user-managed field (passed during initialization) for tracking revisions. #checksum: An automatically calculated SHA256 hash of the diagram's content (nodes, edges, etc.). This changes whenever the content is modified via methods like `add_node`, `add_slice`, etc. Comparison Operator: ==: Compares diagrams based on their type and checksum (content), ignoring the `version` field. ``` -------------------------------- ### Define Custom Diagram Class in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/creating_custom_diagrams.md This Ruby code defines `MyCustomDiagram`, a class inheriting from `Diagrams::Base`. It demonstrates how to initialize a custom diagram with specific data, implement `to_h_content` for serialization, and provide a `.from_h` class method for deserialization, including optional checksum verification. ```ruby # lib/diagrams/my_custom_diagram.rb require_relative 'base' # Require any custom element structs you might define # require_relative 'elements/my_custom_element' module Diagrams class MyCustomDiagram < Base # Use attr_reader for the specific data your diagram holds attr_reader :custom_data_points, :title # Define an initializer # - Accept specific data (e.g., `custom_data_points`) and optional `version`. # - Call `super(version: version)`. # - Store the data in instance variables. # - Perform any necessary validation (`validate_elements!`). # - Call `update_checksum!` at the end. def initialize(title: '', custom_data_points: [], version: 1) super(version: version) @title = title @custom_data_points = custom_data_points validate_elements! update_checksum! end # Implement the required #to_h_content method # This should return a hash containing only the specific data for your diagram type. # Ensure any custom element objects are also converted to hashes via their own `to_h`. # @return [Hash] def to_h_content { title: @title, # Example: assuming MyCustomElement has a #to_h method custom_data_points: @custom_data_points.map(&:to_h) } end # Implement the required .from_h class method # This is used by the `Diagrams::Base.from_h` factory for deserialization. # - It receives the `data_hash` (content from `to_h_content`), `version`, and `checksum`. # - Instantiate your custom element objects from the `data_hash`. # - Create a new instance of your diagram class using `new(...)`. # - Optionally, verify the passed `checksum` against the new instance's checksum. # @param data_hash [Hash] # @param version [String, Integer, nil] # @param checksum [String, nil] # @return [MyCustomDiagram] def self.from_h(data_hash, version:, checksum:) title = data_hash[:title] || '' points_data = data_hash[:custom_data_points] || [] # Example: assuming MyCustomElement can be created from a hash custom_points = points_data.map { |point_h| Elements::MyCustomElement.new(point_h.transform_keys(&:to_sym)) } diagram = new(title: title, custom_data_points: custom_points, version: version) # Optional checksum verification if checksum && diagram.checksum != checksum warn "Checksum mismatch for loaded MyCustomDiagram (version: #{version})." end diagram end # Add any methods specific to your diagram type def add_data_point(point) # Add validation if needed @custom_data_points << point update_checksum! point end private # Implement custom validation logic if needed def validate_elements! # Example: Ensure no duplicate points, etc. # raise ArgumentError, "Invalid data points" unless ... end end end ``` -------------------------------- ### Deserialize Diagram Object in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/creating_custom_diagrams.md This Ruby code snippet demonstrates how to deserialize a diagram object from JSON data using `Diagrams::Base.from_json`. It then prints the class and title of the loaded diagram, illustrating successful deserialization and access to custom diagram properties. For custom diagram types to integrate seamlessly, they must implement `initialize`, `#to_h_content`, and `.from_h`. ```Ruby loaded_diagram = Diagrams::Base.from_json(json_data) puts loaded_diagram.class # => Diagrams::MyCustomDiagram puts loaded_diagram.title # => My Data ``` -------------------------------- ### Define Custom Element Struct using Dry::Struct in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/creating_custom_diagrams.md This Ruby code defines `MyCustomElement` as a `Dry::Struct`, demonstrating how to create structured data elements for use within custom diagrams. It includes attribute definitions with type constraints and a `to_h` method for serialization. ```ruby # lib/diagrams/elements/my_custom_element.rb require 'dry-struct' require_relative 'node' # Or a dedicated types file to get Diagrams::Elements::Types module Diagrams module Elements class MyCustomElement < Dry::Struct include Diagrams::Elements::Types # Use shared types attribute :name, Types::Strict::String.constrained(min_size: 1) attribute :value, Types::Strict::Integer def to_h super # Dry::Struct provides a default end end end end ``` -------------------------------- ### Accessing Reloaded Diagram Entities and Relationships in Ruby Source: https://github.com/seuros/diagram-ruby/blob/master/docs/er_diagram.md This Ruby snippet demonstrates how to programmatically access and inspect elements within a reloaded diagram object. It shows how to retrieve the total number of entities, find a specific entity by name, list its attributes, locate a relationship by its label, and check its properties like identifying status and cardinality. ```Ruby puts "Number of entities: #{reloaded_diagram.entities.size}" # => 5 order_item = reloaded_diagram.find_entity('ORDER_ITEM') puts "ORDER_ITEM attributes: #{order_item.entity_attributes.map(&:name)}" contains_rel = reloaded_diagram.relationships.find { |r| r.label == 'contains' } puts "Relationship 'contains' is identifying: #{contains_rel.identifying}" # => true puts "Cardinality ORDER -> ORDER_ITEM: #{contains_rel.cardinality2}" # => :ONE_OR_MORE ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.