neo4j 7.2.3 → 8.0.0.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -46
- data/Gemfile +15 -14
- data/README.md +21 -14
- data/bin/neo4j-jars +1 -1
- data/lib/neo4j.rb +12 -1
- data/lib/neo4j/active_base.rb +68 -0
- data/lib/neo4j/active_base/session_registry.rb +12 -0
- data/lib/neo4j/active_node.rb +13 -21
- data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +6 -6
- data/lib/neo4j/active_node/enum.rb +3 -6
- data/lib/neo4j/active_node/has_n.rb +24 -19
- data/lib/neo4j/active_node/has_n/association.rb +6 -2
- data/lib/neo4j/active_node/has_n/association/rel_factory.rb +1 -1
- data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +1 -1
- data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +1 -1
- data/lib/neo4j/active_node/id_property.rb +52 -15
- data/lib/neo4j/active_node/labels.rb +32 -10
- data/lib/neo4j/active_node/labels/index.rb +5 -55
- data/lib/neo4j/active_node/node_list_formatter.rb +13 -0
- data/lib/neo4j/active_node/node_wrapper.rb +39 -37
- data/lib/neo4j/active_node/persistence.rb +27 -13
- data/lib/neo4j/active_node/query/query_proxy.rb +11 -9
- data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +4 -4
- data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +1 -0
- data/lib/neo4j/active_node/query/query_proxy_link.rb +13 -9
- data/lib/neo4j/active_node/query/query_proxy_methods.rb +76 -8
- data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +1 -1
- data/lib/neo4j/active_node/query_methods.rb +3 -3
- data/lib/neo4j/active_node/scope.rb +24 -7
- data/lib/neo4j/active_rel.rb +21 -3
- data/lib/neo4j/active_rel/initialize.rb +2 -2
- data/lib/neo4j/active_rel/persistence.rb +32 -6
- data/lib/neo4j/active_rel/persistence/query_factory.rb +3 -3
- data/lib/neo4j/active_rel/property.rb +9 -9
- data/lib/neo4j/active_rel/query.rb +6 -4
- data/lib/neo4j/active_rel/rel_wrapper.rb +24 -16
- data/lib/neo4j/active_rel/related_node.rb +5 -1
- data/lib/neo4j/active_rel/types.rb +2 -2
- data/lib/neo4j/config.rb +0 -1
- data/lib/neo4j/errors.rb +3 -0
- data/lib/neo4j/migration.rb +90 -71
- data/lib/neo4j/migrations.rb +10 -0
- data/lib/neo4j/migrations/base.rb +44 -0
- data/lib/neo4j/migrations/helpers.rb +101 -0
- data/lib/neo4j/migrations/helpers/id_property.rb +75 -0
- data/lib/neo4j/migrations/helpers/relationships.rb +66 -0
- data/lib/neo4j/migrations/helpers/schema.rb +53 -0
- data/lib/neo4j/migrations/migration_file.rb +24 -0
- data/lib/neo4j/migrations/runner.rb +110 -0
- data/lib/neo4j/migrations/schema_migration.rb +9 -0
- data/lib/neo4j/model_schema.rb +100 -0
- data/lib/neo4j/railtie.rb +29 -110
- data/lib/neo4j/schema/operation.rb +24 -13
- data/lib/neo4j/session_manager.rb +137 -0
- data/lib/neo4j/shared.rb +20 -11
- data/lib/neo4j/shared/attributes.rb +10 -16
- data/lib/neo4j/shared/callbacks.rb +3 -3
- data/lib/neo4j/shared/cypher.rb +1 -1
- data/lib/neo4j/shared/declared_properties.rb +1 -1
- data/lib/neo4j/shared/declared_property.rb +1 -1
- data/lib/neo4j/shared/enum.rb +6 -18
- data/lib/neo4j/shared/identity.rb +27 -21
- data/lib/neo4j/shared/persistence.rb +26 -17
- data/lib/neo4j/shared/property.rb +5 -2
- data/lib/neo4j/shared/query_factory.rb +4 -5
- data/lib/neo4j/shared/type_converters.rb +8 -9
- data/lib/neo4j/shared/validations.rb +1 -5
- data/lib/neo4j/tasks/migration.rake +83 -2
- data/lib/neo4j/version.rb +1 -1
- data/lib/rails/generators/neo4j/migration/migration_generator.rb +14 -0
- data/lib/rails/generators/neo4j/migration/templates/migration.erb +9 -0
- data/lib/rails/generators/neo4j/model/model_generator.rb +1 -3
- data/lib/rails/generators/neo4j_generator.rb +1 -0
- data/neo4j.gemspec +3 -3
- metadata +58 -65
- data/bin/rake +0 -17
- data/lib/neo4j/shared/permitted_attributes.rb +0 -28
| @@ -0,0 +1,100 @@ | |
| 1 | 
            +
            require 'set'
         | 
| 2 | 
            +
            module Neo4j
         | 
| 3 | 
            +
              # This is here to support the removed functionality of being able to
         | 
| 4 | 
            +
              # defined indexes and constraints on models
         | 
| 5 | 
            +
              # This code should be removed later
         | 
| 6 | 
            +
              module ModelSchema
         | 
| 7 | 
            +
                MODEL_INDEXES = {}
         | 
| 8 | 
            +
                MODEL_CONSTRAINTS = {}
         | 
| 9 | 
            +
                REQUIRED_INDEXES = {}
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                class << self
         | 
| 12 | 
            +
                  def add_defined_constraint(model, property_name)
         | 
| 13 | 
            +
                    MODEL_CONSTRAINTS[model] ||= Set.new
         | 
| 14 | 
            +
                    MODEL_CONSTRAINTS[model] << property_name.to_sym
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def add_defined_index(model, property_name)
         | 
| 18 | 
            +
                    MODEL_INDEXES[model] ||= Set.new
         | 
| 19 | 
            +
                    MODEL_INDEXES[model] << property_name.to_sym
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def add_required_index(model, property_name)
         | 
| 23 | 
            +
                    REQUIRED_INDEXES[model] ||= Set.new
         | 
| 24 | 
            +
                    REQUIRED_INDEXES[model] << property_name.to_sym
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def defined_constraint?(model, property_name)
         | 
| 28 | 
            +
                    MODEL_CONSTRAINTS[model] &&
         | 
| 29 | 
            +
                      MODEL_CONSTRAINTS[model].include?(property_name.to_sym)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def model_constraints
         | 
| 33 | 
            +
                    constraints = Neo4j::ActiveBase.current_session.constraints.each_with_object({}) do |row, result|
         | 
| 34 | 
            +
                      result[row[:label]] ||= []
         | 
| 35 | 
            +
                      result[row[:label]] << row[:properties]
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    schema_elements_list(MODEL_CONSTRAINTS, constraints)
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def model_indexes
         | 
| 42 | 
            +
                    indexes = Neo4j::ActiveBase.current_session.indexes.each_with_object({}) do |row, result|
         | 
| 43 | 
            +
                      result[row[:label]] ||= []
         | 
| 44 | 
            +
                      result[row[:label]] << row[:properties]
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    schema_elements_list(MODEL_INDEXES, indexes) +
         | 
| 48 | 
            +
                      schema_elements_list(REQUIRED_INDEXES, indexes).reject(&:last)
         | 
| 49 | 
            +
                    # reject required indexes which are already in the DB
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  # should be private
         | 
| 53 | 
            +
                  def schema_elements_list(by_model, db_results)
         | 
| 54 | 
            +
                    by_model.flat_map do |model, property_names|
         | 
| 55 | 
            +
                      label = model.mapped_label_name.to_sym
         | 
| 56 | 
            +
                      property_names.map do |property_name|
         | 
| 57 | 
            +
                        exists = db_results[label] && db_results[label].include?([property_name])
         | 
