Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MRI-driver #1730

Merged
merged 5 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = 'andreas.ronge@gmail.com, public@brian-underwood.codes, chris@subvertallmedia.com, heinrich@mail.com'
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
Loading