Skip to content

Commit

Permalink
Merge pull request #25 from GD-Personal/bug_fix
Browse files Browse the repository at this point in the history
Release v0.4.2 (22-09-2024) - Bug fix
  • Loading branch information
gerdadecio authored Sep 22, 2024
2 parents c74eed4 + 1e48f5e commit 0dbe3de
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 19 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Version: 0.4.2 (23-09-2024)

* [#25](https://github.com/GD-Personal/flexi-json/pull/25): A bug from [v0.4.0](https://github.com/GD-Personal/flexi-json/releases/tag/v0.4.0) was introduced where the advanced search function don't work properly when the options.

# Version: 0.4.1 (22-09-2024)

* [0270c44](https://github.com/GD-Personal/flexi-json/commit/0270c44d7ffabd88ed0b69b09f1e98910257d99b): Update the readme and changelog
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
flexi-json (0.4.1)
flexi-json (0.4.2)

GEM
remote: https://rubygems.org/
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ flexi_json.find_duplicates("email,full_name")

## Advanced search
```ruby
options = {matched_all: true, exact_match: false}
flexi_json.search({first_name: "john", address: "sydney"}, options)
search_query = {first_name: "john", address: "sydney"}
flexi_json.search(
search_query,
options: {matched_all: true, exact_match: false}
)
# => [#<Flexi::Json::Dataset:0x0000ffffa0f5f668 @address="Sydney Australia", @attributes={:name=>"John", :address=>"Sydney Australia"}, @name="John", @searchable_fields=["name", "address"]>]
```

Expand Down
6 changes: 2 additions & 4 deletions lib/flexi/json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ module Flexi::Json
class << self
attr_writer :configuration

# Access or initialize the configuration object
def configuration
@configuration ||= Flexi::Json::Configuration.instance
end

# Configure block for setting custom configurations
def configure
yield(configuration)
end
Expand All @@ -26,8 +24,8 @@ def new(data)
end
end

def search(query = "", fields = nil)
@searcher.search(query, fields)
def search(query = "", fields = nil, options: nil)
@searcher.search(query, fields, options: options)
end

def find_duplicates(keys)
Expand Down
28 changes: 20 additions & 8 deletions lib/flexi/json/dataset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,22 @@ def initialize(attributes = {})
end
end

def matches?(query, fields = searchable_fields, options: Flexi::Json::Configuration.default_match_options)
validateable_fields = query.is_a?(Hash) ? query.keys.map(&:to_s) : fields
valid_fields = validateable_fields&.select { |field| searchable_fields.include?(field) } || searchable_fields
def matches?(query, fields = nil, options: nil)
options ||= Flexi::Json::Configuration.default_match_options

valid_fields = validateable_fields(query, fields)&.select do |field|
searchable_fields.include?(field)
end || searchable_fields

return false if valid_fields.empty?

matching_method = options[:match_all] ? :all? : :any?
valid_fields.public_send(matching_method) do |field|
search_query = query.is_a?(Hash) ? query[field.to_sym] : query
if options[:exact_match]
attributes[field.to_sym].to_s.downcase == search_query.to_s.downcase
else
attributes[field.to_sym].to_s.downcase.include?(search_query.to_s.downcase)
end
attribute_value = attributes[field.to_sym].to_s.downcase
query_value = search_query.to_s.downcase

options[:exact_match] ? attribute_value == query_value : attribute_value.include?(query_value)
end
end

Expand All @@ -35,6 +37,16 @@ def searchable_fields

private

def validateable_fields(query, fields)
if query.is_a?(Hash)
query.keys.map(&:to_s)
elsif fields.is_a?(String)
fields.delete(" ").split(",")
elsif fields.is_a?(Array)
[fields || searchable_fields].flatten
end
end

# Method to validate that a key is a valid method name and not dangerous
def valid_key?(key)
key.match?(/\A[a-z_][a-zA-Z0-9_]*\z/) && !dangerous_method?(key)
Expand Down
4 changes: 2 additions & 2 deletions lib/flexi/json/searcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ def initialize(data)
@result = []
end

def search(query, fields = nil)
@result = @data.select { |data| data.matches?(query, fields) }
def search(query, fields = nil, options: nil)
@result = @data.select { |data| data.matches?(query, fields, options: options) }
end

def find_duplicates(keys)
Expand Down
2 changes: 1 addition & 1 deletion lib/flexi/json/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module Flexi
module Json
VERSION = "0.4.1"
VERSION = "0.4.2"
end
end
1 change: 0 additions & 1 deletion spec/flexi/json/dataset_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require "spec_helper"
require "debug"

RSpec.describe Flexi::Json::Dataset do
describe ".initialize" do
Expand Down
64 changes: 64 additions & 0 deletions spec/flexi/json_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,68 @@
end
end
end

describe "#search" do
subject { described_class.new("./spec/data/dataset.json") }

context "for query param" do
it "works for string type" do
expect(subject.search("john")).not_to eq []
end

it "works for array type" do
expect(subject.search(["john"])).to eq []
end
end

context "for fields param" do
it "works for string type" do
expect(subject.search("john", "full_name")).not_to eq []
expect(subject.search("john", "full_name, email")).not_to eq []
end
it "works for array type" do
expect(subject.search("john", ["full_name"])).not_to eq []
expect(subject.search("john", ["full_name", "email"])).not_to eq []
end
end

context "for options params" do
it "works for match_all option" do
options = {match_all: true}
expect(subject.search("john", "full_name", options: options)).not_to eq []

query = {full_name: "john", email: "[email protected]"}
expect(subject.search(query, "full_name", options: options)).to eq []

query = {full_name: "john", email: "john.doe"}
expect(subject.search(query, options: options)).not_to eq []
end

it "works for exact_match option" do
options = {exact_match: true}
expect(subject.search("john", "full_name", options: options)).to eq []
expect(subject.search("john doe", "full_name", options: options)).not_to eq []

query = {full_name: "john", email: "john.doe"}
expect(subject.search(query, "full_name", options: options)).to eq []
end

it "works for both options" do
options = {exact_match: true, match_all: true}
query = {full_name: "john", email: "[email protected]"}
expect(subject.search(query, options: options)).to eq []

query = {full_name: "john doe", email: "[email protected]"}
expect(subject.search(query, options: options)).not_to eq []
end
end
end

describe "#find_duplicates" do
subject { described_class.new("./spec/data/dataset.json") }
it "works" do
expect(subject.find_duplicates("email").size).to eq 2
expect(subject.find_duplicates("unknown_key").size).to eq 0
end
end
end

0 comments on commit 0dbe3de

Please sign in to comment.