| 58 | 
            +
                        [model, label, property_name, exists]
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def validate_model_schema!
         | 
| 64 | 
            +
                    messages = {index: [], constraint: []}
         | 
| 65 | 
            +
                    [[:constraint, model_constraints], [:index, model_indexes]].each do |type, schema_elements|
         | 
| 66 | 
            +
                      schema_elements.map do |model, label, property_name, exists|
         | 
| 67 | 
            +
                        if exists
         | 
| 68 | 
            +
                          log_warning!(type, model, property_name)
         | 
| 69 | 
            +
                        else
         | 
| 70 | 
            +
                          messages[type] << force_add_message(type, label, property_name)
         | 
| 71 | 
            +
                        end
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    return if messages.values.all?(&:empty?)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    fail validation_error_message(messages)
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def validation_error_message(messages)
         | 
| 81 | 
            +
                    <<MSG
         | 
| 82 | 
            +
                      Some schema elements were defined by the model (which is no longer support), but they do not exist in the database.  Run the following to create them:
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            #{messages[:constraint].join("\n")}
         | 
| 85 | 
            +
            #{messages[:index].join("\n")}
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            (zshell users may need to escape the brackets)
         | 
| 88 | 
            +
            MSG
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def force_add_message(index_or_constraint, label, property_name)
         | 
| 92 | 
            +
                    "rake neo4j:generate_schema_migration[#{index_or_constraint},#{label},#{property_name}]"
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def log_warning!(index_or_constraint, model, property_name)
         | 
| 96 | 
            +
                    Neo4j::ActiveBase.logger.warn "WARNING: The #{index_or_constraint} option is no longer supported (Defined on #{model.name} for #{property_name})"
         | 
| 97 | 
            +
                  end
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
              end
         | 
| 100 | 
            +
            end
         | 
    
        data/lib/neo4j/railtie.rb
    CHANGED
    
    | @@ -1,7 +1,11 @@ | |
| 1 1 | 
             
            require 'active_support/notifications'
         | 
| 2 2 | 
             
            require 'rails/railtie'
         | 
| 3 | 
            +
            require 'neo4j/session_manager'
         | 
| 3 4 | 
             
            # Need the action_dispatch railtie to have action_dispatch.rescue_responses initialized correctly
         | 
| 4 5 | 
             
            require 'action_dispatch/railtie'
         | 
| 6 | 
            +
            require 'neo4j/core/cypher_session/adaptors/http'
         | 
| 7 | 
            +
            require 'neo4j/core/cypher_session/adaptors/bolt'
         | 
| 8 | 
            +
            require 'neo4j/core/cypher_session/adaptors/embedded'
         | 
| 5 9 |  | 
| 6 10 | 
             
            module Neo4j
         | 
| 7 11 | 
             
              class Railtie < ::Rails::Railtie
         | 
| @@ -39,131 +43,46 @@ module Neo4j | |
| 39 43 | 
             
                  load 'neo4j/tasks/migration.rake'
         | 
| 40 44 | 
             
                end
         | 
| 41 45 |  | 
| 42 | 
            -
                 | 
| 43 | 
            -
                   | 
| 44 | 
            -
                    RUBY_PLATFORM =~ /java/
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  def setup_default_session(cfg)
         | 
| 48 | 
            -
                    setup_config_defaults!(cfg)
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                    return if !cfg.sessions.empty?
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                    cfg.sessions << {type: cfg.session_type, path: cfg.session_path, options: cfg.session_options.merge(default: true)}
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                  def setup_config_defaults!(cfg)
         | 
| 56 | 
            -
                    cfg.session_type ||= default_session_type
         | 
| 57 | 
            -
                    cfg.session_path ||= default_session_path
         | 
| 58 | 
            -
                    cfg.session_options ||= {}
         | 
| 59 | 
            -
                    cfg.sessions ||= []
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  def config_data
         | 
| 63 | 
            -
                    @config_data ||= if yaml_path
         | 
