From d6b6dffa88331c1067d70dc43c3f6e59070a0696 Mon Sep 17 00:00:00 2001 From: Syphax Bouazzouni Date: Wed, 17 Apr 2024 16:24:35 +0200 Subject: [PATCH 1/7] implement importing yaml settings file of models attributes metadata --- lib/goo/base/settings/settings.rb | 10 ++- lib/goo/base/settings/yaml_settings.rb | 45 +++++++++++++ test/data/yaml_scheme_model_test.yml | 11 ++++ test/test_dsl_settings.rb | 88 ++++++++++++++++++++++---- test/test_model_complex.rb | 10 +-- 5 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 lib/goo/base/settings/yaml_settings.rb create mode 100644 test/data/yaml_scheme_model_test.yml diff --git a/lib/goo/base/settings/settings.rb b/lib/goo/base/settings/settings.rb index 2a274454..b338f361 100644 --- a/lib/goo/base/settings/settings.rb +++ b/lib/goo/base/settings/settings.rb @@ -1,4 +1,5 @@ require 'active_support/core_ext/string' +require_relative 'yaml_settings' module Goo module Base @@ -12,8 +13,10 @@ module ClassMethods attr_reader :model_name attr_reader :attribute_uris + include YAMLScheme + def default_model_options - return {} + {} end def model(*args) @@ -34,7 +37,9 @@ def model(*args) @model_settings = default_model_options.merge(options || {}) - unless options.include?:name_with + init_yaml_scheme_settings + + unless options.include? :name_with raise ArgumentError, "The model `#{model_name}` definition should include the :name_with option" end Goo.add_model(@model_name,self) @@ -189,6 +194,7 @@ def attribute(*args) options[:enforce] = options[:enforce] ? (options[:enforce] << :no_list) : [:no_list] end @model_settings[:attributes][attr_name] = options + load_yaml_scheme_options(attr_name) shape_attribute(attr_name) namespace = attribute_namespace(attr_name) namespace = namespace || @model_settings[:namespace] diff --git a/lib/goo/base/settings/yaml_settings.rb b/lib/goo/base/settings/yaml_settings.rb new file mode 100644 index 00000000..8a931b3a --- /dev/null +++ b/lib/goo/base/settings/yaml_settings.rb @@ -0,0 +1,45 @@ +require 'yaml' + +module Goo + module Base + module Settings + module YAMLScheme + attr_reader :yaml_settings + + def init_yaml_scheme_settings + scheme_file_path = @model_settings[:scheme] + @yaml_settings = read_yaml_settings_file(scheme_file_path) + end + + def attribute_yaml_settings(attr) + + return {} if yaml_settings.nil? + + yaml_settings[attr.to_sym] + end + + + + private + + def load_yaml_scheme_options(attr) + settings = attribute_settings(attr) + yaml_settings = attribute_yaml_settings(attr) + settings.merge! yaml_settings unless yaml_settings.nil? || yaml_settings.empty? + end + + def read_yaml_settings_file(scheme_file_path) + return if scheme_file_path.nil? + + yaml_contents = File.read(scheme_file_path) rescue return + + YAML.safe_load(yaml_contents, symbolize_names: true) + end + end + end + end +end + + + + diff --git a/test/data/yaml_scheme_model_test.yml b/test/data/yaml_scheme_model_test.yml new file mode 100644 index 00000000..fd8c4921 --- /dev/null +++ b/test/data/yaml_scheme_model_test.yml @@ -0,0 +1,11 @@ +name: + label: 'Name' + description: 'Person name' + equivalents: ['test:name' , 'test2:name', 'test3:person_name'] + help: 'Put the person name as string' + example: 'John' +nationality: + label: 'Person nationality' + enforcedValues: {'fr': 'france', 'us': 'USA'} + + diff --git a/test/test_dsl_settings.rb b/test/test_dsl_settings.rb index 69ab9f6e..9a8f03df 100644 --- a/test/test_dsl_settings.rb +++ b/test/test_dsl_settings.rb @@ -1,5 +1,23 @@ require_relative 'test_case' +GooTest.configure_goo + +class NewPersonModel < Goo::Base::Resource + model :person_model_new, name_with: :name + attribute :name, type: :string, enforce: [ :existence, :unique] + attribute :multiple_values, type: [:list, :integer], enforce: [ :existence, :min_3, :max_5 ] + attribute :one_number, type: :integer,enforce: [ :existence ] #by default not a list + attribute :birth_date, type: :date_time, enforce: [ :existence ] + + attribute :created, type: DateTime , + default: lambda { |record| DateTime.now }, + namespace: :omv + + attribute :friends, type: NewPersonModel , enforce: [ :existence] + attribute :status, type: :status, enforce: [ :existence], + default: lambda { |record| StatusModel.find("single") } +end + class StatusModel < Goo::Base::Resource model :status_model, name_with: :name attribute :description, enforce: [ :existence, :unique] @@ -30,13 +48,46 @@ def initialize(attributes = {}) end end + +class YamlSchemeModelTest < Goo::Base::Resource + model :yaml_scheme_model_test, name_with: :name, scheme: 'test/data/yaml_scheme_model_test.yml' + attribute :name, enforce: [ :existence, :string, :unique] + attribute :last_name, enforce: [ :existence, :string, :unique] + attribute :birth_date, enforce: [ :existence, :date_time ] + attribute :nationality, enforce: [ :existence, :string ] + attribute :created, enforce: [ DateTime ], + default: lambda { |record| DateTime.now }, + namespace: :omv + attribute :friends, enforce: [ :existence , PersonModel] + attribute :status, enforce: [ :existence, :status ], + default: lambda { |record| StatusModel.find("single") } +end + + class TestDSLSeeting < MiniTest::Unit::TestCase def initialize(*args) super(*args) end + def test_data_type_dsl + _test_attributes_enforce NewPersonModel + end + def test_attributes_set_get + _test_attributes_enforce PersonModel + end + + def test_default_value + #default is on save ... returns` person = PersonModel.new + assert_equal nil, person.created + end + + + private + def _test_attributes_enforce(model) + person = model.new + model_key_name = model.model_name assert(person.respond_to? :id) assert(person.kind_of? Goo::Base::Resource) assert !person.valid? @@ -65,7 +116,7 @@ def test_attributes_set_get assert !person.valid? assert !person.errors[:birth_date] - person.birth_date = "X" + person.birth_date = "X" assert !person.valid? assert person.errors[:birth_date][:date_time] @@ -101,17 +152,17 @@ def test_attributes_set_get person.multiple_values << 99 end - friends = [PersonModel.new , PersonModel.new] + friends = [model.new , model.new] person.friends = friends assert !person.valid? assert person.errors[:friends][:no_list] - person.friends = PersonModel.new + person.friends = model.new assert !person.valid? - assert person.errors[:friends][:person_model] + assert person.errors[:friends][model_key_name] person.friends = "some one" assert !person.valid? - assert person.errors[:friends][:person_model] - person.friends = PersonModel.new + assert person.errors[:friends][model_key_name] + person.friends = model.new person.one_number = 99 assert !person.valid? @@ -125,7 +176,7 @@ def test_attributes_set_get assert !person.valid? assert person.errors[:one_number][:no_list] - person.one_number = 99 + person.one_number = 99 assert_equal(99, person.one_number) assert !person.valid? assert !person.errors[:one_number] @@ -137,10 +188,25 @@ def test_attributes_set_get assert !person.valid? end - def test_default_value - #default is on save ... returns` - person = PersonModel.new - assert_equal nil, person.created + def test_model_with_yaml_scheme + + settings = YamlSchemeModelTest.model_settings + attributes_settings = settings[:attributes] + + + assert_equal "test/data/yaml_scheme_model_test.yml", settings[:scheme] + + assert_equal 'Name', attributes_settings[:name][:label] + assert_equal 'Person name', attributes_settings[:name][:description] + assert_equal %w[test:name test2:name test3:person_name], attributes_settings[:name][:equivalents] + assert_equal 'Put the person name as string', attributes_settings[:name][:help] + assert_equal 'John', attributes_settings[:name][:example] + + + assert_equal 'Person nationality', attributes_settings[:nationality][:label] + hash = {fr: 'france', us: 'USA'} + assert_equal hash, attributes_settings[:nationality][:enforcedValues] + end end diff --git a/test/test_model_complex.rb b/test/test_model_complex.rb index 77d59a9b..4545d185 100644 --- a/test/test_model_complex.rb +++ b/test/test_model_complex.rb @@ -8,7 +8,7 @@ class Submission < Goo::Base::Resource end class Term < Goo::Base::Resource - model :class, + model :term, namespace: :owl, collection: :submission, name_with: :id, @@ -23,22 +23,22 @@ class Term < Goo::Base::Resource attribute :parents, namespace: :rdfs, property: lambda { |x| tree_property(x) }, - enforce: [:list, :class] + enforce: [:list, :term] attribute :ancestors, namespace: :rdfs, property: lambda { |x| tree_property(x) }, - enforce: [:list, :class], transitive: true + enforce: [:list, :term], transitive: true attribute :children, namespace: :rdfs, property: lambda { |x| tree_property(x) }, - inverse: { on: :class , attribute: :parents } + inverse: { on: :term , attribute: :parents } attribute :descendants, namespace: :rdfs, property: lambda { |x| tree_property(x) }, - inverse: { on: :class , attribute: :parents }, + inverse: { on: :term , attribute: :parents }, transitive: true def self.tree_property(*args) From d8e2b5c17512b781bb3d3f0441afae33f4ce8e3c Mon Sep 17 00:00:00 2001 From: Syphax Bouazzouni Date: Wed, 17 Apr 2024 16:25:43 +0200 Subject: [PATCH 2/7] implement on model update callback --- lib/goo/base/resource.rb | 37 +++++++++++++++------ lib/goo/base/settings/settings.rb | 10 ++++++ lib/goo/validators/enforce.rb | 15 +++++++++ lib/goo/validators/validator.rb | 6 +++- test/test_update_callbacks.rb | 53 +++++++++++++++++++++++++++++++ test/test_validators.rb | 1 + 6 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 test/test_update_callbacks.rb diff --git a/lib/goo/base/resource.rb b/lib/goo/base/resource.rb index e82265d4..ac68ccbc 100644 --- a/lib/goo/base/resource.rb +++ b/lib/goo/base/resource.rb @@ -298,26 +298,45 @@ def add_aggregate(attribute,aggregate,value) def save(*opts) if self.kind_of?(Goo::Base::Enum) - unless opts[0] && opts[0][:init_enum] - raise ArgumentError, "Enums can only be created on initialization" - end + raise ArgumentError, "Enums can only be created on initialization" unless opts[0] && opts[0][:init_enum] end batch_file = nil - if opts && opts.length > 0 - if opts.first.is_a?(Hash) && opts.first[:batch] && opts.first[:batch].is_a?(File) + callbacks = true + if opts && opts.length > 0 && opts.first.is_a?(Hash) + if opts.first[:batch] && opts.first[:batch].is_a?(File) batch_file = opts.first[:batch] end + + callbacks = opts.first[:callbacks] end if !batch_file - if not modified? - return self - end + return self if not modified? raise Goo::Base::NotValidException, "Object is not valid. Check errors." unless valid? end + #set default values before saving + unless self.persistent? + self.class.attributes_with_defaults.each do |attr| + value = self.send("#{attr}") + if value.nil? + value = self.class.default(attr).call(self) + self.send("#{attr}=", value) + end + end + end + + #call update callback before saving + if callbacks + self.class.attributes_with_update_callbacks.each do |attr| + Goo::Validators::Enforce.enforce_callbacks(self, attr) + end + end + graph_insert, graph_delete = Goo::SPARQL::Triples.model_update_triples(self) - graph = self.graph() + graph = self.graph + + if graph_delete and graph_delete.size > 0 begin Goo.sparql_update_client.delete_data(graph_delete, graph: graph) diff --git a/lib/goo/base/settings/settings.rb b/lib/goo/base/settings/settings.rb index b338f361..4a6b9b26 100644 --- a/lib/goo/base/settings/settings.rb +++ b/lib/goo/base/settings/settings.rb @@ -96,6 +96,16 @@ def attributes_with_defaults select{ |attr,opts| opts[:default] }).keys() end + def attributes_with_update_callbacks + (@model_settings[:attributes]. + select{ |attr,opts| opts[:onUpdate] }).keys + end + + + def update_callbacks(attr) + @model_settings[:attributes][attr][:onUpdate] + end + def default(attr) return @model_settings[:attributes][attr][:default] end diff --git a/lib/goo/validators/enforce.rb b/lib/goo/validators/enforce.rb index 4d0c09f4..d6f3816d 100644 --- a/lib/goo/validators/enforce.rb +++ b/lib/goo/validators/enforce.rb @@ -66,6 +66,17 @@ def enforce(inst,attr,value) errors_by_opt.length > 0 ? errors_by_opt : nil end + def enforce_callback(inst, attr) + callbacks = Array(inst.class.update_callbacks(attr)) + callbacks.each do |proc| + if instance_proc?(inst, proc) + call_proc(inst.method(proc), inst, attr) + elsif proc.is_a?(Proc) + call_proc(proc, inst, attr) + end + end + end + private def object_type(opt) @@ -117,6 +128,10 @@ def add_error(opt, err) def self.enforce(inst,attr,value) EnforceInstance.new.enforce(inst,attr,value) end + + def self.enforce_callbacks(inst, attr) + EnforceInstance.new.enforce_callback(inst, attr) + end end end end diff --git a/lib/goo/validators/validator.rb b/lib/goo/validators/validator.rb index 22d453ac..2536f985 100644 --- a/lib/goo/validators/validator.rb +++ b/lib/goo/validators/validator.rb @@ -91,7 +91,11 @@ def empty_string?(string) end def empty_to_s?(object) - object && object.to_s&.strip.empty? + begin + object && object.to_s&.strip.empty? + rescue + return false + end end def empty_array?(array) diff --git a/test/test_update_callbacks.rb b/test/test_update_callbacks.rb new file mode 100644 index 00000000..bef38a68 --- /dev/null +++ b/test/test_update_callbacks.rb @@ -0,0 +1,53 @@ +require_relative 'test_case' + + +require_relative 'models' + +class TestUpdateCallBack < Goo::Base::Resource + model :update_callback_model, name_with: :code + attribute :code, enforce: [:string, :existence] + attribute :name, enforce: [:string, :existence] + attribute :first_name, onUpdate: :update_name + attribute :last_name, onUpdate: :update_name + + + def update_name(inst, attr) + self.name = self.first_name + self.last_name + end +end + +class TestUpdateCallBacks < MiniTest::Unit::TestCase + + def self.before_suite + GooTestData.delete_all [TestUpdateCallBack] + end + + def self.after_suite + GooTestData.delete_all [TestUpdateCallBack] + end + + + def test_update_callback + p = TestUpdateCallBack.new + p.code = "1" + p.name = "name" + p.first_name = "first_name" + p.last_name = "last_name" + + assert p.valid? + p.save + + p.bring_remaining + + assert_equal p.first_name + p.last_name, p.name + + p.last_name = "last_name2" + p.save + + p.bring_remaining + assert_equal "last_name2", p.last_name + assert_equal p.first_name + p.last_name, p.name + end + +end + diff --git a/test/test_validators.rb b/test/test_validators.rb index e5c3a9fe..5110da80 100644 --- a/test/test_validators.rb +++ b/test/test_validators.rb @@ -1,5 +1,6 @@ require_relative 'test_case' +GooTest.configure_goo require_relative 'models' class Person < Goo::Base::Resource From 8adda81dbf70cfa4f4eb3892a21006f97fa89e03 Mon Sep 17 00:00:00 2001 From: Syphax Bouazzouni Date: Wed, 17 Apr 2024 16:26:32 +0200 Subject: [PATCH 3/7] refactor and clean the model settings code --- .ruby-version | 1 + Gemfile.lock | 4 ++- goo.gemspec | 3 +- lib/goo/base/resource.rb | 45 ++++++++---------------------- lib/goo/base/settings/settings.rb | 30 +++++++++++++++----- lib/goo/sparql/solutions_mapper.rb | 1 + test/test_dsl_settings.rb | 2 -- test/test_validators.rb | 1 - 8 files changed, 42 insertions(+), 45 deletions(-) create mode 100644 .ruby-version diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..6a81b4c8 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.7.8 diff --git a/Gemfile.lock b/Gemfile.lock index b6867344..2544fa8e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -121,6 +121,8 @@ GEM PLATFORMS x86_64-darwin-18 + x86_64-darwin-23 + x86_64-linux DEPENDENCIES activesupport @@ -139,4 +141,4 @@ DEPENDENCIES uuid BUNDLED WITH - 2.3.15 + 2.4.22 diff --git a/goo.gemspec b/goo.gemspec index c3386799..86b50832 100644 --- a/goo.gemspec +++ b/goo.gemspec @@ -6,7 +6,8 @@ Gem::Specification.new do |s| s.email = "manuelso@stanford.edu" s.files = Dir["lib/**/*.rb"] s.homepage = "http://github.com/ncbo/goo" - s.add_dependency("addressable", "~> 2.8") + + s.add_dependency("addressable", "~> 2.8") s.add_dependency("pry") s.add_dependency("rdf", "= 1.0.8") s.add_dependency("redis") diff --git a/lib/goo/base/resource.rb b/lib/goo/base/resource.rb index ac68ccbc..fd50eb80 100644 --- a/lib/goo/base/resource.rb +++ b/lib/goo/base/resource.rb @@ -42,9 +42,7 @@ def valid? self.class.attributes.each do |attr| inst_value = self.instance_variable_get("@#{attr}") attr_errors = Goo::Validators::Enforce.enforce(self,attr,inst_value) - unless attr_errors.nil? - validation_errors[attr] = attr_errors - end + validation_errors[attr] = attr_errors unless attr_errors.nil? end if !@persistent && validation_errors.length == 0 @@ -70,9 +68,7 @@ def valid? end def id=(new_id) - if !@id.nil? and @persistent - raise ArgumentError, "The id of a persistent object cannot be changed." - end + raise ArgumentError, "The id of a persistent object cannot be changed." if !@id.nil? and @persistent raise ArgumentError, "ID must be an RDF::URI" unless new_id.kind_of?(RDF::URI) @id = new_id end @@ -128,6 +124,7 @@ def unmapped_set(attribute,value) def unmmaped_to_array cpy = {} + @unmapped.each do |attr,v| cpy[attr] = v.to_a end @@ -136,9 +133,7 @@ def unmmaped_to_array def delete(*args) if self.kind_of?(Goo::Base::Enum) - unless args[0] && args[0][:init_enum] - raise ArgumentError, "Enums cannot be deleted" - end + raise ArgumentError, "Enums cannot be deleted" unless args[0] && args[0][:init_enum] end raise ArgumentError, "This object is not persistent and cannot be deleted" if !@persistent @@ -146,9 +141,7 @@ def delete(*args) if !fully_loaded? missing = missing_load_attributes options_load = { models: [ self ], klass: self.class, :include => missing } - if self.class.collection_opts - options_load[:collection] = self.collection - end + options_load[:collection] = self.collection if self.class.collection_opts Goo::SPARQL::Queries.model_load(options_load) end @@ -164,9 +157,7 @@ def delete(*args) end @persistent = false @modified = true - if self.class.inmutable? && self.class.inm_instances - self.class.load_inmutable_instances - end + self.class.load_inmutable_instances if self.class.inmutable? && self.class.inm_instances return nil end @@ -174,15 +165,11 @@ def bring(*opts) opts.each do |k| if k.kind_of?(Hash) k.each do |k2,v| - if self.class.handler?(k2) - raise ArgumentError, "Unable to bring a method based attr #{k2}" - end + raise ArgumentError, "Unable to bring a method based attr #{k2}" if self.class.handler?(k2) self.instance_variable_set("@#{k2}",nil) end else - if self.class.handler?(k) - raise ArgumentError, "Unable to bring a method based attr #{k}" - end + raise ArgumentError, "Unable to bring a method based attr #{k}" if self.class.handler?(k) self.instance_variable_set("@#{k}",nil) end end @@ -197,9 +184,7 @@ def bring(*opts) def graph opts = self.class.collection_opts - if opts.nil? - return self.class.uri_type - end + return self.class.uri_type if opts.nil? col = collection if col.is_a?Array if col.length == 1 @@ -281,9 +266,7 @@ def collection if opts.instance_of?(Symbol) if self.class.attributes.include?(opts) value = self.send("#{opts}") - if value.nil? - raise ArgumentError, "Collection `#{opts}` is nil" - end + raise ArgumentError, "Collection `#{opts}` is nil" if value.nil? return value else raise ArgumentError, "Collection `#{opts}` is not an attribute" @@ -370,9 +353,7 @@ def save(*opts) @modified_attributes = Set.new @persistent = true - if self.class.inmutable? && self.class.inm_instances - self.class.load_inmutable_instances - end + self.class.load_inmutable_instances if self.class.inmutable? && self.class.inm_instances return self end @@ -410,9 +391,7 @@ def to_hash end end @unmapped.each do |attr,values| - unless all_attr_uris.include?(attr) - attr_hash[attr] = values.map { |v| v.to_s } - end + attr_hash[attr] = values.map { |v| v.to_s } unless all_attr_uris.include?(attr) end end attr_hash[:id] = @id diff --git a/lib/goo/base/settings/settings.rb b/lib/goo/base/settings/settings.rb index 4a6b9b26..5512278e 100644 --- a/lib/goo/base/settings/settings.rb +++ b/lib/goo/base/settings/settings.rb @@ -200,9 +200,12 @@ def attribute(*args) attr_name = attr_name.to_sym options = options.pop options = {} if options.nil? - if options[:enforce].nil? or !options[:enforce].include?(:list) - options[:enforce] = options[:enforce] ? (options[:enforce] << :no_list) : [:no_list] - end + + options[:enforce] ||= [] + + set_data_type(options) + set_no_list_by_default(options) + @model_settings[:attributes][attr_name] = options load_yaml_scheme_options(attr_name) shape_attribute(attr_name) @@ -248,15 +251,13 @@ def shape_attribute(attr) raise ArgumentError, "Method based attributes cannot be set" end if self.class.inverse?(attr) && !(args && args.last.instance_of?(Hash) && args.last[:on_load]) - raise ArgumentError, - "`#{attr}` is an inverse attribute. Values cannot be assigned." + raise ArgumentError, "`#{attr}` is an inverse attribute. Values cannot be assigned." end @loaded_attributes.add(attr) value = args[0] unless args.last.instance_of?(Hash) and args.last[:on_load] if self.persistent? and self.class.name_with == attr - raise ArgumentError, - "`#{attr}` attribute is used to name this resource and cannot be modified." + raise ArgumentError, "`#{attr}` attribute is used to name this resource and cannot be modified." end prev = self.instance_variable_get("@#{attr}") if !prev.nil? and !@modified_attributes.include?(attr) @@ -388,6 +389,21 @@ def read_only(attributes) instance end + + private + + def set_no_list_by_default(options) + if options[:enforce].nil? or !options[:enforce].include?(:list) + options[:enforce] = options[:enforce] ? (options[:enforce] << :no_list) : [:no_list] + end + end + def set_data_type(options) + if options[:type] + options[:enforce] += Array(options[:type]) + options[:enforce].uniq! + options.delete :type + end + end end end end diff --git a/lib/goo/sparql/solutions_mapper.rb b/lib/goo/sparql/solutions_mapper.rb index 954ceca9..3ee764f3 100644 --- a/lib/goo/sparql/solutions_mapper.rb +++ b/lib/goo/sparql/solutions_mapper.rb @@ -24,6 +24,7 @@ def initialize(aggregate_projections, bnode_extraction, embed_struct, @incl = options[:include] @count = options[:count] @collection = options[:collection] + @options = options end def map_each_solutions(select) diff --git a/test/test_dsl_settings.rb b/test/test_dsl_settings.rb index 9a8f03df..50bbc5c6 100644 --- a/test/test_dsl_settings.rb +++ b/test/test_dsl_settings.rb @@ -1,7 +1,5 @@ require_relative 'test_case' -GooTest.configure_goo - class NewPersonModel < Goo::Base::Resource model :person_model_new, name_with: :name attribute :name, type: :string, enforce: [ :existence, :unique] diff --git a/test/test_validators.rb b/test/test_validators.rb index 5110da80..e5c3a9fe 100644 --- a/test/test_validators.rb +++ b/test/test_validators.rb @@ -1,6 +1,5 @@ require_relative 'test_case' -GooTest.configure_goo require_relative 'models' class Person < Goo::Base::Resource From 7a23f08a8aae4426a071ef46f909d51ac7b1436c Mon Sep 17 00:00:00 2001 From: Syphax Bouazzouni Date: Wed, 17 Apr 2024 17:00:02 +0200 Subject: [PATCH 4/7] add again regex filter --- lib/goo/sparql/query_builder.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/goo/sparql/query_builder.rb b/lib/goo/sparql/query_builder.rb index 7ef72193..9d8e59e2 100644 --- a/lib/goo/sparql/query_builder.rb +++ b/lib/goo/sparql/query_builder.rb @@ -311,13 +311,18 @@ def query_filter_sparql(klass, filter, filter_patterns, filter_graphs, filter_var = inspected_patterns[filter_pattern_match] if !filter_operation.value.instance_of?(Goo::Filter) - if filter_operation.operator == :unbound || filter_operation.operator == :bound - if filter_operation.operator == :unbound - filter_operations << "!BOUND(?#{filter_var.to_s})" - else - filter_operations << "BOUND(?#{filter_var.to_s})" - end + case filter_operation.operator + when :unbound + filter_operations << "!BOUND(?#{filter_var.to_s})" + return :optional + + when :bound + filter_operations << "BOUND(?#{filter_var.to_s})" return :optional + when :regex + if filter_operation.value.is_a?(String) + filter_operations << "REGEX(STR(?#{filter_var.to_s}) , \"#{filter_operation.value.to_s}\", \"i\")" + end else value = RDF::Literal.new(filter_operation.value) if filter_operation.value.is_a? String From 28f8969c8c4f2f436c360b95455473c62de29ad6 Mon Sep 17 00:00:00 2001 From: Alex Skrenchuk Date: Wed, 25 Sep 2024 16:08:30 -0700 Subject: [PATCH 5/7] ruby v3.0 upgrade --- .ruby-version | 2 +- Gemfile.lock | 49 ++++++++++++++++++++++++++-------------------- docker-compose.yml | 4 ++-- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/.ruby-version b/.ruby-version index 6a81b4c8..818bd47a 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.8 +3.0.6 diff --git a/Gemfile.lock b/Gemfile.lock index 7283992d..69c9a18f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,45 +31,50 @@ GEM multi_json (~> 1.3) thread_safe (~> 0.1) tzinfo (~> 0.3.37) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) base64 (0.2.0) - builder (3.2.4) + builder (3.3.0) coderay (1.1.3) - concurrent-ruby (1.2.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) cube-ruby (0.0.3) daemons (1.4.1) - docile (1.4.0) + docile (1.4.1) domain_name (0.6.20240107) eventmachine (1.2.7) - faraday (2.8.1) - base64 - faraday-net_http (>= 2.0, < 3.1) - ruby2_keywords (>= 0.0.4) - faraday-net_http (3.0.2) + faraday (2.12.0) + faraday-net_http (>= 2.0, < 3.4) + json + logger + faraday-net_http (3.3.0) + net-http http-accept (1.7.0) - http-cookie (1.0.5) + http-cookie (1.0.7) domain_name (~> 0.5) i18n (0.9.5) concurrent-ruby (~> 1.0) + json (2.7.2) json_pure (2.7.2) + logger (1.6.1) macaddr (1.7.2) systemu (~> 2.6.5) method_source (1.1.0) mime-types (3.5.2) mime-types-data (~> 3.2015) - mime-types-data (3.2024.0305) + mime-types-data (3.2024.0903) minitest (4.7.5) multi_json (1.15.0) - mustermann (3.0.0) + mustermann (3.0.3) ruby2_keywords (~> 0.0.1) + net-http (0.4.1) + uri net-http-persistent (2.9.4) netrc (0.11.0) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) - public_suffix (5.0.5) + public_suffix (6.0.1) rack (2.2.9) rack-accept (0.4.5) rack (>= 0.4) @@ -81,18 +86,18 @@ GEM rake (13.2.1) rdf (1.0.8) addressable (>= 2.2) - redis (5.2.0) + redis (5.3.0) redis-client (>= 0.22.0) - redis-client (0.22.1) + redis-client (0.22.2) connection_pool - request_store (1.6.0) + request_store (1.7.0) rack (>= 1.4) rest-client (2.1.0) http-accept (>= 1.7.0, < 2.0) http-cookie (>= 1.0.2, < 2.0) mime-types (>= 1.16, < 4.0) netrc (~> 0.8) - rexml (3.2.6) + rexml (3.3.7) rsolr (2.6.0) builder (>= 2.1.2) faraday (>= 0.9, < 3, != 2.0.0) @@ -104,7 +109,7 @@ GEM simplecov-cobertura (2.1.0) rexml simplecov (~> 0.19) - simplecov-html (0.12.3) + simplecov-html (0.13.1) simplecov_json_formatter (0.1.4) sinatra (3.2.0) mustermann (~> 3.0) @@ -117,12 +122,14 @@ GEM eventmachine (~> 1.0, >= 1.0.4) rack (>= 1, < 3) thread_safe (0.3.6) - tilt (2.3.0) + tilt (2.4.0) tzinfo (0.3.62) + uri (0.13.1) uuid (2.3.9) macaddr (~> 1.0) PLATFORMS + arm64-darwin-22 x86_64-darwin-21 x86_64-darwin-23 x86_64-linux @@ -144,4 +151,4 @@ DEPENDENCIES uuid BUNDLED WITH - 2.4.22 + 2.5.20 diff --git a/docker-compose.yml b/docker-compose.yml index f66e7fef..3d11d903 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: retries: 30 solr-ut: - image: ontoportal/solr-ut:0.1.0 + image: ontoportal/solr-ut:0.2.0 ports: - 8983:8983 healthcheck: @@ -21,7 +21,7 @@ services: retries: 5 agraph-ut: - image: franzinc/agraph:v8.1.0 + image: franzinc/agraph:v8.2.1 platform: linux/amd64 environment: - AGRAPH_SUPER_USER=test From aaa3941b48edbc317ec42ba4ecb44c0defeccef6 Mon Sep 17 00:00:00 2001 From: Alex Skrenchuk Date: Wed, 25 Sep 2024 16:20:49 -0700 Subject: [PATCH 6/7] add ruby 3.1 to test matrix --- .github/workflows/ruby-unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby-unit-test.yml b/.github/workflows/ruby-unit-test.yml index 906e1ad5..659ec31b 100644 --- a/.github/workflows/ruby-unit-test.yml +++ b/.github/workflows/ruby-unit-test.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - ruby-version: ['2.7', '3.0'] + ruby-version: ['3.0', '3.1'] triplestore: ['fs', 'ag'] steps: From 9b15e2422e437277102531cb32689046175a0456 Mon Sep 17 00:00:00 2001 From: Alex Skrenchuk Date: Mon, 30 Sep 2024 18:06:41 -0700 Subject: [PATCH 7/7] use pre-multilingual solr schema ontoportal:solr-ut:0.1.0 multilingual solr schema has multivalued perfLabels which is not handleled in the goo. This would not be an issue once schemaless solr is adopted --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3d11d903..43507c3f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: retries: 30 solr-ut: - image: ontoportal/solr-ut:0.2.0 + image: ontoportal/solr-ut:0.1.0 ports: - 8983:8983 healthcheck: