Skip to content
This repository was archived by the owner on Dec 12, 2021. It is now read-only.
Open
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
6 changes: 4 additions & 2 deletions lib/xapit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'rack'
require 'json'
require 'net/http'
require 'active_support'
require 'time'

module Xapit
Expand All @@ -29,9 +30,9 @@ def reload
@config.merge!(@loaded_config) if @loaded_config
end

def database
def database(force_local = false)
raise Disabled, "Unable to access Xapit database because it is disabled in configuration." unless Xapit.config[:enabled]
if config[:server]
if config[:server] && !force_local
@database ||= Xapit::Client::RemoteDatabase.new(config[:server])
elsif config[:read_only]
@database ||= Xapit::Server::ReadOnlyDatabase.new(config[:database_path])
Expand Down Expand Up @@ -140,3 +141,4 @@ def import_changes
require 'xapit/client/model_adapters/abstract_model_adapter'
require 'xapit/client/model_adapters/default_model_adapter'
require 'xapit/client/model_adapters/active_record_adapter'
require 'xapit/client/model_adapters/mongoid_adapter'
5 changes: 3 additions & 2 deletions lib/xapit/client/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ def initialize(clauses = [])
end

def in_classes(*classes)
scope(:in_classes, classes)
scope(:in_classes, classes.map(&:to_s))
end

def not_in_classes(*classes)
scope(:not_in_classes, classes)
scope(:not_in_classes, classes.map(&:to_s))
end

def search(phrase = nil)
Expand Down Expand Up @@ -89,6 +89,7 @@ def equal?(other)
def total_entries
query[:total].to_i
end
alias :total_count :total_entries

def current_page
(clause_value(:page) || 1).to_i
Expand Down
39 changes: 32 additions & 7 deletions lib/xapit/client/index_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ module Xapit
module Client
class IndexBuilder
attr_reader :attributes
attr_reader :language

def initialize
@attributes = {}
@language = Xapit.config[:stemming]
end

def text(*args, &block)
Expand All @@ -24,20 +27,26 @@ def facet(name, custom_name = nil, &block)
add_attribute(:facet, name, options, &block)
end

def add_document(member)
Xapit.database.add_document(document_data(member))
def add_document(member, force_local = false)
Xapit.database(force_local).add_document(document_data(member))
end

def remove_document(member)
Xapit.database.remove_document(document_data(member))
def remove_document(member, force_local = false)
Xapit.database(force_local).remove_document(document_data(member))
end

def update_document(member)
Xapit.database.update_document(document_data(member))
def update_document(member, force_local = false)
Xapit.database(force_local).update_document(document_data(member))
end

def document_data(member)
data = {:class => member.class.name, :id => member.id, :attributes => {}}
data = {
:class => member.class.name,
:id => member.id,
:attributes => {},
:language => find_language(member)
}

attributes.each do |name, options|
options = options.dup # so we can remove block without changing original hash
value = member.send(name)
Expand All @@ -53,8 +62,24 @@ def facets
end
end

def language(lang)
@language = lang
end

private

def find_language(member)
lang = if @language.kind_of?(Symbol)
member.send(@language)
elsif @language.kind_of?(Proc)
@language.call(member)
else
@language
end

lang || 'english'
end

def add_attribute(type, *args, &block)
options = args.last.kind_of?(Hash) ? args.pop : {}
args.each do |attribute|
Expand Down
4 changes: 2 additions & 2 deletions lib/xapit/client/model_adapters/active_record_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Xapit
module Client
class ActiveRecordAdapter < AbstractModelAdapter
def self.for_class?(model_class)
model_class <= ActiveRecord::Base
defined?(ActiveRecord::Base) && model_class <= ActiveRecord::Base
end

def setup
Expand All @@ -19,7 +19,7 @@ def setup

