Skip to content

Commit

Permalink
add hash-bashed sub-document finder; add support for add_conditions t…
Browse files Browse the repository at this point in the history
…o Array; update README for latest features
  • Loading branch information
mccolin committed Mar 30, 2010
1 parent f692f6f commit d8fe7c3
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 26 deletions.
29 changes: 24 additions & 5 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ Once you've migrated that change into your model, here's a sample of hold to add
# Declare that we are using document blobs in a particular column of this object:
do_document_fields

# If we wanted to change the name of the field we use for documents, we'd do this:
# do_document_fields :something_other_than_document

# Declare the columns we are adding to our document:
document_field :name, String
document_field :phone, String
Expand All @@ -24,6 +21,23 @@ Once you've migrated that change into your model, here's a sample of hold to add
# Declare the document fields you'd like to track with indexes:
document_index :name


# If we wanted to change the name of the column in which we store the document, we'd do this:
# do_document_fields :something_other_than_document. Like so:

do_document_fields :settings

# Changing the name of the column gives you a specifically-formatted field-definition method:

settings_field :age
settings_field :sex
settings_field :location

# This also provides a customized way to index:

settings_index :location


end


Expand All @@ -38,9 +52,14 @@ Once you've added any indices to your model's fields, you'll want to be sure to
Now, you can use strictly-provided finders to find your objects by their document field attributes. Considering the model we described above, you can lookup by any *indexed* field like so:

obj = ObjectWithBlob.find_by_name("Charlie")
=> #<ObjectWithBlob id: 412, document: {:name=>"Charlie", :phone=>"212-555-1234", :age=>34}, created_at: "2010-03-22 20:49:03", updated_at: "2010-03-22 20:49:03">
=> [#<ObjectWithBlob id: 412, document: {:name=>"Charlie", :phone=>"212-555-1234", :age=>34}, created_at: "2010-03-22 20:49:03", updated_at: "2010-03-22 20:49:03">]

Finders are only added to document fields that are indexed. Finders also are all "find_all" lookups on equality.

If you'd like to use special sub-searching within any of your document-formatted fields, you can use the hash-based search conditions. Given the "settings" document declared in the example above, we can now also do this:

Finders are only added to document fields that are indexed.
obj = ObjectWithBlob.find_with_settings(:location=>"San Francisco, CA")
=> [#<ObjectWithBlob id: 412, settings: {:age=>32, :sex=>"Female", :location=>"San Francisco, CA"}, created_at: "2010-03-22 20:49:03", updated_at: "2010-03-22 20:49:03">]


It's simple.
Expand Down
5 changes: 4 additions & 1 deletion init.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# AWEXOME
# DoDocumentFields - initializer

require 'missing_hash'
require 'utils'
require 'do_document_fields'
Hash.class_eval do
include Awexome::Util::MissingHash
end
Array.class_eval do
include Awexome::Util::CondArray
end
ActiveRecord::Base.class_eval do
include Awexome::Do::DocumentFields
end
Expand Down
14 changes: 14 additions & 0 deletions lib/do_document_fields.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,20 @@ def find_by_#{column_name}_#{field_name}(val)
def find_by_#{field_name}(val)
find_by_#{column_name}_#{field_name}(val)
end
def find_with_#{column_name}(hash={})
conditions = Array.new
hash.each do |key, val|
conditions.add_condition(["`#{index_table_name}`.field = ? AND `#{index_table_name}`.value = ?", "#{search_field_name}", val])
end
find(
:all,
:select=>"*",
:from=>"#{index_table_name}",
:conditions=>conditions,
:joins=>"LEFT JOIN `#{class_table_name}` ON `#{class_table_name}`.id = `#{index_table_name}`.doc_id"
)
end
EOS

# after_save callback to update index
Expand Down
20 changes: 0 additions & 20 deletions lib/missing_hash.rb

This file was deleted.

39 changes: 39 additions & 0 deletions lib/utils.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# AWEXOME
# MissingHash - a Hash reimplementation with direct-access to top-level keys

module Awexome
module Util

module MissingHash
def method_missing(method, *args)
unless method.to_s.scan(/=$/).empty?
return self[method.to_s.gsub(/=$/,"").to_sym] = args.shift
else
return self[method] if self.keys.include?(method)
end
super(method, *args)
end
end # MissingHash


module CondArray
def add_condition(cond, conj="AND")
if cond.is_a?(Array)
if self.empty?
(self << cond).flatten!
else
self[0] += " #{conj} #{cond.shift}"
(self << cond).flatten!
end
elsif cond.is_a?(String)
self[0] += " #{conj} #{cond}"
else
raise "Condition must be an Array or String"
end
self
end
end

end # Util
end # Awexome

0 comments on commit d8fe7c3

Please sign in to comment.