Repository: JackDanger/immutable_attributes Branch: master Commit: 2244781cd954 Files: 12 Total size: 7.6 KB Directory structure: gitextract_g04nhw_n/ ├── .document ├── .gitignore ├── LICENSE ├── README ├── Rakefile ├── VERSION ├── immutable_attributes.gemspec ├── init.rb ├── install.rb ├── lib/ │ └── immutable_attributes.rb ├── rails/ │ └── init.rb └── test/ └── immutable_attributes_test.rb ================================================ FILE CONTENTS ================================================ ================================================ FILE: .document ================================================ README Rakefile init.rb install.rb lib/*.rb rails/init.rb test/*.rb ================================================ FILE: .gitignore ================================================ *~ *.swp ================================================ FILE: LICENSE ================================================ Copyright (c) 2011 Jack Danger Canty Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README ================================================ ImmutableAttributes =================== When you want to prevent certain attributes from being changed once set you can declare them as immutable: class MyModel < ActiveRecord::Base attr_immutable :permalink, :param_identifier end When MyModel.find(:first).permalink = 'anything' is called it will raise an ImmutableAttributeError MyModel.new.permalink = 'works!' will properly set the value because the record is unsaved. If you'd only like this to happen for certain conditions, and want to handle other attribute-writers, too (like update_attribute), you can use the validation. validates_immutable :permalink Configuration options for the validation: * :message - A customer error message (default is: "can't be changed") * :if - Specifies a method, proc, or string to call to determine if the validation should occure (e.g., :if => :allow_validation or :if => Proc.new{|user| user.signup_step > 2}. The method, proc or string should return or evaluate to a true or false value. * :unless - Specifies a method, proc, or string to call to determine if the validation should not occure (e.g., :unless => :skip_validation or :unless => Proc.new{|user| user.signup_step <= 2}. The method, proc or string should return or evaluate to a true or false value. Created by Jack Danger Canty @ http://6brand.com Released under the same licence as Rails (MIT) ================================================ FILE: Rakefile ================================================ require 'rubygems' require 'rake' begin require 'jeweler' Jeweler::Tasks.new do |gem| gem.name = "immutable_attributes" gem.summary = %Q{Selected attributes are permanent once a record is created} gem.description = %Q{Allows specified attributes to be freely overwritten _until_ the record is saved for the first time} gem.email = "gemcutter@jackcanty.com" gem.homepage = "http://github.com/JackDanger/immutable_attributes" gem.authors = ["Jack Danger Canty", "Terry Heath", "Nicholas Mertaugh"] end rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" end require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.libs << '.' test.pattern = 'test/*_test.rb' test.verbose = true end task :default => :test ================================================ FILE: VERSION ================================================ 1.2.0 ================================================ FILE: immutable_attributes.gemspec ================================================ # Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = %q{immutable_attributes} s.version = "1.2.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Jack Danger Canty", "Terry Heath", "Nicholas Mertaugh"] s.date = %q{2011-07-18} s.description = %q{Allows specified attributes to be freely overwritten _until_ the record is saved for the first time} s.email = %q{gemcutter@jackcanty.com} s.extra_rdoc_files = [ "LICENSE", "README" ] s.files = [ ".document", "LICENSE", "README", "Rakefile", "VERSION", "immutable_attributes.gemspec", "init.rb", "install.rb", "lib/immutable_attributes.rb", "rails/init.rb", "test/immutable_attributes_test.rb" ] s.homepage = %q{http://github.com/JackDanger/immutable_attributes} s.require_paths = ["lib"] s.rubygems_version = %q{1.4.2} s.summary = %q{Selected attributes are permanent once a record is created} if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then else end else end end ================================================ FILE: init.rb ================================================ # Include hook code here require 'immutable_attributes' ================================================ FILE: install.rb ================================================ puts IO.read(File.join(File.dirname(__FILE__), 'README')) ================================================ FILE: lib/immutable_attributes.rb ================================================ begin require 'activerecord' rescue LoadError require 'active_record' end module ImmutableErrors class ImmutableAttributeError < ActiveRecord::ActiveRecordError end end module ImmutableAttributes VERSION = "1.0.3" def attr_immutable(*args) class_eval do args.each do |attr| define_method("#{attr}=") do |value| new_record? || read_attribute(attr).nil? ? write_attribute(attr, value) : raise(ActiveRecord::ImmutableAttributeError, "#{attr} is immutable!") end end # handle ActiveRecord::Base#[]= define_method :[]= do |attr, value| return write_attribute(attr, value) unless args.include?(attr.to_sym) send "#{attr}=", value end end end def validates_immutable(*attr_names) config = { :on => :update, :if => lambda {|x| true}, :message => "can't be changed" } config.update(attr_names.extract_options!) @immutables = attr_names attr_names.each do |attr| class_eval do define_method("original_#{attr}") do instance_variable_get("@original_#{attr}") end end end class_eval do def self.immutables @immutables end def after_initialize; end; def setup_originals self.class.immutables.each do |attr_name| next unless attribute_names.include? attr_name instance_variable_set("@original_#{attr_name}", send(attr_name.to_s)) end end after_initialize :setup_originals end validates_each(attr_names, config) do |record, attr_name, value| next if record.send("original_#{attr_name.to_s}").nil? record.errors.add(attr_name, config[:message]) if record.send("original_#{attr_name.to_s}") != record.send(attr_name.to_s) end end end ActiveRecord.send :include, ImmutableErrors ActiveRecord::Base.extend ImmutableAttributes ================================================ FILE: rails/init.rb ================================================ # Include hook code here require 'immutable_attributes' ================================================ FILE: test/immutable_attributes_test.rb ================================================ require 'test/unit' require 'rubygems' require 'activerecord' require File.join(File.dirname(__FILE__), '..', 'lib', 'immutable_attributes') ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database => ":memory:" ) ActiveRecord::Schema.define do create_table :records do |table| table.column :name, :string table.column :body, :string end end class Record < ActiveRecord::Base attr_immutable :name end class ImmutableAttributesTest < Test::Unit::TestCase def test_immutable_attribute_can_be_set assert Record.new(:name => 'record name') end def test_immutable_attribute_cannot_be_changed_via_mass_setter record = Record.create!(:name => 'record name') assert_raises(ActiveRecord::ImmutableAttributeError) { record.update_attributes(:name => 'new name') } end def test_immutable_attribute_cannot_be_changed_via_bracket_setter record = Record.create!(:name => 'record name') assert_raises(ActiveRecord::ImmutableAttributeError) { record[:name] = 'new name' } end end