def index_all
@model_class.find_each do |member|
member.class.xapit_index_builder.add_document(member)
member.class.xapit_index_builder.add_document(member, true)
end
end
end
Expand Down
32 changes: 32 additions & 0 deletions lib/xapit/client/model_adapters/mongoid_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Xapit
module Client
class MongoidAdapter < AbstractModelAdapter
def self.for_class?(model_class)
defined?(Mongoid::Document) && model_class <= Mongoid::Document
end

def setup
@model_class.after_create do |member|
member.class.xapit_index_builder.add_document(member) if Xapit.config[:enabled]
end
@model_class.after_update do |member|
member.class.xapit_index_builder.update_document(member) if Xapit.config[:enabled]
end
@model_class.after_destroy do |member|
member.class.xapit_index_builder.remove_document(member) if Xapit.config[:enabled]
end
end

def index_all
@model_class.all.each do |member|
member.class.xapit_index_builder.add_document(member, true)
end
end
end
end
end

if defined?(Mongoid::Document)
Mongoid::Document::ClassMethods.send(:include, Xapit::Client::Membership::ClassMethods)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? I want those methods available on sinatra too, that's not rails exclusive

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good, then is a good idea move the AR one to active_record_adapter.rb

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then is a good idea move the AR one to the adapter also :)

end

2 changes: 1 addition & 1 deletion lib/xapit/server/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def authorized_action(command, params)

def action(command, json)
data = Xapit.symbolize_keys(JSON.parse(json))
render :content => Xapit.database.send(command, data).to_json
render :content => Xapit.database(true).send(command, data).to_json
end

def render(options = {})
Expand Down
46 changes: 38 additions & 8 deletions lib/xapit/server/indexer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,35 @@ def values
values
end

# TODO refactor with stemmed_text_terms
def text_terms
terms = []
each_attribute(:text) do |name, value, options|
value = value.to_s.split(/\s+/u).map { |w| w.gsub(/[^\w]/u, "") } unless value.kind_of? Array
value.map(&:to_s).map(&:downcase).map do |term|
[term, options[:weight] || 1] unless term.empty?
words = value
words = value.to_s.split(/\s+/u) unless value.kind_of? Array

weight = options[:weight] || 1
words.each do |word|
next if word.empty? || word.bytesize >= 245

word.downcase!

terms << [word, weight]
terms << stemmed_term(word, weight)

clean_word = ActiveSupport::Multibyte::Chars.new(word).normalize(:kd).gsub(/[^\w]/u, "").to_s
if !clean_word.empty? && clean_word != word
terms << [clean_word, weight]
terms << stemmed_term(clean_word, weight)
end
end
end.flatten(1).compact
end

terms.uniq
end

# TODO refactor with stemmed_text_terms
def stemmed_text_terms
if stemmer
if stemmer = build_stemmer
each_attribute(:text) do |name, value, options|
value = value.to_s.split(/\s+/u).map { |w| w.gsub(/[^\w]/u, "") } unless value.kind_of? Array
value.map(&:to_s).map(&:downcase).map do |term|
Expand Down Expand Up @@ -94,8 +110,22 @@ def save_facets

private

def stemmer
@stemmer ||= Xapian::Stem.new(Xapit.config[:stemming]) if Xapit.config[:stemming]
def build_stemmer
begin
Xapian::Stem.new(@data[:language])
rescue ArgumentError
return nil
end
end

def stemmed_term(word, weight = 1)
term = [word, weight]
if stemmer = build_stemmer
stemmed = stemmer.call(word)
term = ["Z#{word}", weight] if stemmed != word
end

term
end

def base_terms
Expand Down
2 changes: 1 addition & 1 deletion xapit.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Gem::Specification.new do |s|
s.files = Dir["{lib,spec,features,rails_generators,tasks}/**/*", "[A-Z]*", "init.rb", "install.rb", "uninstall.rb"] - ["Gemfile.lock"]
s.require_path = "lib"

s.add_dependency 'rack'
s.add_dependency 'rack', '~> 1.3.4'

s.add_development_dependency 'rspec', '~> 2.7.0'
s.add_development_dependency 'cucumber', '~> 0.10.2'
Expand Down