A from-scratch fork of simply_couch's model layer that runs on Couchbase natively: `include SimplyBased::Model` instead of `include SimplyCouch::Model`. - SimplyBased::Store replaces the CouchDB layer: KV documents, N1QL/SQL++ finders + lazily-created GSIs, CAS mapped onto _rev. No design documents or JavaScript map/reduce — the hand-written association views become N1QL (belongs_to/has_many/has_one scalar FK; habtm via ANY ... SATISFIES + array index, or KV multi-get on the storing side). - Redis replacements on the same cluster: Counter (atomic increment/decrement), Cache (ActiveSupport::Cache::Store over KV+TTL, drop-in Rails.cache/ActiveJob), Lock (insert-if-absent + TTL + CAS-checked release). - Runs the simply_couch test suite against live Couchbase: 378/432 applicable examples green (CouchDB-mechanic specs tagged :couchdb_only and excluded). - Remaining: ancestry (tree) + embedded_in reverse-lookups (recursive/embedded N1QL) and a few pagination/lifecycle edges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
2.5 KiB
Ruby
78 lines
2.5 KiB
Ruby
module SimplyBased
|
|
module ClassMethods
|
|
module Base
|
|
def get_class_from_name(klass_name)
|
|
# Try to find class from property definition
|
|
if property = _find_property(klass_name) and property.respond_to?(:options) and property.options[:class_name].present?
|
|
property.options[:class_name].constantize
|
|
else # Fall back to name guessing
|
|
base = klass_name.to_s.gsub('__','/')
|
|
base = base.classify unless base[0,1] =~ /[A-Z]/
|
|
base.constantize
|
|
end
|
|
end
|
|
|
|
def foreign_key
|
|
name.underscore.gsub('/','__').gsub('::','__') + "_id"
|
|
end
|
|
|
|
def foreign_property
|
|
name.underscore.gsub('/','__').gsub('::','__')
|
|
end
|
|
|
|
def attr_protected(*args)
|
|
@_protected_attributes ||= []
|
|
@_protected_attributes += args.to_a
|
|
end
|
|
|
|
def attr_accessible(*args)
|
|
@_accessible_attributes ||= []
|
|
@_accessible_attributes += args.to_a
|
|
end
|
|
|
|
def _find_property(name)
|
|
properties.find{|property| property.name == name}
|
|
end
|
|
|
|
# Namespace aware method of creating proper class names
|
|
def find_association_class_name(association_name)
|
|
(name.split('::')[0..-2] + [association_name.to_s.singularize.camelize]).join('::')
|
|
end
|
|
|
|
# More compatibility with active record plugins
|
|
def primary_key
|
|
'id'
|
|
end
|
|
|
|
def view(view_name, options)
|
|
# SimplyBased serves associations and lookups with N1QL, not CouchDB
|
|
# JavaScript views. Hand-written map/reduce registrations
|
|
# (:map_function / :reduce_function / :type => :custom|:raw) are no-ops —
|
|
# the association layer queries the Store directly. Structured model
|
|
# views (all_documents, find_by_*; no :map_function) still register.
|
|
return if options[:map_function] || options[:reduce_function] ||
|
|
[:custom, :raw].include?(options[:type])
|
|
super(view_name, options)
|
|
end
|
|
|
|
# Fix for paperclip > 3.5.2
|
|
def after_commit(*); end
|
|
|
|
# Get documents by ids and bulk update attributes
|
|
def bulk_update(ids, pairs)
|
|
# Bulk load documents
|
|
# Map to doc
|
|
# Filter out errors, or none founds (compact)
|
|
# Select the Couch objects
|
|
docs = database.bulk_load(ids).select{|d| d.is_a?(SimplyBased::Model)}
|
|
for doc in docs
|
|
pairs.each_pair do |k, v|
|
|
doc.send("#{k}=", v) if doc.respond_to?("#{k}=")
|
|
end
|
|
doc.save # Should become a bulk update in the future
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|