Skip to content

Commit

Permalink
MRI-driver (#1730)
Browse files Browse the repository at this point in the history
* MRI driver

* MRI driver

* update workflow

* update workflow

* update workflow
  • Loading branch information
klobuczek authored Jan 13, 2025
1 parent 4e7f303 commit c586343
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 85 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/e2e_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: [ jruby, ruby-3.3.5 ]
neo4j: [ 5.23.0 ]
active_model: [ 7.1.4, 7.2.1 ]
ruby: [ jruby, ruby ]
neo4j: [ 5.26.0 ]
active_model: [ 7.1.5.1, 7.2.2.1 ]
include:
- ruby: ruby
neo4j: 5.26.0
active_model: 8.0.1
- ruby: jruby
java-version: 17
env:
Expand Down
21 changes: 12 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: [ jruby, ruby-3.1.6 ]
neo4j: [ 5.23.0 ]
active_model: [ 7.0.8, 7.1.4, 7.2.1 ]
ruby: [ jruby, ruby ]
neo4j: [ 5.26.0 ]
active_model: [ 7.1.5.1, 7.2.2.1 ]
include:
- ruby: ruby-3.2.5
neo4j: 5.23.0
active_model: 7.1.4
- ruby: ruby-3.3.5
neo4j: 5.23.0
active_model: 7.1.4
- ruby: ruby-3.2.6
neo4j: 5.26.0
active_model: 7.1.5.1
- ruby: ruby-3.3.6
neo4j: 5.26.0
active_model: 7.1.5.1
- ruby: ruby
neo4j: 5.26.0
active_model: 8.0.1
- ruby: jruby
java-version: 17
env:
Expand Down
6 changes: 3 additions & 3 deletions activegraph.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Gem::Specification.new do |s|
s.name = 'activegraph'
s.version = ActiveGraph::VERSION

s.required_ruby_version = '>= 2.6'
s.required_ruby_version = '>= 3.1'

s.authors = 'Andreas Ronge, Brian Underwood, Chris Grigg, Heinrich Klobuczek'
s.email = '[email protected], [email protected], [email protected], [email protected]'
Expand All @@ -30,9 +30,9 @@ DESCRIPTION
'bug_tracker_uri' => 'https://github.com/neo4jrb/activegraph/issues'
}

s.add_dependency('activemodel', '>= 7')
s.add_dependency('activemodel')
s.add_dependency('i18n', '!= 1.8.8') # https://github.com/jruby/jruby/issues/6547
s.add_dependency('neo4j-ruby-driver', '>= 5.7.0.alpha.1')
s.add_dependency('neo4j-ruby-driver', '>= 5.7.0.alpha.3')
s.add_dependency('orm_adapter', '>= 0.5.0')
s.add_dependency('sorted_set')
s.add_development_dependency('guard')
Expand Down
4 changes: 2 additions & 2 deletions lib/active_graph/migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ def initialize(path = default_path)

def migrate
ActiveGraph.deprecator.warn '`AddIdProperty` task is deprecated and may be removed from future releases. ' \
'Create a new migration and use the `populate_id_property` helper.', caller
'Create a new migration and use the `populate_id_property` helper.',
caller_locations
models = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(models_filename))[:models]
output 'This task will add an ID Property every node in the given file.'
output 'It may take a significant amount of time, please be patient.'
Expand Down Expand Up @@ -108,7 +109,6 @@ def setup
# print_output message
# end


# def id_batch_set(label, id_property, new_ids, count)
# tx = ActiveGraph::Base.new_transaction

Expand Down
2 changes: 1 addition & 1 deletion lib/active_graph/relationship/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def last
private

def deprecation_warning!
ActiveGraph.deprecator.warn 'The ActiveGraph::Relationship::Query module has been deprecated and will be removed in a future version of the gem.', caller
ActiveGraph.deprecator.warn 'The ActiveGraph::Relationship::Query module has been deprecated and will be removed in a future version of the gem.', caller_locations
end

def where_query
Expand Down
2 changes: 1 addition & 1 deletion lib/active_graph/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ActiveGraph
VERSION = '12.0.0.beta.4'
VERSION = '12.0.0.beta.5'
end
5 changes: 2 additions & 3 deletions spec/e2e/association_dependency_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ def routing_setup
@route2 = Route.create(name: 'Secondary Route')
@tour.routes << [@route1, @route2]


# Pro Tip from Chris: No good metal shows happen in Manhattan.
# Boston is iffy, too.
city_names = %w(Philadelphia Brooklyn Manhattan Providence Boston)
Expand Down Expand Up @@ -217,7 +216,7 @@ def routing_setup
it 'deletes only orphans' do
rel_1.destroy
expect { BadModel.find(bad_model_1.id) }.to raise_error(ActiveGraph::Node::Labels::RecordNotFound)
expect { BadModel.find(bad_model_2.id) }.not_to raise_error
expect { BadModel.find(bad_model_2.id) }.not_to raise_error
end
end

