### Bundle Install Command Source: https://github.com/seuros/activecypher/blob/master/README.md The command to execute after adding the gem to your Gemfile to install it and its dependencies. ```bash $ bundle install ``` -------------------------------- ### Gem Install Command Source: https://github.com/seuros/activecypher/blob/master/README.md Alternative command to install the ActiveCypher gem directly from RubyGems. ```bash $ gem install activecypher ``` -------------------------------- ### Install ActiveCypher Base Classes Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Generates the necessary base classes and configuration file for ActiveCypher integration. This includes `ApplicationGraphNode`, `ApplicationGraphRelationship`, and `cypher_databases.yml`. ```bash bin/rails generate active_cypher:install ``` -------------------------------- ### Install ActiveCypher Gem Source: https://github.com/seuros/activecypher/blob/master/README.md Instructions for adding the ActiveCypher gem to your Ruby on Rails project's Gemfile and installing it. ```ruby gem 'activecypher' ``` -------------------------------- ### Install ActiveCypher and Generate Configuration Source: https://context7.com/seuros/activecypher/llms.txt Installs the ActiveCypher gem and generates essential configuration files and base classes for your Rails application. This includes setting up base classes for node and relationship models, and a configuration file for database connections. ```bash # Install ActiveCypher in your Rails project gem install activecypher # Generate configuration files bin/rails generate active_cypher:install ``` -------------------------------- ### Configure Graph Database Connections (YAML) Source: https://github.com/seuros/activecypher/blob/master/README.md Example configuration for `config/cypher_databases.yml` showing how to set up connections for Memgraph and Neo4j across different Rails environments (development, test, production). ```yaml # config/cypher_databases.yml development: primary: url: memgraph://memgraph:activecypher@localhost:17688 neo4j: url: <%= ENV.fetch('NEO4J_URL', 'neo4j://neo4j:activecypher@localhost:17687') %> migrations_paths: graphdb/neo4j test: primary: url: memgraph://memgraph:activecypher@localhost:17688 neo4j: url: <%= ENV.fetch('NEO4J_URL', 'neo4j://neo4j:activecypher@localhost:17687') %> migrations_paths: graphdb/neo4j production: primary: url: memgraph+ssc://user:pass@memgraph:7687 ``` -------------------------------- ### ActiveCypher Database Configuration (YAML) Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This YAML code provides configuration examples for ActiveCypher database connections using `config/cypher_databases.yml`. It shows two formats: a preferred `url` format leveraging environment variables, and an alternative format with individual connection parameters. ```yaml development: primary: url: <%= ENV.fetch('GRAPHDB_URL', 'neo4j://caffeine_addict:espresso123@localhost:17687/coffee_empire') %> analytics_db: url: neo4j://bean_counter:latte_art@analytics-db.example.com:7687/hipster_metrics production: primary: url: <%= ENV['GRAPHDB_URL'] %> ``` ```yaml development: primary: adapter: neo4j # or memgraph (the cooler, younger sibling) host: localhost port: 17687 username: barista_supreme password: no_decaf_please database: coffee_supply_chain ``` -------------------------------- ### Execute Cypher Queries via Shell (Bash) Source: https://github.com/seuros/activecypher/blob/master/GRAPH_REFERENCE.md Demonstrates executing Cypher queries from files or directly from the command line using `cypher-shell` for Neo4j and `mgconsole` for Memgraph. Includes examples for single queries and executing from files. ```bash # Execute from file cypher-shell -u neo4j -p activecypher < queries.cypher mgconsole --host localhost --port 17688 --username memgraph --password activecypher < queries.cypher # Single query echo "MATCH (n) RETURN count(n);" | cypher-shell -u neo4j -p activecypher echo "MATCH (n) RETURN count(n);" | mgconsole --host localhost --port 17688 --username memgraph --password activecypher # Exit shell :exit (Neo4j) :quit (Memgraph) ``` -------------------------------- ### Query Coffee Supply Chain with ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This Ruby code demonstrates querying a Neo4j graph database for coffee supply chain information using ActiveCypher. It includes examples for finding suppliers of specific beans, locating high-quality beans with contracts, identifying organic roasteries, and retrieving a shop's complete supply chain via a custom Cypher query. ```ruby # Find all coffee shops serving Colombian beans colombian_suppliers = CoffeeBeanNode.where(origin: "Colombia") .joins(:serves_rel) .includes(:coffee_shop_nodes) # Find high-quality beans (score > 85) with their supply contracts premium_beans = CoffeeBeanNode.where("quality_score > ?", 85) .joins(:supplies_rel) .includes(:roastery_nodes) # Find roasteries with organic certification organic_roasters = RoasteryNode.where(certified_organic: true) # Get the complete supply chain for a specific coffee shopcafe = CoffeeShopNode.find_by(name: "The Grind Coffee Co.") supply_chain = cafe.cypher_query(<<~CYPHER) MATCH (shop:CoffeeShopNode {name: $shop_name}) MATCH (shop)-[serves:SERVES]->(beans:CoffeeBeanNode) MATCH (roastery:RoasteryNode)-[roasts:ROASTS]->(beans) MATCH (beans)-[supplies:SUPPLIES]->(roastery) RETURN shop, serves, beans, roasts, roastery, supplies CYPHER ``` -------------------------------- ### Create and Query Nodes/Relationships in Ruby Source: https://github.com/seuros/activecypher/blob/master/README.md Provides Ruby code examples for creating new nodes (`PersonNode`, `ConspiracyNode`) and relationships (`BelievesInRelationship`) using ActiveCypher. It also demonstrates how to query relationships from a node's perspective (e.g., `conspiracy.followers`) and retrieve related nodes. ```ruby # Create a new person node person = PersonNode.create(name: 'Alice', age: 30) # Create a new conspiracy node conspiracy = ConspiracyNode.create(name: 'Flat Earth', description: 'The earth is flat.', believability_index: 1) # Create a relationship between person and conspiracy BelievesInRelationship.create( from: person, to: conspiracy, reddit_karma_spent: 100, level_of_devotion: 'casual' ) # Find all people who believe in a specific conspiracy followers = conspiracy.followers # Find all conspiracies a person believes in conspiracies = person.believes_in_relationships.map(&:to) ``` -------------------------------- ### Configure Primary Connection via Environment Variable Source: https://github.com/seuros/activecypher/blob/master/README.md Examples of setting the `GRAPHDB_URL` environment variable to configure the primary graph database connection for Neo4j and Memgraph, supporting various SSL modes. ```bash # For Neo4j export GRAPHDB_URL="neo4j://username:password@localhost:17687/database_name" # For Memgraph export GRAPHDB_URL="memgraph://username:password@localhost:17688" ``` -------------------------------- ### Cyrel Shorthand Helpers for Query Building Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Illustrates the use of Cyrel's shorthand helper methods for more concise query construction. This includes using `Cyrel.query` for starting a query and `Cyrel.n` for defining nodes, making the code more readable. ```ruby # Using the query helper query = Cyrel.query .match(Cyrel.n(:p, :Person, name: 'Alice')) .where(Cyrel.prop(:p, :age) > 25) .return_(:p) # Using the node helper (alias for Pattern::Node) person = Cyrel.n(:p, :Person, active: true) query = Cyrel.query.match(person).return_(:p) # Note: Cyrel automatically assigns parameter keys (like $p1, $p2) and collects the values. ``` -------------------------------- ### Cyrel Automatic Parameterization Example Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Shows how Cyrel automatically handles parameterization for literal values in queries. This is a key security feature that prevents Cypher injection and can improve query performance. The example demonstrates parameterization of strings and booleans. ```ruby node = Cyrel::Pattern::Node.new(:p, labels: 'Person', properties: { name: 'Bob', active: true }) query = Cyrel::Query.new.match(node).return_(node) cypher, params = query.to_cypher # cypher => "MATCH (p:Person {name: $p1, active: $p2}) RETURN p" # params => { p1: 'Bob', p2: true } ``` -------------------------------- ### Advanced Relationship Queries in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This Ruby code showcases advanced querying capabilities for relationships in ActiveCypher. It includes examples for finding the most expensive supply contracts, identifying seasonal coffee offerings, and calculating average cupping scores grouped by roast level. ```ruby # Find the most expensive coffee supply contracts expensive_contracts = SuppliesRel.where("price_per_bag > ?", 200) .order(price_per_bag: :desc) .includes(:from_node, :to_node) # Find seasonal coffee offerings seasonal_coffees = ServesRel.where(seasonal_offering: true) .includes(:coffee_shop_nodes, :coffee_bean_nodes) # Get roasting statistics roasting_stats = RoastsRel.group(:roast_level) .average(:cupping_score) ``` -------------------------------- ### Cypher CALL Procedures and Subqueries in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Illustrates how to execute stored procedures or embedded subqueries using the CALL clause in Cyrel. Examples show calling a built-in procedure like `db.labels` and embedding a query as a subquery. The output displays the generated Cypher syntax for both scenarios. ```ruby query.call('db.labels').yield(:label).return_(:label) #=> CALL db.labels() YIELD label RETURN label # Subqueries query.call_subquery do |sub| sub.match(node).return_(node) end #=> CALL { MATCH (node) RETURN node } ``` -------------------------------- ### ActiveCypher Migration Helper Methods Overview (Ruby) Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This Ruby code snippet outlines the available helper methods within ActiveCypher for defining graph database schema migrations. It shows how to create node indexes, relationship indexes, and uniqueness constraints, including composite options. The `execute` method is also presented for running raw Cypher queries when helper methods are insufficient. ```ruby # Node indexes create_node_index :Label, :property, name: :optional_name create_node_index :Label, :prop1, :prop2, unique: true # Composite index # Relationship indexes create_rel_index :REL_TYPE, :property, name: :optional_name # Uniqueness constraints create_uniqueness_constraint :Label, :property, name: :optional_name create_uniqueness_constraint :Label, :prop1, :prop2 # Composite constraint # Raw Cypher (when helpers don't cover your use case) execute "CREATE INDEX fancy_index FOR (n:Node) ON (n.computed_property)" ``` -------------------------------- ### Cypher UNION Queries in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Shows how to combine the results of multiple Cypher queries using the UNION clause in Cyrel. This example defines two separate queries and then combines them into a single union query. The output is the resulting Cypher query string. ```ruby query1 = Cyrel::Query.new.match(Cyrel.n(:a, :Person)).return_(:a) query2 = Cyrel::Query.new.match(Cyrel.n(:b, :Company)).return_(:b) union_query = Cyrel::Query.union_queries([query1, query2]) #=> MATCH (a:Person) RETURN a UNION MATCH (b:Company) RETURN b ``` -------------------------------- ### Create and Connect Entities in Neo4j Graph Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This Ruby snippet demonstrates creating various nodes (CoffeeBeanNode, RoasteryNode, CoffeeShopNode) and relationships (SuppliesRel, RoastsRel, ServesRel) in a Neo4j graph database using ActiveCypher. It includes detailed attributes for each entity and relationship, illustrating a supply chain for coffee. ```ruby # Create coffee beans (the foundation of all productivity) arabica_beans = CoffeeBeanNode.create!( variety: "Arabica", origin: "Colombia", harvest_date: 1.month.ago, quality_score: 87.5, # Higher than most code reviews processing_method: "washed" ) # Create a roastery (where magic happens) mountain_roasters = RoasteryNode.create!( name: "Mountain Peak Roasters", location: "Denver, CO", # High altitude = better coffee, obviously capacity_bags_per_day: 50, roast_profiles: %w[light medium dark], # Like debugging: light warnings, medium errors, dark despair certified_organic: true ) # Create supply relationship (the caffeine lifeline) supply_contract = SuppliesRel.create!( from_node: arabica_beans, to_node: mountain_roasters, quantity_bags: 20, price_per_bag: 180.50, # Cheaper than therapy contract_date: Date.current, delivery_schedule: "monthly" ) # Create a coffee shop (developer sanctuary) specialty_cafe = CoffeeShopNode.create!( name: "The Grind Coffee Co.", # Where code is debugged one cup at a time location: "Boulder, CO", established_year: 2018, chain: false, # Independent, like most developers' spirits specialty: "pour_over" ) # Create roasting relationship (transformation magic) roasting = RoastsRel.create!( from_node: mountain_roasters, to_node: arabica_beans, roast_level: "medium", # Like our bugs: not too light, not too dark roast_date: Date.current, batch_size_kg: 45.0, roast_profile: { "temp_curve": "gradual", "total_time": "12min" }, # Slower than CI/CD pipeline cupping_score: 89.2 ) # Create serving relationship (the final delivery) serving = ServesRel.create!( from_node: specialty_cafe, to_node: arabica_beans, # Direct from source to your keyboard blend_name: "Colombian Mountain Blend", price_per_cup: 4.50, # Still cheaper than AWS charges per minute daily_volume_cups: 85, brewing_method: "pour_over", # Because we're fancy like that seasonal_offering: false # Available year-round, unlike good documentation ) ``` -------------------------------- ### Configure Default and Custom Database Connections in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Demonstrates how to configure database connections for ActiveCypher models. `ApplicationGraphNode` uses the primary connection by default. Custom base classes like `AnalyticsGraphNode` allow specifying different read/write connections for multiple databases. ```ruby # app/graph/application_graph_node.rb - Uses primary connection (default) class ApplicationGraphNode < ActiveCypher::Base # No need to specify connects_to - primary is default end # app/graph/analytics_graph_node.rb - Analytics database class AnalyticsGraphNode < ActiveCypher::Base connects_to writing: :analytics_db, reading: :analytics_readonly end # Relationships automatically inherit from their corresponding node base # app/graph/application_graph_relationship.rb class ApplicationGraphRelationship < ActiveCypher::Relationship # Inherits connection from ApplicationGraphNode end ``` -------------------------------- ### Define Roastery Node in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Defines a `RoasteryNode` model inheriting from `ApplicationGraphNode`. It includes attributes for name, location, capacity, roast profiles, and organic certification, with validations for name and capacity. ```ruby # app/graph/roastery_node.rb class RoasteryNode < ApplicationGraphNode attribute :name, :string attribute :location, :string attribute :capacity_bags_per_day, :integer attribute :roast_profiles, :json # Array of available roast levels attribute :certified_organic, :boolean, default: false validates :name, presence: true validates :capacity_bags_per_day, numericality: { greater_than: 0 } end ``` -------------------------------- ### Abstract Base Class Convention in Ruby Source: https://github.com/seuros/activecypher/blob/master/README.md Demonstrates how ActiveCypher automatically pairs abstract relationship base classes with corresponding abstract node base classes by convention. It shows the setup for `ApplicationGraphNode` and `ApplicationGraphRelationship`, and how to explicitly set the `node_base_class` if needed. This convention reduces boilerplate code. ```ruby # app/graph/application_graph_node.rb class ApplicationGraphNode < ActiveCypher::Base self.abstract_class = true connects_to writing: :primary, reading: :primary end # app/graph/application_graph_relationship.rb class ApplicationGraphRelationship < ActiveCypher::Relationship self.abstract_class = true # No need to specify node_base_class; ActiveCypher will play matchmaker and default to ApplicationGraphNode end # Explicitly setting node_base_class class MyRelationshipBase < ActiveCypher::Relationship self.abstract_class = true node_base_class MyNodeBase end ``` -------------------------------- ### Query Nodes with Cyrel in Ruby Source: https://github.com/seuros/activecypher/blob/master/README.md Shows how to perform queries on ActiveCypher models using the Cyrel query language. Examples include finding nodes by exact attribute match (`PersonNode.where(name: 'Alice')`) and using conditional logic for attribute filtering (`ConspiracyNode.where('believability_index > ?', 5)`). ```ruby # Find all people named 'Alice' people = PersonNode.where(name: 'Alice') # Find all conspiracies with a believability index greater than 5 believable_conspiracies = ConspiracyNode.where('believability_index > ?', 5) ``` -------------------------------- ### Define Serves Relationship in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Defines a `ServesRel` model inheriting from `ApplicationGraphRelationship`. It includes attributes for blend name, price per cup, daily volume, brewing method, and seasonal offering status, with validations for price and brewing method. ```ruby # app/graph/serves_rel.rb class ServesRel < ApplicationGraphRelationship attribute :blend_name, :string # Custom name for the coffee offering attribute :price_per_cup, :decimal attribute :daily_volume_cups, :integer attribute :brewing_method, :string # "espresso", "drip", "french_press" attribute :seasonal_offering, :boolean, default: false validates :price_per_cup, numericality: { greater_than: 0 } validates :brewing_method, presence: true end ``` -------------------------------- ### Create Coffee Supply Chain Graph Database Schema (Ruby) Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This Ruby code defines an ActiveCypher migration to set up the schema for a coffee supply chain. It creates uniqueness constraints on node properties and indexes on various node and relationship properties to optimize common queries. It also includes a raw Cypher command to create a fulltext index for searching coffee beans. ```ruby class CreateCoffeeSupplyChain < ActiveCypher::Migration up do # Create uniqueness constraints using helper methods create_uniqueness_constraint :CoffeeBeanNode, :id, name: :coffee_bean_id_unique create_uniqueness_constraint :RoasteryNode, :name, name: :roastery_name_unique create_uniqueness_constraint :CoffeeShopNode, :name, :location, name: :coffee_shop_location_unique # Create indexes for common queries create_node_index :CoffeeBeanNode, :origin, name: :coffee_origin_idx create_node_index :CoffeeBeanNode, :quality_score, name: :coffee_quality_idx create_node_index :RoasteryNode, :certified_organic, name: :organic_roastery_idx create_node_index :CoffeeShopNode, :specialty, name: :coffee_shop_specialty_idx # Create relationship indexes for performance create_rel_index :SUPPLIES, :contract_date, name: :supply_contract_timeline_idx create_rel_index :ROASTS, :roast_date, name: :roasting_timeline_idx create_rel_index :SERVES, :seasonal_offering, name: :seasonal_coffee_idx # Use raw execute only for advanced features not covered by helpers execute <<~CYPHER CREATE FULLTEXT INDEX coffee_search IF NOT EXISTS FOR (bean:CoffeeBeanNode) ON EACH [bean.variety, bean.origin, bean.processing_method] CYPHER end # Note: No down method needed - migrations are append-only in graph databases # Dropping constraints/indexes in production can be dangerous! end ``` -------------------------------- ### Define Node and Relationship Models in Ruby Source: https://github.com/seuros/activecypher/blob/master/README.md Defines example Ruby classes for graph nodes (PersonNode, ConspiracyNode) and relationships (BelievesInRel) using ActiveCypher. It shows how to declare attributes, define relationships with specific classes and directions, and set up validation rules. Dependencies include ActiveCypher and Rails application structure. ```ruby # app/graph/person_node.rb class PersonNode < ApplicationGraphNode attribute :id, :string attribute :name, :string attribute :age, :integer attribute :active, :boolean, default: true validates :name, presence: true end # app/graph/conspiracy_node.rb class ConspiracyNode < ApplicationGraphNode attribute :name, :string attribute :description, :string attribute :believability_index, :integer has_many :followers, class_name: 'PersonNode', relationship: 'BELIEVES_IN', direction: :in, relationship_class: 'BelievesInRel' end # app/graph/believes_in_rel.rb class BelievesInRel < ApplicationGraphRelationship from_class 'PersonNode' to_class 'ConspiracyNode' type 'BELIEVES_IN' attribute :reddit_karma_spent, :integer attribute :level_of_devotion, :string # "casual", "zealot", "makes merch" end ``` -------------------------------- ### Connect to Graph Databases (Bash) Source: https://github.com/seuros/activecypher/blob/master/GRAPH_REFERENCE.md Commands to connect to Neo4j and Memgraph databases using their respective shell clients. Requires database credentials and host information. ```bash # Neo4j cypher-shell -u neo4j -p activecypher # Memgraph mgconsole --host localhost --port 17688 --username memgraph --password activecypher --use-ssl=false ``` -------------------------------- ### Basic Cyrel Query Construction in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Demonstrates how to build a basic Cypher query using Cyrel. It involves defining pattern components like nodes, creating conditions, and chaining methods to construct the query. The output includes the generated Cypher string and its associated parameters. ```ruby require 'cyrel' # 1. Define pattern components person_node = Cyrel::Pattern::Node.new(:person, labels: ['Person'], properties: { name: 'Alice' }) age_condition = person_node[:age].gt(25) # Creates an Expression object # 2. Build the query query = Cyrel::Query.new .match(person_node) # Add a MATCH clause .where(age_condition) # Add a WHERE clause .return_(person_node[:name]) # Add a RETURN clause (use return_ for Symbol/Expression) # 3. Generate Cypher and parameters cypher_string, params_hash = query.to_cypher puts cypher_string #=> MATCH (person:Person {name: $p1}) WHERE person.age > $p2 RETURN person.name puts params_hash #=> { p1: 'Alice', p2: 25 } ``` -------------------------------- ### Define Supplies Relationship in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Defines a `SuppliesRel` model inheriting from `ApplicationGraphRelationship`. It includes attributes for quantity, price, contract date, and delivery schedule, with validations for quantity and price. ```ruby # app/graph/supplies_rel.rb class SuppliesRel < ApplicationGraphRelationship # Relationships inherit connection from ApplicationGraphNode by default # No need to specify connects_to unless you want custom connection handling and like problems attribute :quantity_bags, :integer attribute :price_per_bag, :decimal attribute :contract_date, :date attribute :delivery_schedule, :string # "weekly", "monthly", "seasonal" validates :quantity_bags, numericality: { greater_than: 0 } validates :price_per_bag, numericality: { greater_than: 0 } end ``` -------------------------------- ### Define Coffee Shop Node in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Defines a `CoffeeShopNode` model inheriting from `ApplicationGraphNode`. It includes attributes for name, location, establishment year, chain status, and specialty, with validations for name and establishment year. ```ruby # app/graph/coffee_shop_node.rb class CoffeeShopNode < ApplicationGraphNode attribute :name, :string attribute :location, :string attribute :established_year, :integer attribute :chain, :boolean, default: false attribute :specialty, :string # "espresso", "pour_over", "cold_brew" validates :name, presence: true validates :established_year, numericality: { greater_than: 1900 } end ``` -------------------------------- ### Define ActiveCypher Relationship Model Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md This Ruby code defines a custom relationship model `AnalyticsGraphRelationship` that inherits from `ActiveCypher::Relationship`. It establishes a connection to an analytics graph node by convention and notes that cross-database operations are not supported. ```ruby class AnalyticsGraphRelationship < ActiveCypher::Relationship # Inherits connection from AnalyticsGraphNode (by naming convention) end ``` -------------------------------- ### Generate ActiveCypher Relationship Class Source: https://github.com/seuros/activecypher/blob/master/README.md Generates a relationship class for ActiveCypher. By default, the class name is suffixed with 'Rel'. You can specify the starting and ending nodes for the relationship using --from and --to options. The suffix can be customized with the --suffix option. ```bash bin/rails generate active_cypher:relationship BelievesIn --from=PersonNode --to=ConspiracyNode bin/rails generate active_cypher:relationship CustomRel --suffix=MySuffix --from=NodeA --to=NodeB ``` -------------------------------- ### Cyrel Query Builder - Basic Query Construction in Ruby Source: https://context7.com/seuros/activecypher/llms.txt Programmatically build Cypher queries using the Cyrel DSL in Ruby. This snippet demonstrates creating query components like nodes and conditions, then assembling them into a complete query. It shows how to return specific properties and includes shorthand helpers for common patterns. Cyrel automatically parameterizes literals to prevent injection. ```ruby # Create query components person_node = Cyrel::Pattern::Node.new(:person, labels: ['Person'], properties: { name: 'Alice' }) age_condition = person_node[:age].gt(25) # Build and compile query query = Cyrel::Query.new .match(person_node) .where(age_condition) .return_(person_node[:name]) cypher, params = query.to_cypher # cypher => "MATCH (person:Person {name: $p1}) WHERE person.age > $p2 RETURN person.name" # params => { p1: 'Alice', p2: 25 } # Shorthand helpers query = Cyrel.query .match(Cyrel.n(:p, :Person, name: 'Alice')) .where(Cyrel.prop(:p, :age) > 25) .return_(:p) # Optional match user = Cyrel::Pattern::Node.new(:u, labels: ['User']) follows = Cyrel::Pattern::Relationship.new(types: ['FOLLOWS'], direction: :outgoing) org = Cyrel::Pattern::Node.new(:o, labels: ['Organization']) path = Cyrel::Pattern::Path.new([user, follows, org]) query = Cyrel::Query.new .match(user) .optional_match(path) .return_(:u, :o) cypher, params = query.to_cypher # cypher => "MATCH (u:User) OPTIONAL MATCH (u:User)-[:FOLLOWS]->(o:Organization) RETURN u, o" ``` -------------------------------- ### Ordering, Skipping, and Limiting Results in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Shows how to control the order, offset, and number of results returned by a Cypher query using Cyrel. It demonstrates the use of order_by, skip, and limit methods to produce paginated or sorted query outputs. The output includes the generated Cypher query with parameters for skip and limit. ```ruby query.match(node).return_(node).order_by([node[:name], :desc]).skip(10).limit(5) #=> MATCH (node) RETURN node ORDER BY node.name DESC SKIP $p1 LIMIT $p2 ``` -------------------------------- ### Define Roasts Relationship in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Defines a `RoastsRel` model inheriting from `ApplicationGraphRelationship`. It includes attributes for roast level, date, batch size, roast profile, and cupping score, with validations for roast level and batch size. ```ruby # app/graph/roasts_rel.rb class RoastsRel < ApplicationGraphRelationship attribute :roast_level, :string # "light", "medium", "dark" attribute :roast_date, :date attribute :batch_size_kg, :float attribute :roast_profile, :json # Temperature curve, timing, etc. attribute :cupping_score, :float # Quality assessment after roasting validates :roast_level, inclusion: { in: %w[light medium dark] } validates :batch_size_kg, numericality: { greater_than: 0 } end ``` -------------------------------- ### Environment Variables for Graph DB URLs (Bash) Source: https://github.com/seuros/activecypher/blob/master/GRAPH_REFERENCE.md Environment variables used to configure connection URLs for Neo4j and Memgraph databases. These variables are typically used by client applications to establish connections. ```bash NEO4J_URL="neo4j:activecypher@localhost:17687" GRAPHDB_URL="memgraph://memgraph:activecypher@localhost:17688" ``` -------------------------------- ### Multi-Database Connection Configuration Source: https://context7.com/seuros/activecypher/llms.txt Demonstrates how to configure ActiveCypher models to connect to different graph databases using the `connects_to` method. ```APIDOC ## Multi-Database Connection Configuration ### Description Demonstrates how to configure ActiveCypher models to connect to different graph databases using the `connects_to` method. ### Method N/A (Ruby Class Definition) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```ruby # app/graph/application_graph_node.rb class ApplicationGraphNode < ActiveCypher::Base self.abstract_class = true connects_to writing: :primary, reading: :primary end # app/graph/neo4j_record.rb class Neo4jRecord < ActiveCypher::Base self.abstract_class = true # Shorthand: equivalent to writing: :neo4j, reading: :neo4j connects_to :neo4j end ``` ### Response #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Define Coffee Bean Node in ActiveCypher Source: https://github.com/seuros/activecypher/blob/master/EXAMPLES.md Defines a `CoffeeBeanNode` model inheriting from `ApplicationGraphNode`. It includes attributes like variety, origin, harvest date, quality score, and processing method, along with validations for variety and quality score. ```ruby # app/graph/coffee_bean_node.rb class CoffeeBeanNode < ApplicationGraphNode attribute :variety, :string # e.g., "Arabica", "Robusta" attribute :origin, :string # e.g., "Colombia", "Ethiopia" attribute :harvest_date, :date attribute :quality_score, :float # 1-100 scale (Float support enabled) attribute :processing_method, :string # "washed", "natural", "honey" validates :variety, presence: true validates :quality_score, inclusion: { in: 1..100 } end ``` -------------------------------- ### Cyrel Query Builder: OR Labels and EXISTS Subqueries Source: https://context7.com/seuros/activecypher/llms.txt Demonstrates the use of modern OpenCypher features for flexible pattern matching with the Cyrel Query Builder. This includes defining nodes with OR labels and constructing queries with EXISTS subqueries, which are useful for checking the existence of patterns within the database. Requires Memgraph 3.2+ for OR labels and 3.5+ for EXISTS. ```ruby # OR label expressions (Memgraph 3.2+) node = Cyrel.node(:n, or_labels: ['Person', 'Organization']) query = Cyrel::Query.new.match(node).return_(:n) # cypher => "MATCH (n:Person|Organization) RETURN n" # With properties node = Cyrel.node(:n, or_labels: ['Admin', 'Moderator'], name: 'Alice') query = Cyrel::Query.new.match(node).return_(:n) # cypher => "MATCH (n:Admin|Moderator {name: $p1}) RETURN n" # EXISTS subqueries (Memgraph 3.5+) path = Cyrel.path { node(:person) > rel(:r, :MANAGES) > node(:team, :Team) } query = Cyrel::Query.new .match(Cyrel.node(:person, :Person)) .where(Cyrel.exists_block { match(path) }) .return_(:person) # cypher => "MATCH (person:Person) WHERE EXISTS { MATCH (person)-[r:MANAGES]->(team:Team) } RETURN person" # EXISTS with WHERE inside path = Cyrel.path { node(:a) > rel(:r) > node(:b) } condition = Cyrel.prop(:b, :active) == true exists_expr = Cyrel.exists_block do match(path) where(condition) end query = Cyrel::Query.new .match(Cyrel.node(:a, :User)) .where(exists_expr) .return_(:a) # cypher => "MATCH (a:User) WHERE EXISTS { MATCH (a)-[r]-(b) WHERE b.active = $p1 } RETURN a" ``` -------------------------------- ### Connect Model to Specific Database (Full Mapping) Source: https://github.com/seuros/activecypher/blob/master/README.md Ruby code demonstrating how to configure a model class to use specific database connections for writing and reading roles using the `connects_to` method with a full mapping syntax. ```ruby class ApplicationGraphNode < ActiveCypher::Base self.abstract_class = true connects_to writing: :primary, reading: :primary end ``` -------------------------------- ### Query Merging with merge! in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Demonstrates how to merge two Cyrel::Query objects using the merge! method. This combines query parts, handling parameter merging, appending additive clauses, and combining WHERE clauses with AND. The output shows the resulting Cypher query and parameters. ```ruby query1 = Cyrel::Query.new.match(Cyrel::Pattern::Node.new(:p, labels: 'Person')) query2 = Cyrel::Query.new.where(Cyrel['p'][:age].gt(30)).return_('p.name') query1.merge!(query2) cypher, params = query1.to_cypher # cypher => MATCH (p:Person) WHERE p.age > $p1 RETURN p.name # params => { p1: 30 } ``` -------------------------------- ### Cypher Functions and Expressions in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Illustrates how to build complex conditions and return calculated values using functions and expressions within Cyrel. This includes using Cyrel.id and Cyrel.count to generate WHERE and RETURN clauses respectively. The output shows the generated Cypher query with parameterization. ```ruby query.match(node).where(Cyrel.id(node).eq(123)).return_(Cyrel.count(node)) #=> MATCH (node) WHERE id(node) = $p1 RETURN count(node) ``` -------------------------------- ### Connect Model to Specific Database (Shorthand) Source: https://github.com/seuros/activecypher/blob/master/README.md Ruby code showing a shorthand syntax for the `connects_to` method, where a single connection name is used for both writing and reading roles. ```ruby class Neo4jRecord < ActiveCypher::Base self.abstract_class = true # Equivalent to writing: :neo4j, reading: :neo4j connects_to :neo4j end ``` -------------------------------- ### Load Graph Fixtures with ActiveCypher DSL Source: https://context7.com/seuros/activecypher/llms.txt This Ruby code snippet illustrates the use of ActiveCypher's declarative fixture DSL for loading test and seed data into a graph database. It defines nodes (persons, companies) and relationships (works_at) using a concise syntax, making test data management straightforward. Fixtures can be loaded using `ActiveCypher::Fixtures.load` and accessed via `ActiveCypher::Fixtures.registry`. ```ruby # config/graphdb/fixtures/users.cyrel # Define nodes and relationships using DSL person :alice do name 'Alice' email 'alice@example.com' age 30 end person :bob do name 'Bob' email 'bob@example.com' age 25 end company :acme do name 'Acme Corp' industry 'Technology' end # Create relationships works_at from: :alice, to: :acme do title 'Engineer' since 2020 end works_at from: :bob, to: :acme do title 'Designer' since 2021 end # Load fixtures in tests ActiveCypher::Fixtures.load('users') # Access created nodes alice = ActiveCypher::Fixtures.registry[:alice] alice.name # => 'Alice' ``` -------------------------------- ### Ruby: Build Cypher MATCH and OPTIONAL MATCH Queries Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Demonstrates how to construct Cypher `MATCH` and `OPTIONAL MATCH` clauses using ActiveCypher's objects for nodes, relationships, and paths. This includes matching nodes with specific labels and properties, and defining relationships with directionality. ```ruby # Matching nodes with labels and properties user_node = Cyrel::Pattern::Node.new(:user, labels: ['User'], properties: { email: 'test@example.com' }) query = Cyrel::Query.new.match(user_node).return_(:user) #=> MATCH (user:User {email: $p1}) RETURN user # Matching relationships (simple outgoing) user_node = Cyrel::Pattern::Node.new(:u, labels: ['User']) rel = Cyrel::Pattern::Relationship.new(types: ['FOLLOWS'], direction: :outgoing) org_node = Cyrel::Pattern::Node.new(:o, labels: ['Organization']) path = Cyrel::Pattern::Path.new([user_node, rel, org_node]) query = Cyrel::Query.new.match(path).return_(:u, :o) #=> MATCH (u:User)-[:FOLLOWS]->(o:Organization) RETURN u, o # Using the path DSL (Note: Direction preservation has known issues in current version) query = Cyrel::Query.new .match(Cyrel.path { node(:a) > rel(:r) > node(:b) }) .return_(:a, :b) #=> MATCH (a)-[r]-(b) RETURN a, b # Known issue: should be (a)-[r]->(b) # Optional Match query = Cyrel::Query.new .match(user_node) .optional_match(path) .return_(:u, :o) #=> MATCH (u:User) OPTIONAL MATCH (u:User)-[:FOLLOWS]->(o:Organization) RETURN u, o ``` -------------------------------- ### Cypher UNWIND Clause in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Explains how to use the UNWIND clause in Cyrel to expand list elements into individual rows. This is useful for processing multiple items within a single query. The code example shows unwinding a list and returning its elements. The output is the corresponding Cypher query. ```ruby query.unwind([1, 2, 3], :x).return_(:x) #=> UNWIND [1, 2, 3] AS x RETURN x ``` -------------------------------- ### Cyrel Query Builder - Data Manipulation in Ruby Source: https://context7.com/seuros/activecypher/llms.txt Use the Cyrel query builder in Ruby to perform data manipulation operations on the graph database, including creating, merging, updating, and deleting nodes and relationships. This example demonstrates the basic syntax for creating and merging nodes with specified labels and properties, showing the resulting Cypher and parameters. ```ruby # CREATE nodes node = Cyrel::Pattern::Node.new(:person, labels: 'Person', properties: { name: 'Alice', age: 30 }) query = Cyrel::Query.new.create(node) cypher, params = query.to_cypher # cypher => "CREATE (person:Person {name: $p1, age: $p2})" # params => { p1: 'Alice', p2: 30 } # MERGE (find or create) query = Cyrel::Query.new.merge(node) # cypher => "MERGE (person:Person {name: $p1, age: $p2})" ``` -------------------------------- ### Configure Graph Database Connections (YAML) Source: https://context7.com/seuros/activecypher/llms.txt Configures connections to graph databases like Neo4j and Memgraph using a YAML file. Supports various URL schemes and allows specifying different connection configurations for development, testing, and production environments. ```yaml # config/cypher_databases.yml development: primary: url: <%= ENV.fetch('GRAPHDB_URL', 'memgraph://memgraph:password@localhost:17688') %> neo4j: url: neo4j://neo4j:password@localhost:17687/database_name migrations_paths: graphdb/neo4j test: primary: url: memgraph://memgraph:password@localhost:17688 production: primary: url: <%= ENV['GRAPHDB_URL'] %> ``` -------------------------------- ### Run and Check ActiveCypher GraphDB Migrations Source: https://github.com/seuros/activecypher/blob/master/README.md Commands to manage ActiveCypher graph database migrations. 'bin/rails graphdb:migrate' applies pending migrations, while 'bin/rails graphdb:status' shows the current migration status. ```bash bin/rails graphdb:migrate bin/rails graphdb:status ``` -------------------------------- ### Sanity Check Graph Database Server Reachability Source: https://github.com/seuros/activecypher/blob/master/README.md Verifies that the Memgraph and Neo4j database servers are accessible on their default ports (17688 for Memgraph, 17687 for Neo4j). The script will exit with an error if either server is not reachable. ```bash bin/sanity ``` -------------------------------- ### Cyrel Query Builder: WITH Clause, Functions, Ordering, Skipping, Limiting Source: https://context7.com/seuros/activecypher/llms.txt Illustrates advanced Cypher features within the Cyrel Query Builder. This includes using the WITH clause for query chaining, applying functions and expressions, and implementing ordering, skipping, and limiting results. These features enhance query flexibility and control. ```ruby # WITH clause for query chaining query = Cyrel::Query.new .match(Cyrel.n(:user, :User)) .with(Cyrel.prop(:user, :name).as(:userName)) .return_(:userName) # cypher => "MATCH (user:User) WITH user.name AS userName RETURN userName" # Functions and expressions query = Cyrel::Query.new .match(Cyrel.n(:node, :Person)) .where(Cyrel.id(Cyrel[:node]).eq(123)) .return_(Cyrel.count(Cyrel[:node])) # cypher => "MATCH (node:Person) WHERE id(node) = $p1 RETURN count(node)" # Ordering, skipping, limiting query = Cyrel::Query.new .match(Cyrel.n(:person, :Person)) .return_(Cyrel[:person]) .order_by([Cyrel.prop(:person, :age), :desc]) .skip(10) .limit(5) # cypher => "MATCH (person:Person) RETURN person ORDER BY person.age DESC SKIP $p1 LIMIT $p2" ``` -------------------------------- ### Define ActiveCypher GraphDB Migrations Source: https://github.com/seuros/activecypher/blob/master/README.md Defines a database migration using ActiveCypher's DSL. The 'up' method contains the logic for creating indexes and constraints, or executing raw Cypher. Migrations are append-only and should not be modified after creation. ```ruby class AddFacilityIndexes < ActiveCypher::Migration up do create_uniqueness_constraint :Facility, :commonid, name: :facility_commonid_unique create_node_index :Facility, :country_id, :kind, name: :facility_country_kind_idx create_rel_index :FACILITY_REL, :rel_type, name: :facility_rel_type_idx execute <<~CYPHER CREATE INDEX IF NOT EXISTS FOR (f:Facility) ON (f.created_at) CYPHER end end ``` -------------------------------- ### Cypher FOREACH Loop in Ruby Source: https://github.com/seuros/activecypher/blob/master/CYREL.md Demonstrates the usage of the FOREACH loop in Cyrel for iterating over lists within a Cypher query. It highlights potential issues with variable context in the current version, as noted in the limitations. The output shows the generated Cypher query structure. ```ruby query.foreach(:item, :list) do |sub| sub.set(node[:processed] => true) end #=> FOREACH (item IN $p1 | SET node.processed = $p2) ```