diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..9012037 --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008 Nando Vieira + +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. \ No newline at end of file diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..0667a5f --- /dev/null +++ b/README.markdown @@ -0,0 +1,33 @@ +marshaled_attributes +==================== + +A simple plugin for saving marshaled objects using ActiveRecord. + +Instalation +----------- + +Install the plugin with `script/plugin install git://github.com/fnando/marshaled_attributes.git` + +Usage +===== + +Considering the following schema: + + create_table :pages do |t| + t.string :name + t.text :body + t.binary :meta + end + +1) Add the method call `marshaled_attributes` to your model. + + class Page < ActiveRecord::Base + marshaled_attributes :meta + end + + @page = Page.new # => do not mass-assign the marshaled attributes. + @page.meta = {:last_comment_id => 100} + +IMPORTANT: Remember NOT to mass-assign the attributes you want to be marshaled. + +Copyright (c) 2008 Nando Vieira, released under the MIT license \ No newline at end of file diff --git a/init.rb b/init.rb new file mode 100644 index 0000000..ff89b74 --- /dev/null +++ b/init.rb @@ -0,0 +1,9 @@ +require "marshaled_attributes" + +# ActiveRecord only calls after_initialize callbacks only if is +# explicitly defined in a class. +class ActiveRecord::Base # :nodoc: + def after_initialize; end +end + +ActiveRecord::Base.send(:include, SimplesIdeias::Marshaling) \ No newline at end of file diff --git a/lib/marshaled_attributes.rb b/lib/marshaled_attributes.rb new file mode 100644 index 0000000..f87d761 --- /dev/null +++ b/lib/marshaled_attributes.rb @@ -0,0 +1,43 @@ +module SimplesIdeias + module Marshaling + def self.included(base) + base.extend ClassMethods + + class << base + attr_accessor :marshaled_attributes_options + end + end + + module ClassMethods + # marshaled_attributes :title, :settings + def marshaled_attributes(*attrs) + self.marshaled_attributes_options = { + :attributes => attrs + } + + include SimplesIdeias::Marshaling::InstanceMethods + + after_initialize :add_marshaled_attributes! + end + end + + module InstanceMethods + private + def add_marshaled_attributes! + evaluate = self.class.marshaled_attributes_options[:attributes].inject("") do |memo, name| + memo + %( + def #{name} + Marshal.load read_attribute(:#{name}) unless read_attribute(:#{name}).blank? + end + + def #{name}=(value) + write_attribute(:#{name}, Marshal.dump(value)) + end + ) + end + + self.class.class_eval(evaluate) + end + end + end +end \ No newline at end of file diff --git a/specs/marshaled_attributes_spec.rb b/specs/marshaled_attributes_spec.rb new file mode 100644 index 0000000..57f6ebe --- /dev/null +++ b/specs/marshaled_attributes_spec.rb @@ -0,0 +1,27 @@ +require File.dirname(__FILE__) + "/spec_helper" + +# unset models used for testing purposes +Object.unset_class('Beer') + +class Beer < ActiveRecord::Base + marshaled_attributes :meta +end + +describe "marshaled_attributes" do + before(:each) do + @beer = Beer.new(:name => 'Duffys') + @attrs = {:taste => 'great!'} + end + + it "should dump value" do + Marshal.should_receive(:dump).with(@attrs).and_return('dumped') + @beer.should_receive(:write_attribute).with(:meta, 'dumped') + @beer.meta = @attrs + end + + it "should load dumped value" do + Marshal.should_receive(:load).with(@attrs).and_return('loaded') + @beer.should_receive(:read_attribute).any_number_of_times.with(:meta).and_return(@attrs) + @beer.meta.should == 'loaded' + end +end \ No newline at end of file diff --git a/specs/schema.rb b/specs/schema.rb new file mode 100644 index 0000000..788eeb0 --- /dev/null +++ b/specs/schema.rb @@ -0,0 +1,6 @@ +ActiveRecord::Schema.define(:version => 0) do + create_table :beers do |t| + t.string :name + t.binary :meta + end +end \ No newline at end of file diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb new file mode 100644 index 0000000..86f47e7 --- /dev/null +++ b/specs/spec_helper.rb @@ -0,0 +1,27 @@ +ENV["RAILS_ENV"] = "test" + +require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment") +require "spec" +require "spec/rails" +require "ruby-debug" + +ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ":memory:"}} +ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations["test"]) + +load(File.dirname(__FILE__) + '/schema.rb') + +Spec::Runner.configure do |config| +end + +class Object + def self.unset_class(*args) + class_eval do + args.each do |klass| + eval(klass) rescue nil + remove_const(klass) if const_defined?(klass) + end + end + end +end + +alias :doing :lambda \ No newline at end of file