| 64 | 
            -
                                       HashWithIndifferentAccess.new(YAML.load(ERB.new(yaml_path.read).result)[Rails.env])
         | 
| 65 | 
            -
                                     else
         | 
| 66 | 
            -
                                       {}
         | 
| 67 | 
            -
                                     end
         | 
| 68 | 
            -
                  end
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  def yaml_path
         | 
| 71 | 
            -
                    @yaml_path ||= %w(config/neo4j.yml config/neo4j.yaml).map do |path|
         | 
| 72 | 
            -
                      Rails.root.join(path)
         | 
| 73 | 
            -
                    end.detect(&:exist?)
         | 
| 74 | 
            -
                  end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  def default_session_type
         | 
| 77 | 
            -
                    type = ENV['NEO4J_TYPE'] || config_data[:type] || :server_db
         | 
| 78 | 
            -
                    type.to_sym
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  def default_session_path
         | 
| 82 | 
            -
                    ENV['NEO4J_URL'] || ENV['NEO4J_PATH'] ||
         | 
| 83 | 
            -
                      config_data[:url] || config_data[:path] ||
         | 
| 84 | 
            -
                      'http://localhost:7474'
         | 
| 85 | 
            -
                  end
         | 
| 46 | 
            +
                console do |app|
         | 
| 47 | 
            +
                  Neo4j::Config[:logger] = ActiveSupport::Logger.new(STDOUT)
         | 
| 86 48 |  | 
| 87 | 
            -
                   | 
| 88 | 
            -
             | 
| 89 | 
            -
                    security_class = java.lang.Class.for_name('javax.crypto.JceSecurity')
         | 
| 90 | 
            -
                    restricted_field = security_class.get_declared_field('isRestricted')
         | 
| 91 | 
            -
                    restricted_field.accessible = true
         | 
| 92 | 
            -
                    restricted_field.set nil, false
         | 
| 93 | 
            -
                    session.start
         | 
| 94 | 
            -
                  end
         | 
| 49 | 
            +
                  register_neo4j_cypher_logging(app.config.neo4j.sessions.map { |s| s[:type] })
         | 
| 50 | 
            +
                end
         | 
| 95 51 |  | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 52 | 
            +
                # Starting Neo after :load_config_initializers allows apps to
         | 
| 53 | 
            +
                # register migrations in config/initializers
         | 
| 54 | 
            +
                initializer 'neo4j.start', after: :load_config_initializers do |app|
         | 
| 55 | 
            +
                  cfg = app.config.neo4j
         | 
| 56 | 
            +
                  # Set Rails specific defaults
         | 
| 57 | 
            +
                  Neo4j::SessionManager.setup! cfg
         | 
| 98 58 |  | 
| 99 | 
            -
             | 
| 100 | 
            -
                      fail "Tried to start embedded Neo4j db without using JRuby (got #{RUBY_PLATFORM}), please run `rvm jruby`"
         | 
| 101 | 
            -
                    end
         | 
| 59 | 
            +
                  Neo4j::Config[:logger] ||= Rails.logger
         | 
| 102 60 |  | 
| 103 | 
            -
             | 
| 104 | 
            -
                      if options.key?(:name)
         | 
| 105 | 
            -
                        Neo4j::Session.open_named(type, name, default, path)
         | 
| 106 | 
            -
                      else
         | 
| 107 | 
            -
                        Neo4j::Session.open(type, path, options[:options])
         | 
| 108 | 
            -
                      end
         | 
| 109 | 
            -
                    end
         | 
| 61 | 
            +
                  session_types = cfg.sessions.map { |session_opts| session_opts[:type] }
         | 
| 110 62 |  | 
| 111 | 
            -
             | 
| 112 | 
            -
                  end
         | 
| 63 | 
            +
                  register_neo4j_cypher_logging(session_types)
         | 
| 113 64 | 
             
                end
         | 
| 114 65 |  | 
| 115 | 
            -
                 | 
| 116 | 
            -
                   | 