Expand Down Expand Up @@ -365,7 +364,7 @@ def routing_setup

describe 'invalid options' do
it 'raises an error when an invalid option is passed' do
expect { Stop.has_many(:out, :fooz, dependent: :foo).to raise_error }
expect { Stop.has_many(:out, :fooz, dependent: :foo) }.to raise_error
end
end
end
58 changes: 28 additions & 30 deletions spec/e2e/query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
clear_model_memory_caches
end


let(:student_interests_association_options) { {} }

before(:each) do
Expand Down Expand Up @@ -42,11 +41,11 @@ def self.ordered_by_subject

has_many :out, :lessons, rel_class: 'IsEnrolledFor'

has_many :out, :interests, {type: nil}.merge(scoped_interests_options)
has_many :out, :interests, { type: nil }.merge(scoped_interests_options)

has_many :both, :favorite_teachers, type: nil, model_class: 'Teacher'
has_many :both, :hated_teachers, type: nil, model_class: 'Teacher'
has_many :in, :winning_lessons, model_class: 'Lesson', origin: :teachers_pet
has_many :in, :winning_lessons, model_class: 'Lesson', origin: :teachers_pet
end

stub_relationship_class('IsEnrolledFor') do
Expand Down Expand Up @@ -167,7 +166,6 @@ def self.ordered_by_subject
let!(:math) { Interest.create(name: 'Math') }
let!(:monster_trucks) { Interest.create(name: 'Monster Trucks') }


it 'evaluates `all` lazily' do
result = Teacher.all
expect(result).to be_a(ActiveGraph::Node::Query::QueryProxy)
Expand Down Expand Up @@ -209,10 +207,10 @@ def self.ordered_by_subject

describe '.merge' do
let(:timestamps) { [1, 1, 2, 3].map(&DateTime.method(:new)) }
let(:merge_attrs) { {name: 'Dr. Dre'} }
let(:merge_attrs) { { name: 'Dr. Dre' } }
let(:on_match_clause) { {} }
let(:on_create_clause) { {} }
let(:set_attrs) { {status: 'on create status'} }
let(:set_attrs) { { status: 'on create status' } }

before { allow(DateTime).to receive(:now).and_return(*timestamps) }
after { expect(Teacher.count).to eq 1 }
Expand All @@ -235,7 +233,7 @@ def self.ordered_by_subject
its(:labels) { is_expected.to match_array [:TeacherFoo, :Substitute] }
end

let_context 'on_create', on_create_clause: {age: 49} do
let_context 'on_create', on_create_clause: { age: 49 } do
its(:age) { is_expected.to eq 49 }
its(:status) { is_expected.to eq 'on create status' }

Expand All @@ -244,8 +242,7 @@ def self.ordered_by_subject
end
end


let_context 'on_merge', on_match_clause: {age: 50}, on_create_clause: {age: 49}, set_attrs: {status: 'on match status'} do
let_context 'on_merge', on_match_clause: { age: 50 }, on_create_clause: { age: 49 }, set_attrs: { status: 'on match status' } do
before { Teacher.merge(on_create_clause.merge(merge_attrs)) }

its(:age) { is_expected.to eq 50 }
Expand Down Expand Up @@ -286,7 +283,7 @@ def self.ordered_by_subject
end

it 'also sets properties on create' do
Teacher.find_or_create({name: 'Dr. Harold Samuels'}, age: 34)
Teacher.find_or_create({ name: 'Dr. Harold Samuels' }, age: 34)

expect(Teacher.count).to eq(1)

Expand All @@ -298,7 +295,7 @@ def self.ordered_by_subject
end

it 'overrides default properties on create' do
Teacher.find_or_create({name: 'Dr. Harold Samuels'}, age: 34, status: 'inactive')
Teacher.find_or_create({ name: 'Dr. Harold Samuels' }, age: 34, status: 'inactive')

expect(Teacher.count).to eq(1)

Expand Down Expand Up @@ -343,7 +340,7 @@ def custom_prop_method
end

context 'on match' do
let(:original) { Teacher.find_or_create({name: 'Dr. Harold Samuels'}, age: 34) }
let(:original) { Teacher.find_or_create({ name: 'Dr. Harold Samuels' }, age: 34) }

before(:each) { original }

Expand All @@ -355,7 +352,7 @@ def custom_prop_method
end

it 'updates nothing' do
teacher = Teacher.find_or_create({name: 'Dr. Harold Samuels'}, age: 0)
teacher = Teacher.find_or_create({ name: 'Dr. Harold Samuels' }, age: 0)

