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>
218 lines
6.6 KiB
Ruby
218 lines
6.6 KiB
Ruby
require 'spec_helper'
|
|
|
|
describe "BelongsTo" do
|
|
context "with associations" do
|
|
context "with belongs_to" do
|
|
it "generate a view for the association" do
|
|
#Post.respond_to?(:association_post_belongs_to_user).should be_present
|
|
Post.should respond_to :association_post_belongs_to_user
|
|
end
|
|
|
|
it "raise an error if another property with the same name already exists" do
|
|
expect {
|
|
class ::DoubleBelongsToUser
|
|
include SimplyBased::Model
|
|
property :user
|
|
belongs_to :user
|
|
end
|
|
}.to raise_error RuntimeError
|
|
end
|
|
|
|
it "add the foreign key id to the referencing object" do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.create(:user => user)
|
|
|
|
post = Post.find(post.id)
|
|
post.user_id.should eq user.id
|
|
end
|
|
|
|
it "create a property for the foreign key attribute" do
|
|
Post.properties.any?{|p| p.name.to_s == 'user_id'}.should be true
|
|
end
|
|
|
|
it "notice a change to the foreign key attribute in dirty checks" do
|
|
user = User.create!(:title => 'Prof')
|
|
post = Post.create!
|
|
post.user = user
|
|
post.should be_user_id_changed
|
|
end
|
|
|
|
it "set also the foreign key id to nil if setting the referencing object to nil" do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.create(:user => user)
|
|
post.user = nil
|
|
post.save!
|
|
post.reload.user.should be nil
|
|
post.reload.user_id.should be nil
|
|
end
|
|
|
|
it "fetch the object from the database when requested through the getter" do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.create(:user => user)
|
|
|
|
post = Post.find(post.id)
|
|
post.user.should eq user
|
|
end
|
|
|
|
it "mark the referencing object as dirty" do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.create
|
|
post.user = user
|
|
post.should be_dirty
|
|
end
|
|
|
|
it "allow assigning a different object and store the id accordingly" do
|
|
user = User.create(:title => "Mr.")
|
|
user2 = User.create(:title => "Mrs.")
|
|
post = Post.create(:user => user)
|
|
post.user = user2
|
|
post.save
|
|
|
|
post = Post.find(post.id)
|
|
post.user.id.should eq user2.id
|
|
end
|
|
|
|
it "check the class and raise an error if not matching in belongs_to setter" do
|
|
post = Post.create
|
|
expect{ post.user = 'foo' }.to raise_error(ArgumentError, 'expected User got String')
|
|
end
|
|
|
|
it 'not query for the object twice in getter' do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.create(:user => user)
|
|
post = Post.find(post.id)
|
|
expect( User ).to receive(:find).and_return "user"
|
|
post.user
|
|
expect( User ).not_to receive(:find)
|
|
post.user
|
|
end
|
|
|
|
it 'use cache in getter' do
|
|
post = Post.create
|
|
post.instance_variable_set("@user", 'foo')
|
|
post.user.should eq 'foo'
|
|
end
|
|
|
|
it "ignore the cache if force_reload is given as an option" do
|
|
user = User.create(:name => 'Dude', :title => 'Mr.')
|
|
post = Post.create(:user => user)
|
|
post.reload
|
|
post.instance_variable_set("@user", 'foo')
|
|
post.user(:force_reload => true).should_not eq 'foo'
|
|
end
|
|
|
|
it 'set cache in setter' do
|
|
post = Post.create
|
|
user = User.create :title => 'Mr.'
|
|
post.instance_variable_get("@user").should be nil
|
|
post.user = user
|
|
post.instance_variable_get("@user").should eq user
|
|
end
|
|
|
|
it "not hit the database when the id column is empty" do
|
|
expect( User ).not_to receive(:find)
|
|
post = Post.create
|
|
post.user
|
|
end
|
|
|
|
it "know when the associated object changed" do
|
|
post = Post.create(:user => User.create(:title => "Mr."))
|
|
user2 = User.create(:title => "Mr.")
|
|
post.user = user2
|
|
post.should be_user_id_changed
|
|
end
|
|
|
|
it "not be changed when an association has not changed" do
|
|
post = Post.create(:user => User.create(:title => "Mr."))
|
|
post.should_not be_user_id_changed
|
|
end
|
|
|
|
it "not be changed when assigned the same object" do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.create(:user => user)
|
|
post.user = user
|
|
post.should_not be_user_changed
|
|
end
|
|
|
|
it "not be changed after saving" do
|
|
user = User.create(:title => "Mr.")
|
|
post = Post.new
|
|
post.user = user
|
|
post.should be_user_id_changed
|
|
post.save!
|
|
post.should_not be_user_id_changed
|
|
end
|
|
|
|
it "have a proper _was value" do
|
|
user = User.create(:title => "Mr.")
|
|
user2 = User.create(:title => "Mrs.")
|
|
post = Post.new
|
|
|
|
post.save
|
|
post.user.should be nil
|
|
post.user_id.should be nil
|
|
|
|
post.user = user
|
|
#post.user_was.should be nil
|
|
post.user_id_was.should be nil
|
|
|
|
post.save
|
|
|
|
post.user = user2
|
|
#post.user_was.should eq user
|
|
post.user_id_was.should eq user.id
|
|
end
|
|
|
|
it "set the parent object on has_many association" do
|
|
# Copy from has_many, but belongs here as well
|
|
expect( User ).not_to receive(:find)
|
|
user = User.create(:title => "Mr.")
|
|
3.times {
|
|
post = Post.new
|
|
post.user = user
|
|
post.save!
|
|
}
|
|
post = user.posts.first
|
|
user.posts.first.user.should eq user
|
|
end
|
|
|
|
it "set the parent object on has_one association" do
|
|
# Taken from has_one, but belongs here as well
|
|
expect( Instance ).not_to receive(:find)
|
|
instance = Instance.create
|
|
identity = Identity.create(:instance => instance)
|
|
|
|
instance.identity.instance.should eq instance
|
|
end
|
|
|
|
it "handle a foreign_key of '' as nil" do
|
|
post = Post.create
|
|
post.user_id = ''
|
|
|
|
post.user.should be nil
|
|
end
|
|
|
|
context "with aliased associations" do
|
|
it "allow different names for the same class" do
|
|
editor = User.create(:name => 'Editor', :title => 'Dr.')
|
|
author = User.create(:name => 'author', :title => 'Dr.')
|
|
editor.id.should_not be nil
|
|
author.id.should_not be nil
|
|
|
|
doc = Document.create(:editor => editor, :author => author)
|
|
doc.save!
|
|
doc.editor_id.should eq editor.id
|
|
doc.author_id.should eq author.id
|
|
doc = Document.find(doc.id)
|
|
doc.editor.should_not be nil
|
|
doc.author.should_not be nil
|
|
doc.editor.id.should eq editor.id
|
|
doc.author.id.should eq author.id
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
end
|