BUGFIX: attribute protection
Fixes bug where documents recreated from the database were being stripped of their protected attributes when instantiated Signed-off-by: Marcos Tapajos <tapajos@Tapajos-MacBook.local>
This commit is contained in:
parent
5707d89290
commit
d41c7c96da
|
@ -183,7 +183,7 @@ module CouchRest
|
||||||
if @container_class.nil?
|
if @container_class.nil?
|
||||||
results
|
results
|
||||||
else
|
else
|
||||||
results['rows'].collect { |row| @container_class.new(row['doc']) } unless results['rows'].nil?
|
results['rows'].collect { |row| @container_class.create_from_database(row['doc']) } unless results['rows'].nil?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,9 @@ module CouchRest
|
||||||
# db<Database>:: optional option to pass a custom database to use
|
# db<Database>:: optional option to pass a custom database to use
|
||||||
def get(id, db = database)
|
def get(id, db = database)
|
||||||
begin
|
begin
|
||||||
doc = db.get id
|
get!(id, db)
|
||||||
rescue
|
rescue
|
||||||
nil
|
nil
|
||||||
else
|
|
||||||
new(doc)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -72,7 +70,7 @@ module CouchRest
|
||||||
# db<Database>:: optional option to pass a custom database to use
|
# db<Database>:: optional option to pass a custom database to use
|
||||||
def get!(id, db = database)
|
def get!(id, db = database)
|
||||||
doc = db.get id
|
doc = db.get id
|
||||||
new(doc)
|
create_from_database(doc)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -137,13 +137,13 @@ module CouchRest
|
||||||
collection_proxy_for(design_doc, name, opts.merge({:include_docs => true}))
|
collection_proxy_for(design_doc, name, opts.merge({:include_docs => true}))
|
||||||
else
|
else
|
||||||
view = fetch_view db, name, opts.merge({:include_docs => true}), &block
|
view = fetch_view db, name, opts.merge({:include_docs => true}), &block
|
||||||
view['rows'].collect{|r|new(r['doc'])} if view['rows']
|
view['rows'].collect{|r|create_from_database(r['doc'])} if view['rows']
|
||||||
end
|
end
|
||||||
rescue
|
rescue
|
||||||
# fallback for old versions of couchdb that don't
|
# fallback for old versions of couchdb that don't
|
||||||
# have include_docs support
|
# have include_docs support
|
||||||
view = fetch_view(db, name, opts, &block)
|
view = fetch_view(db, name, opts, &block)
|
||||||
view['rows'].collect{|r|new(db.get(r['id']))} if view['rows']
|
view['rows'].collect{|r|create_from_database(db.get(r['id']))} if view['rows']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,10 +39,19 @@ module CouchRest
|
||||||
define_callbacks :update, "result == :halt"
|
define_callbacks :update, "result == :halt"
|
||||||
define_callbacks :destroy, "result == :halt"
|
define_callbacks :destroy, "result == :halt"
|
||||||
|
|
||||||
def initialize(passed_keys={})
|
# Creates a new instance, bypassing attribute protection
|
||||||
|
#
|
||||||
|
# ==== Returns
|
||||||
|
# a document instance
|
||||||
|
def self.create_from_database(passed_keys={})
|
||||||
|
new(passed_keys, :directly_set_attributes => true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(passed_keys={}, options={})
|
||||||
apply_defaults # defined in CouchRest::Mixins::Properties
|
apply_defaults # defined in CouchRest::Mixins::Properties
|
||||||
set_attributes(passed_keys) unless passed_keys.nil?
|
remove_protected_attributes(passed_keys) unless options[:directly_set_attributes]
|
||||||
super
|
directly_set_attributes(passed_keys) unless passed_keys.nil?
|
||||||
|
super(passed_keys)
|
||||||
cast_keys # defined in CouchRest::Mixins::Properties
|
cast_keys # defined in CouchRest::Mixins::Properties
|
||||||
unless self['_id'] && self['_rev']
|
unless self['_id'] && self['_rev']
|
||||||
self['couchrest-type'] = self.class.to_s
|
self['couchrest-type'] = self.class.to_s
|
||||||
|
@ -282,13 +291,17 @@ module CouchRest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def directly_set_attributes(hash)
|
||||||
|
hash.each do |attribute_name, attribute_value|
|
||||||
|
if self.respond_to?("#{attribute_name}=")
|
||||||
|
self.send("#{attribute_name}=", hash.delete(attribute_name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def set_attributes(hash)
|
def set_attributes(hash)
|
||||||
attrs = remove_protected_attributes(hash)
|
attrs = remove_protected_attributes(hash)
|
||||||
attrs.each do |attribute_name, attribute_value|
|
directly_set_attributes(attrs)
|
||||||
if self.respond_to?("#{attribute_name}=")
|
|
||||||
self.send("#{attribute_name}=", attrs.delete(attribute_name))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,17 @@ describe "ExtendedDocument", "no declarations" do
|
||||||
user.name.should == "will"
|
user.name.should == "will"
|
||||||
user.phone.should == "555-5555"
|
user.phone.should == "555-5555"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should recreate from the database properly" do
|
||||||
|
user = NoProtection.new
|
||||||
|
user.name = "will"
|
||||||
|
user.phone = "555-5555"
|
||||||
|
user.save!
|
||||||
|
|
||||||
|
user = NoProtection.get(user.id)
|
||||||
|
user.name.should == "will"
|
||||||
|
user.phone.should == "555-5555"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "ExtendedDocument", "accessible flag" do
|
describe "ExtendedDocument", "accessible flag" do
|
||||||
|
@ -92,3 +103,48 @@ describe "ExtendedDocument", "protected flag" do
|
||||||
lambda { WithBoth.new }.should raise_error
|
lambda { WithBoth.new }.should raise_error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "ExtendedDocument", "from database" do
|
||||||
|
class WithProtected < CouchRest::ExtendedDocument
|
||||||
|
use_database TEST_SERVER.default_database
|
||||||
|
property :name
|
||||||
|
property :admin, :default => false, :protected => true
|
||||||
|
view_by :name
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
@user = WithProtected.new
|
||||||
|
@user.name = "will"
|
||||||
|
@user.admin = true
|
||||||
|
@user.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
def verify_attrs(user)
|
||||||
|
user.name.should == "will"
|
||||||
|
user.admin.should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ExtendedDocument#get should not strip protected attributes" do
|
||||||
|
reloaded = WithProtected.get( @user.id )
|
||||||
|
verify_attrs reloaded
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ExtendedDocument#get! should not strip protected attributes" do
|
||||||
|
reloaded = WithProtected.get!( @user.id )
|
||||||
|
verify_attrs reloaded
|
||||||
|
end
|
||||||
|
|
||||||
|
it "ExtendedDocument#all should not strip protected attributes" do
|
||||||
|
# all creates a CollectionProxy
|
||||||
|
docs = WithProtected.all(:key => @user.id)
|
||||||
|
docs.size.should == 1
|
||||||
|
reloaded = docs.first
|
||||||
|
verify_attrs reloaded
|
||||||
|
end
|
||||||
|
|
||||||
|
it "views should not strip protected attributes" do
|
||||||
|
docs = WithProtected.by_name(:startkey => "will", :endkey => "will")
|
||||||
|
reloaded = docs.first
|
||||||
|
verify_attrs reloaded
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in a new issue