| 117 | 
            -
                   | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
                        if session = yield
         | 
| 121 | 
            -
                          puts
         | 
| 122 | 
            -
                          return session
         | 
| 123 | 
            -
                        end
         | 
| 124 | 
            -
                      rescue Faraday::ConnectionFailed => e
         | 
| 125 | 
            -
                        raise e if !wait
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                        putc '.'
         | 
| 128 | 
            -
                        sleep(1)
         | 
| 129 | 
            -
                      end
         | 
| 130 | 
            -
                    end
         | 
| 131 | 
            -
                  end
         | 
| 132 | 
            -
                end
         | 
| 66 | 
            +
                TYPE_SUBSCRIBERS = {
         | 
| 67 | 
            +
                  http: Neo4j::Core::CypherSession::Adaptors::HTTP.method(:subscribe_to_request),
         | 
| 68 | 
            +
                  bolt: Neo4j::Core::CypherSession::Adaptors::Bolt.method(:subscribe_to_request),
         | 
| 69 | 
            +
                  embedded: Neo4j::Core::CypherSession::Adaptors::Embedded.method(:subscribe_to_transaction)
         | 
| 70 | 
            +
                }
         | 
| 133 71 |  | 
| 134 | 
            -
                def register_neo4j_cypher_logging
         | 
| 72 | 
            +
                def register_neo4j_cypher_logging(session_types)
         | 
| 135 73 | 
             
                  return if @neo4j_cypher_logging_registered
         | 
| 136 74 |  | 
| 137 75 | 
             
                  Neo4j::Core::Query.pretty_cypher = Neo4j::Config[:pretty_logged_cypher_queries]
         | 
| 138 76 |  | 
| 139 | 
            -
                   | 