expect(teacher.id).to eq(original.id)
expect(teacher.name).to eq('Dr. Harold Samuels')
Expand Down Expand Up @@ -550,13 +547,13 @@ def custom_prop_method
describe 'on classes' do
before(:each) do
danny.lessons << math101
danny.lessons(:l, :r).query.set(r: {grade: 65}).exec
danny.lessons(:l, :r).query.set(r: { grade: 65 }).exec

bobby.lessons << math101
bobby.lessons(:l, :r).query.set(r: {grade: 71})
bobby.lessons(:l, :r).query.set(r: { grade: 71 })

math101.teachers << othmar
math101.teachers(:t, :r).query.set(r: {since: 2001}).exec
math101.teachers(:t, :r).query.set(r: { since: 2001 }).exec

sandra.lessons << ss101
end
Expand All @@ -565,9 +562,8 @@ def custom_prop_method
it { expect(Student.as(:student).where(age: 15).lessons(:lesson).where(level: 101).pluck(:student)).to eq([danny]) }
it { expect(Student.where(age: 15).lessons(:lesson).where(level: '101').pluck(:lesson)).not_to eq([[othmar]]) }
it do
expect(Student.as(:student).where(age: 15).lessons(:lesson).where(level: 101).pluck(:student)).to eq(
Student.as(:student).node_where(age: 15).lessons(:lesson).node_where(level: 101).pluck(:student)
)
expect(Student.as(:student).where(age: 15).lessons(:lesson).where(level: 101).pluck(:student))
.to eq( Student.as(:student).node_where(age: 15).lessons(:lesson).node_where(level: 101).pluck(:student) )
end
end

Expand Down Expand Up @@ -687,17 +683,19 @@ def custom_prop_method
expect(Teacher.where(date: date).to_cypher_with_params).to include(converted_date.to_s)
expect(Teacher.where(datetime: datetime).to_cypher_with_params).to include(converted_datetime.to_s)
expect(Teacher.where(time: time).to_cypher_with_params).to include(converted_time.to_s)
expect(Teacher.where(age: '1').to_cypher_with_params).to include(':result_teacher2_age=>1')
expect(Student.where(likely_to_succeed: 'false').to_cypher_with_params).to include(':result_student2_likely_to_succeed=>false')
expect(Teacher.where(age: '1').to_cypher_with_params).to include({ result_teacher2_age: 1 }.to_s)
expect(Student.where(likely_to_succeed: 'false').to_cypher_with_params)
.to include({ result_student2_likely_to_succeed: false }.to_s)
end

context '...and values already in the destination format' do
it 'uses the values as they are' do
expect(Teacher.where(date: converted_date).to_cypher_with_params).to include(converted_date.to_s)
expect(Teacher.where(datetime: converted_datetime).to_cypher_with_params).to include(converted_datetime.to_s)
expect(Teacher.where(time: converted_time).to_cypher_with_params).to include(converted_time.to_s)
expect(Teacher.where(age: 1).to_cypher_with_params).to include(':result_teacher2_age=>1')
expect(Student.where(likely_to_succeed: false).to_cypher_with_params).to include(':result_student2_likely_to_succeed=>false')
expect(Teacher.where(age: 1).to_cypher_with_params).to include({ result_teacher2_age: 1 }.to_s)
expect(Student.where(likely_to_succeed: false).to_cypher_with_params)
.to include({ result_student2_likely_to_succeed: false }.to_s)
end
end

Expand Down Expand Up @@ -741,9 +739,9 @@ def custom_prop_method

describe 'Associations with `unique` set' do
let(:from_node) { Student.create }
let(:to_node) { Interest.create }
let(:first_props) { {score: 900} }
let(:second_props) { {score: 1000} }
let(:to_node) { Interest.create }
let(:first_props) { { score: 900 } }
let(:second_props) { { score: 1000 } }
let(:changed_props_create) { proc { from_node.interests.create(to_node, second_props) } }

before do
Expand All @@ -752,7 +750,7 @@ def custom_prop_method
end

context 'with `true` option' do
let(:student_interests_association_options) { {type: nil, unique: true} }
let(:student_interests_association_options) { { type: nil, unique: true } }

it 'becomes :none' do
expect(ActiveGraph::Shared::FilteredHash).to receive(:new).with(instance_of(Hash), :none).and_call_original
Expand All @@ -761,7 +759,7 @@ def custom_prop_method
end

context 'with :none open' do
let(:student_interests_association_options) { {type: nil, unique: :none} }
let(:student_interests_association_options) { { type: nil, unique: :none } }

it 'does not create additional rels, even when properties change' do
expect do
Expand All @@ -771,15 +769,15 @@ def custom_prop_method
end

