Permalink
Browse files

Allow mixing of protected and accessible properties.

Any unspecified properties are now assumed to be protected by default
  • Loading branch information...
1 parent bf22222 commit aac6b80d2671c8b2767a1bb7d550d49ed799d295 @will will committed Aug 11, 2010
Showing with 66 additions and 54 deletions.
  1. +3 −0 .gitignore
  2. +21 −20 history.txt
  3. +22 −21 lib/couchrest/model/attribute_protection.rb
  4. +20 −13 spec/couchrest/attribute_protection_spec.rb
View
@@ -2,3 +2,6 @@
html/*
pkg
*.swp
+Gemfile*
+.rvmrc
+.bundle
View
@@ -4,12 +4,13 @@
* Minor enhancements
* Raise error on adding objects to "collection_of" without an id
+ * Allow mixing of protected and accessible properties. Any unspecified properties are now assumed to be protected by default
== CouchRest Model 1.0.0.beta7
* Major enhancements
* Renamed ExtendedDocument to CouchRest::Model
- * Added initial support for simple belongs_to associations
+ * Added initial support for simple belongs_to associations
* Added support for basic collection_of association (unique to document databases!)
* Moved Validation to ActiveModel
* Moved Callbacks to ActiveModel
@@ -74,7 +75,7 @@
* Adds support for continuous replication (sauy7)
* Automatic Type Casting (Alexander Uvarov, Sam Lown, Tim Heighes, Will Leinweber)
* Added a search method to CouchRest:Database to search the documents in a given database. (Dave Farkas, Arnaud Berthomier, John Wood)
-
+
* Minor enhancements
* Provide a description of the timeout error (John Wood)
@@ -103,9 +104,9 @@
* Adds attribute protection to properties. (Will Leinweber)
* Improved CouchRest::Database#save_doc, added "batch" mode to significantly speed up saves at cost of lower durability gurantees. (Igal Koshevoy)
* Added CouchRest::Database#bulk_save_doc and #batch_save_doc as human-friendlier wrappers around #save_doc. (Igal Koshevoy)
-
-* Minor enhancements
-
+
+* Minor enhancements
+
* Fix content_type handling for attachments
* Fixed a bug in the pagination code that caused it to paginate over records outside of the scope of the view parameters.(John Wood)
* Removed amount_pages calculation for the pagination collection, since it cannot be reliably calculated without a view.(John Wood)
@@ -124,9 +125,9 @@
* Major enhancements
* Added a new Rack logger middleware letting you log/save requests/queries (Matt Aimonetti)
-
-* Minor enhancements
-
+
+* Minor enhancements
+
* Added #amount_pages to a paginated result array (Matt Aimonetti)
* Ruby 1.9.2 compatible (Matt Aimonetti)
* Added a property? method for property cast as :boolean (John Wood)
@@ -135,14 +136,14 @@
* Bug fix: made ExtendedDocument#all compatible with Couch 0.10 (tc)
== 0.32
-
+
* Major enhancements
* ExtendedDocument.get doesn't raise an exception anymore. If no documents are found nil is returned.
* ExtendedDocument.get! works the say #get used to work and will raise an exception if a document isn't found.
-
-* Minor enhancements
-
+
+* Minor enhancements
+
* Bug fix: Model.all(:keys => [1,2]) was not working (Matt Aimonetti)
* Added ValidationErrors#count in order to play nicely with Rails (Peter Wagenet)
* Bug fix: class proxy design doc refresh (Daniel Kirsh)
@@ -155,29 +156,29 @@
* Created an abstraction HTTP layer to support different http adapters (Matt Aimonetti)
* Added ExtendedDocument.create({}) and #create!({}) so you don't have to do Model.new.create (Matt Aimonetti)
-
+
* Minor enhancements
-
+
* Added an init.rb file for easy usage as a Rails plugin (Aaron Quint)
* Bug fix: pagination shouldn't die on empty results (Arnaud Berthomier)
* Optimized ExtendedDocument.count to run about 3x faster (Matt Aimonetti)
* Added Float casting (Ryan Felton & Matt Aimonetti)
== 0.30
-
+
* Major enhancements
-
+
* Added support for pagination (John Wood)
* Improved performance when initializing documents with timestamps (Matt Aimonetti)
-
+
* Minor enhancements
-
+
* Extended the API to retrieve an attachment URI (Matt Aimonetti)
* Bug fix: default value should be able to be set as false (Alexander Uvarov)
* Bug fix: validates_is_numeric should be able to properly validate a Float instance (Rob Kaufman)
* Bug fix: fixed the Timeout implementation (Seth Falcon)
-
-
+
+
---
Unfortunately, before 0.30 we did not keep a track of the modifications made to CouchRest.
@@ -1,25 +1,31 @@
module CouchRest
module Model
module AttributeProtection
- # Attribute protection from mass assignment to CouchRest properties
- #
+ # Attribute protection from mass assignment to CouchRest::Model properties
+ #
# Protected methods will be removed from
- # * new
+ # * new
# * update_attributes
# * upate_attributes_without_saving
# * attributes=
- #
+ #
# There are two modes of protection
- # 1) Declare accessible poperties, assume all the rest are protected
- # property :name, :accessible => true
- # property :admin # this will be automatically protected
+ # 1) Declare accessible poperties, and assume all unspecified properties are protected
+ # property :name, :accessible => true
+ # property :admin # this will be automatically protected
#
- # 2) Declare protected properties, assume all the rest are accessible
- # property :name # this will not be protected
+ # 2) Declare protected properties, and assume all unspecified properties are accessible
+ # property :name # this will not be protected
# property :admin, :protected => true
#
- # Note: you cannot set both flags in a single class
-
+ # 3) Mix and match, and assume all unspecified properties are protected.
+ # property :name, :accessible => true
+ # property :admin, :protected => true
+ # property :phone # this will be automatically protected
+ #
+ # Note: the timestamps! method protectes the created_at and updated_at properties
+
+
def self.included(base)
base.extend(ClassMethods)
end
@@ -56,18 +62,13 @@ def remove_protected_attributes(attributes)
private
def properties_to_remove_from_mass_assignment
- has_protected = !protected_properties.empty?
- has_accessible = !accessible_properties.empty?
+ to_remove = protected_properties
- if !has_protected && !has_accessible
- []
- elsif has_protected && !has_accessible
- protected_properties
- elsif has_accessible && !has_protected
- properties.reject { |prop| prop.options[:accessible] }
- else
- raise "Set either :accessible or :protected for #{self.class}, but not both"
+ unless accessible_properties.empty?
+ to_remove += properties.reject { |prop| prop.options[:accessible] }
end
+
+ to_remove
end
end
end
@@ -23,13 +23,13 @@ class NoProtection < CouchRest::Model::Base
user.name.should == "will"
user.phone.should == "555-5555"
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"
@@ -50,7 +50,7 @@ class WithAccessible < CouchRest::Model::Base
end
it "should protect non-accessible properties set through new" do
- user = WithAccessible.new(:name => "will", :admin => true)
+ user = WithAccessible.new(:name => "will", :admin => true)
user.name.should == "will"
user.admin.should == false
@@ -79,7 +79,7 @@ class WithProtected < CouchRest::Model::Base
end
it "should protect non-accessible properties set through new" do
- user = WithProtected.new(:name => "will", :admin => true)
+ user = WithProtected.new(:name => "will", :admin => true)
user.name.should == "will"
user.admin.should == false
@@ -94,15 +94,22 @@ class WithProtected < CouchRest::Model::Base
end
end
- describe "protected flag" do
- class WithBoth < CouchRest::Model::Base
+ describe "Model Base", "mixing protected and accessible flags" do
+ class WithBothAndUnspecified < CouchRest::Model::Base
use_database TEST_SERVER.default_database
property :name, :accessible => true
property :admin, :default => false, :protected => true
+ property :phone, :default => 'unset phone number'
end
- it "should raise an error when both are set" do
- lambda { WithBoth.new }.should raise_error
+ it { expect { WithBothAndUnspecified.new }.to_not raise_error }
+
+ it 'should assume that any unspecified property is protected by default' do
+ user = WithBothAndUnspecified.new(:name => 'will', :admin => true, :phone => '555-1234')
+
+ user.name.should == 'will'
+ user.admin.should == false
+ user.phone.should == 'unset phone number'
end
end
@@ -113,7 +120,7 @@ class WithProtected < CouchRest::Model::Base
property :admin, :default => false, :protected => true
view_by :name
end
-
+
before(:each) do
@user = WithProtected.new
@user.name = "will"
@@ -128,26 +135,26 @@ def verify_attrs(user)
it "Base#get should not strip protected attributes" do
reloaded = WithProtected.get( @user.id )
- verify_attrs reloaded
+ verify_attrs reloaded
end
it "Base#get! should not strip protected attributes" do
reloaded = WithProtected.get!( @user.id )
- verify_attrs reloaded
+ verify_attrs reloaded
end
it "Base#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
+ 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
+ verify_attrs reloaded
end
end
end

0 comments on commit aac6b80

Please sign in to comment.