| 140 | 
            -
                    (Neo4j::Config[:logger]  | 
| 77 | 
            +
                  logger_proc = ->(message) do
         | 
| 78 | 
            +
                    (Neo4j::Config[:logger] ||= Rails.logger).debug message
         | 
| 141 79 | 
             
                  end
         | 
| 142 | 
            -
             | 
| 143 | 
            -
                   | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
                console do
         | 
| 147 | 
            -
                  Neo4j::Config[:logger] = ActiveSupport::Logger.new(STDOUT)
         | 
| 148 | 
            -
             | 
| 149 | 
            -
                  register_neo4j_cypher_logging
         | 
| 150 | 
            -
                end
         | 
| 151 | 
            -
             | 
| 152 | 
            -
                # Starting Neo after :load_config_initializers allows apps to
         | 
| 153 | 
            -
                # register migrations in config/initializers
         | 
| 154 | 
            -
                initializer 'neo4j.start', after: :load_config_initializers do |app|
         | 
| 155 | 
            -
                  cfg = app.config.neo4j
         | 
| 156 | 
            -
                  # Set Rails specific defaults
         | 
| 157 | 
            -
                  Neo4j::Railtie.setup_default_session(cfg)
         | 
| 158 | 
            -
             | 
| 159 | 
            -
                  cfg.sessions.each do |session_opts|
         | 
| 160 | 
            -
                    Neo4j::Railtie.open_neo4j_session(session_opts, cfg.wait_for_connection)
         | 
| 80 | 
            +
                  Neo4j::Core::CypherSession::Adaptors::Base.subscribe_to_query(&logger_proc)
         | 
| 81 | 
            +
                  session_types.map(&:to_sym).uniq.each do |type|
         | 
| 82 | 
            +
                    TYPE_SUBSCRIBERS[type].call(&logger_proc)
         | 
| 161 83 | 
             
                  end
         | 
| 162 | 
            -
                  Neo4j::Config.configuration.merge!(cfg.to_hash)
         | 
| 163 84 |  | 
| 164 | 
            -
                   | 
| 165 | 
            -
             | 
| 166 | 
            -
                  register_neo4j_cypher_logging
         | 
| 85 | 
            +
                  @neo4j_cypher_logging_registered = true
         | 
| 167 86 | 
             
                end
         | 
| 168 87 | 
             
              end
         | 
| 169 88 | 
             
            end
         | 
| @@ -1,10 +1,15 @@ | |
| 1 1 | 
             
            module Neo4j
         | 
| 2 2 | 
             
              module Schema
         | 
| 3 3 | 
             
                class Operation
         | 
| 4 | 
            -
                  attr_reader : | 
| 4 | 
            +
                  attr_reader :label, :property, :options
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  def initialize(label, property, options = default_options)
         | 
| 7 | 
            +
                    @label = if label.is_a?(Neo4j::Core::Label)
         | 
| 8 | 
            +
                               label
         | 
| 9 | 
            +
                             else
         | 
| 10 | 
            +
                               Neo4j::Core::Label.new(label, ActiveBase.current_session)
         | 
| 11 | 
            +
                             end
         | 
| 5 12 |  | 
| 6 | 
            -
                  def initialize(label_name, property, options = default_options)
         | 
| 7 | 
            -
                    @label_name = label_name.to_sym
         | 
| 8 13 | 
             
                    @property = property.to_sym
         | 
| 9 14 | 
             
                    @options = options
         | 
| 10 15 | 
             
                  end
         | 
| @@ -13,14 +18,14 @@ module Neo4j | |
| 13 18 | 
             
                    []
         | 
| 14 19 | 
             
                  end
         | 
| 15 20 |  | 
| 21 | 
            +
                  def label_object
         | 
| 22 | 
            +
                    label
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 16 25 | 
             
                  def create!
         | 
| 17 26 | 
             
                    drop_incompatible!
         | 
| 18 27 | 
             
                    return if exist?
         | 
| 19 | 
            -
                     | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  def label_object
         | 
| 23 | 
            -
                    @label_object ||= Neo4j::Label.create(label_name)
         | 
| 28 | 
            +
                    schema_query(:"create_#{type}")
         | 
| 24 29 | 
             
                  end
         | 
| 25 30 |  | 
| 26 31 | 
             
                  def incompatible_operation_classes
         | 
| @@ -28,12 +33,12 @@ module Neo4j | |
| 28 33 | 
             
                  end
         | 
| 29 34 |  | 
| 30 35 | 
             
                  def drop!
         | 
| 31 | 
            -
                     | 
| 36 | 
            +
                    schema_query(:"drop_#{type}")
         | 
| 32 37 | 
             
                  end
         | 
| 33 38 |  | 
| 34 39 | 
             
                  def drop_incompatible!
         | 
| 35 40 | 
             
                    incompatible_operation_classes.each do |clazz|
         | 
| 36 | 
            -
                      operation = clazz.new( | 
| 41 | 
            +
                      operation = clazz.new(@label, property)
         | 
| 37 42 | 
             
                      operation.drop! if operation.exist?
         | 
| 38 43 | 
             
                    end
         | 
| 39 44 | 
             
                  end
         | 
| @@ -49,6 +54,12 @@ module Neo4j | |
| 49 54 | 
             
                  def type
         | 
| 50 55 | 
             
                    fail 'Abstract class, not implemented'
         | 
| 51 56 | 
             
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  private
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  def schema_query(method)
         | 
| 61 | 
            +
                    label.send(method, property, options)
         | 
| 62 | 
            +
                  end
         | 
| 52 63 | 
             
                end
         | 
| 53 64 |  | 
| 54 65 | 
             
                class ExactIndexOperation < Neo4j::Schema::Operation
         | 
| @@ -61,7 +72,7 @@ module Neo4j | |
| 61 72 | 
             
                  end
         | 
| 62 73 |  | 
| 63 74 | 
             
                  def exist?
         | 
| 64 | 
            -
                     | 
| 75 | 
            +
                    label.index?(property)
         | 
| 65 76 | 
             
                  end
         | 
| 66 77 | 
             
                end
         | 
| 67 78 |  | 
| @@ -71,7 +82,7 @@ module Neo4j | |
| 71 82 | 
             
                  end
         | 
| 72 83 |  | 
| 73 84 | 
             
                  def type
         | 
| 74 | 
            -
                    ' | 
| 85 | 
            +
                    'uniqueness_constraint'
         | 
| 75 86 | 
             
                  end
         | 
| 76 87 |  | 
| 77 88 | 
             
                  def create!
         | 
| @@ -80,7 +91,7 @@ module Neo4j | |
| 80 91 | 
             
                  end
         | 
| 81 92 |  | 
| 82 93 | 
             
                  def exist?
         | 
| 83 | 
            -
                     | 
| 94 | 
            +
                    label.uniqueness_constraint?(property)
         | 
| 84 95 | 
             
                  end
         | 
| 85 96 |  | 
| 86 97 | 
             
                  def default_options
         | 
| @@ -0,0 +1,137 @@ | |
| 1 | 
            +
            require 'active_support/core_ext/hash'
         | 
| 2 | 
            +
            require 'active_support/ordered_options'
         | 
| 3 | 
            +
            require 'neo4j/core/cypher_session/adaptors/http'
         | 
| 4 | 
            +
            require 'neo4j/core/cypher_session/adaptors/bolt'
         | 
| 5 | 
            +
            require 'neo4j/core/cypher_session/adaptors/embedded'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Neo4j
         | 
| 8 | 
            +
              class SessionManager
         | 
| 9 | 
            +
                class << self
         | 
| 10 | 
            +
                  def setup!(cfg = nil)
         | 
| 11 | 
            +
                    cfg ||= ActiveSupport::OrderedOptions.new
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    setup_default_session(cfg)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    cfg.sessions.each do |session_opts|
         | 
| 16 | 
            +
                      open_neo4j_session(session_opts, cfg.wait_for_connection)
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    Neo4j::Config.configuration.merge!(cfg.to_h)
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # TODO: Remove ability for multiple sessions?
         | 
| 23 | 
            +
                  # Ability to overwrite default session per-model like ActiveRecord?
         | 
| 24 | 
            +
                  def setup_default_session(cfg)
         | 
| 25 | 
            +
                    setup_config_defaults!(cfg)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    return if !cfg.sessions.empty?
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    cfg.sessions << {type: cfg.session_type, path: cfg.session_path, options: cfg.session_options.merge(default: true)}
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  # TODO: Support `session_url` config for server mode
         | 
| 33 | 
            +
                  def setup_config_defaults!(cfg)
         | 
| 34 | 
            +
                    cfg.session_type ||= default_session_type
         | 
| 35 | 
            +
                    cfg.session_path ||= default_session_path
         | 
| 36 | 
            +
                    cfg.session_options ||= {}
         | 
| 37 | 
            +
                    cfg.sessions ||= []
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def open_neo4j_session(options, wait_for_connection = false)
         | 
| 41 | 
            +
                    session_type, path, url = options.values_at(:type, :path, :url)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    enable_unlimited_strength_crypto! if java_platform? && session_type_is_embedded?(session_type)
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    adaptor = wait_for_value(wait_for_connection) do
         | 
| 46 | 
            +
                      cypher_session_adaptor(session_type, url || path, (options[:options] || {}).merge(wrap_level: :proc))
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    Neo4j::ActiveBase.current_adaptor = adaptor
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  protected
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  def session_type_is_embedded?(session_type)
         | 
| 55 | 
            +
                    [:embedded_db, :embedded].include?(session_type)
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  def enable_unlimited_strength_crypto!
         | 
| 59 | 
            +
                    # See https://github.com/jruby/jruby/wiki/UnlimitedStrengthCrypto
         | 
| 60 | 
            +
                    security_class = java.lang.Class.for_name('javax.crypto.JceSecurity')
         | 
| 61 | 
            +
                    restricted_field = security_class.get_declared_field('isRestricted')
         | 
| 62 | 
            +
                    restricted_field.accessible = true
         | 
| 63 | 
            +
                    restricted_field.set nil, false
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def config_data
         | 
| 67 | 
            +
                    @config_data ||= if yaml_path
         | 
| 68 | 
            +
                                       HashWithIndifferentAccess.new(YAML.load(ERB.new(yaml_path.read).result)[Rails.env])
         | 
| 69 | 
            +
                                     else
         | 
| 70 | 
            +
                                       {}
         | 
| 71 | 
            +
                                     end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  def yaml_path
         | 
| 75 | 
            +
                    return unless defined?(Rails)
         | 
| 76 | 
            +
                    @yaml_path ||= %w(config/neo4j.yml config/neo4j.yaml).map do |path|
         | 
| 77 | 
            +
                      Rails.root.join(path)
         | 
| 78 | 
            +
                    end.detect(&:exist?)
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  # TODO: Deprecate embedded_db and http in favor of embedded and http
         | 
| 82 | 
            +
                  #
         | 
| 83 | 
            +
                  def cypher_session_adaptor(type, path_or_url, options = {})
         | 
| 84 | 
            +
                    case type
         | 
| 85 | 
            +
                    when :embedded_db, :embedded
         | 
| 86 | 
            +
                      Neo4j::Core::CypherSession::Adaptors::Embedded.new(path_or_url, options)
         | 
| 87 | 
            +
                    when :http
         | 
| 88 | 
            +
                      Neo4j::Core::CypherSession::Adaptors::HTTP.new(path_or_url, options)
         | 
| 89 | 
            +
                    when :bolt
         | 
| 90 | 
            +
                      Neo4j::Core::CypherSession::Adaptors::Bolt.new(path_or_url, options)
         | 
| 91 | 
            +
                    else
         | 
| 92 | 
            +
                      extra = ' (`server_db` has been replaced by `http` or `bolt`)'
         | 
| 93 | 
            +
                      fail ArgumentError, "Invalid session type: #{type.inspect}#{extra if type.to_sym == :server_db}"
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  def default_session_type
         | 
| 98 | 
            +
                    if ENV['NEO4J_URL']
         | 
| 99 | 
            +
                      URI(ENV['NEO4J_URL']).scheme.tap do |scheme|
         | 
| 100 | 
            +
                        fail "Invalid scheme for NEO4J_URL: #{scheme}" if !%w(http bolt).include?(scheme)
         | 
| 101 | 
            +
                      end
         | 
| 102 | 
            +
                    else
         | 
| 103 | 
            +
                      ENV['NEO4J_TYPE'] || config_data[:type] || :http
         | 
| 104 | 
            +
                    end.to_sym
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  def default_session_path
         | 
| 108 | 
            +
                    ENV['NEO4J_URL'] || ENV['NEO4J_PATH'] ||
         | 
| 109 | 
            +
                      config_data[:url] || config_data[:path] ||
         | 
| 110 | 
            +
                      'http://localhost:7474'
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  def java_platform?
         | 
| 114 | 
            +
                    RUBY_PLATFORM =~ /java/
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  def wait_for_value(wait)
         | 
| 118 | 
            +
                    session = nil
         | 
| 119 | 
            +
                    Timeout.timeout(60) do
         | 
| 120 | 
            +
                      until session
         | 
| 121 | 
            +
                        begin
         | 
| 122 | 
            +
                          if session = yield
         | 
| 123 | 
            +
                            puts
         | 
| 124 | 
            +
                            return session
         | 
| 125 | 
            +
                          end
         | 
| 126 | 
            +
                        rescue Faraday::ConnectionFailed => e
         | 
| 127 | 
            +
                          raise e if !wait
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                          putc '.'
         | 
| 130 | 
            +
                          sleep(1)
         | 
| 131 | 
            +
                        end
         | 
| 132 | 
            +
                      end
         | 
| 133 | 
            +
                    end
         | 
| 134 | 
            +
                  end
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
            end
         |