context 'with `:all` option' do
let(:student_interests_association_options) { {type: nil, unique: :all} }
let(:student_interests_association_options) { { type: nil, unique: :all } }

it 'creates additional rels when properties change' do
expect { changed_props_create.call }.to change { from_node.interests.count }
end
end

context 'with {on: [keys]} option' do
let(:student_interests_association_options) { {type: nil, unique: {on: :score}} }
let(:student_interests_association_options) { { type: nil, unique: { on: :score } } }

context 'and a listed property changes' do
it 'creates a new rel' do
Expand Down
12 changes: 6 additions & 6 deletions spec/unit/migrations/schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
let(:constraints) { [] }

let(:range_index) { 'CREATE RANGE INDEX `range_index` FOR (n:`Person`) ON (n.`nickname`)' }
let(:point_index) { "CREATE POINT INDEX `point_index` FOR (n:`Person`) ON (n.`location`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'point-1.0'}" }
let(:fulltext_index) { "CREATE FULLTEXT INDEX `fulltext_index` FOR (n:`Friend`) ON EACH [n.`name`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'swedish',`fulltext.eventually_consistent`: false}, indexProvider: 'fulltext-1.0'}" }
let(:text_index) { "CREATE TEXT INDEX `text_index` FOR ()-[r:`KNOWS`]-() ON (r.`city`) OPTIONS {indexConfig: {}, indexProvider: 'text-2.0'}" }
let(:point_index) { "CREATE POINT INDEX `point_index` FOR (n:`Person`) ON (n.`location`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" }
let(:fulltext_index) { "CREATE FULLTEXT INDEX `fulltext_index` FOR (n:`Friend`) ON EACH [n.`name`] OPTIONS {indexConfig: {`fulltext.analyzer`: 'swedish',`fulltext.eventually_consistent`: false}}" }
let(:text_index) { "CREATE TEXT INDEX `text_index` FOR ()-[r:`KNOWS`]-() ON (r.`city`)" }

let(:unique_constraint) { 'CREATE CONSTRAINT `unique_constraint` FOR (n:`Person`) REQUIRE (n.`name`) IS UNIQUE' }
let(:not_null_rel_prop_constraint) { 'CREATE CONSTRAINT `not_null_rel_prop_constraint` FOR ()-[r:`LIKED`]-() REQUIRE (r.`when`) IS NOT NULL' }
Expand All @@ -28,14 +28,14 @@
end

if ActiveGraph::Base.version?('<4.4')
let(:range_index) { "CREATE INDEX `range_index` FOR (n:`Person`) ON (n.`nickname`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'native-btree-1.0'}" }
let(:range_index) { "CREATE INDEX `range_index` FOR (n:`Person`) ON (n.`nickname`) OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" }
let(:point_index) {}
let(:text_index) {}

let(:unique_constraint) { "CREATE CONSTRAINT `unique_constraint` ON (n:`Person`) ASSERT (n.`name`) IS UNIQUE OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'native-btree-1.0'}" }
let(:unique_constraint) { "CREATE CONSTRAINT `unique_constraint` ON (n:`Person`) ASSERT (n.`name`) IS UNIQUE OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" }
let(:not_null_rel_prop_constraint) { 'CREATE CONSTRAINT `not_null_rel_prop_constraint` ON ()-[r:`LIKED`]-() ASSERT (r.`when`) IS NOT NULL' }
let(:not_null_node_prop_constraint) { 'CREATE CONSTRAINT `not_null_node_prop_constraint` ON (n:`Person`) ASSERT (n.`name`) IS NOT NULL' }
let(:node_key_constraint) { "CREATE CONSTRAINT `node_key_constraint` ON (n:`Person`) ASSERT (n.`name`, n.`surname`) IS NODE KEY OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}, indexProvider: 'native-btree-1.0'}" }
let(:node_key_constraint) { "CREATE CONSTRAINT `node_key_constraint` ON (n:`Person`) ASSERT (n.`name`, n.`surname`) IS NODE KEY OPTIONS {indexConfig: {`spatial.cartesian-3d.max`: [1000000.0, 1000000.0, 1000000.0],`spatial.cartesian-3d.min`: [-1000000.0, -1000000.0, -1000000.0],`spatial.cartesian.max`: [1000000.0, 1000000.0],`spatial.cartesian.min`: [-1000000.0, -1000000.0],`spatial.wgs-84-3d.max`: [180.0, 90.0, 1000000.0],`spatial.wgs-84-3d.min`: [-180.0, -90.0, -1000000.0],`spatial.wgs-84.max`: [180.0, 90.0],`spatial.wgs-84.min`: [-180.0, -90.0]}}" }
end

if ActiveGraph::Base.version?('<4.3')
Expand Down
Loading

0 comments on commit c586343

Please sign in to comment.