accessorize 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jeff Rafter
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,72 @@
1
+ = Accessorize
2
+
3
+ Log all data access for your ActiveRecord models
4
+
5
+ == How does it work?
6
+
7
+ Sometimes you need to keep rigid logs of who created, updated and even accessed
8
+ the data in your database. Accessorize simplifies the process by allowing you to
9
+ register observers for your models declaratively in one place. Each ovbserver
10
+ will save access events to a single table "accessors" which stores the user that
11
+ is accessing the record, the type of access (create, update, view, destroy) and
12
+ the id of the record that was accessed.
13
+
14
+ == Performance
15
+
16
+ Because accessorize record view level access events it can become very slow. You
17
+ should only enable it for heavily controlled models. For example, if you have an
18
+ index page that lists all patients in your database in a table, a new access
19
+ event is created for every row. Think of the children.
20
+
21
+ == Make it work
22
+
23
+ First you need to install the gem (hosted on Gemcutter):
24
+
25
+ sudo gem install accessorize
26
+
27
+ Then you need to run the generator in your project:
28
+
29
+ /my/cool/rails/app $ accessorize
30
+
31
+ Then you need to edit the accessorize.rb file in config/initializers. You can
32
+ control the automatic accessor and meta methods:
33
+
34
+ Accessorize.configure do |config|
35
+ config.accessor = :current_user # default
36
+ config.meta = :current_meta # default
37
+ end
38
+
39
+ Accessorize uses these settings when your model is accessed from a controller.
40
+ When logging the "accessor_id", it will by default grab the id current_user from
41
+ the application controller. You can change which method is called and replace it
42
+ with something custom.
43
+
44
+ The meta information has no specific use. It could be used to store the users
45
+ IP address, the current action or route, or really anything you like. Again,
46
+ accessorize will by default try to access the current_meta method on the
47
+ application controller. You can define this method or point it to something
48
+ else. If the method does not exist, the meta attribute will be nil for the
49
+ record.
50
+
51
+ If you are not saving from a controller you can simply set these values to
52
+ whatever you like:
53
+
54
+ Accessorize::Extension.accessor = 101
55
+ SomeAccessorizedModel.first
56
+ Accessorize::Accessor.last.accessor
57
+ # => 101
58
+
59
+
60
+ == Note on Patches/Pull Requests
61
+
62
+ * Fork the project.
63
+ * Make your feature addition or bug fix.
64
+ * Add tests for it. This is important so I don't break it in a
65
+ future version unintentionally.
66
+ * Commit, do not mess with rakefile, version, or history.
67
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
68
+ * Send me a pull request. Bonus points for topic branches.
69
+
70
+ == Copyright
71
+
72
+ Copyright (c) 2010 Jeff Rafter. See LICENSE for details.
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "accessorize"
8
+ gem.summary = %Q{Log all data access for your ActiveRecord models}
9
+ gem.description = %Q{Sometimes you need to keep rigid logs of who created, updated and even accessed the data in your database. Accessorize simplifies the process.}
10
+ gem.email = "jeff@socialrange.org"
11
+ gem.homepage = "http://github.com/jeffrafter/accessorize"
12
+ gem.authors = ["Jeff Rafter"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.files = FileList["[A-Z]*", "{generators,lib,rails}/**/*", "test/accessorize_test.rb"]
15
+ gem.test_files = FileList["test/accessorize_test.rb"]
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test => ["generator:cleanup", "generator:accessorize"]) do |task|
25
+ task.libs << "lib" << "test" << "test/rails/test"
26
+ task.pattern = "test/**/*_test.rb"
27
+ task.verbose = true
28
+ end
29
+
30
+ namespace :test do
31
+ Rake::TestTask.new(:database => ["generator:cleanup", "generator:database", "generator:accessorize"]) do |task|
32
+ task.libs << "lib" << "test"
33
+ task.pattern = "test/**/*_test.rb"
34
+ task.verbose = true
35
+ end
36
+ end
37
+
38
+ begin
39
+ require 'rcov/rcovtask'
40
+ Rcov::RcovTask.new do |test|
41
+ test.libs << 'test'
42
+ test.pattern = 'test/**/test_*.rb'
43
+ test.verbose = true
44
+ end
45
+ rescue LoadError
46
+ task :rcov do
47
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
48
+ end
49
+ end
50
+
51
+ generators = %w(accessorize)
52
+
53
+ namespace :generator do
54
+ desc "Cleans up the test app before running the generator"
55
+ task :cleanup do
56
+ FileUtils.rm_rf("test/rails")
57
+ system "cd test && rails rails"
58
+
59
+ # I don't like testing performance!
60
+ FileUtils.rm_rf("test/rails/test/performance")
61
+
62
+ system "echo \"\" >> test/rails/config/environments/test.rb"
63
+ system "echo \"config.gem 'thoughtbot-shoulda', :lib => 'shoulda'\" >> test/rails/config/environments/test.rb"
64
+ system "echo \"config.gem 'thoughtbot-factory_girl', :lib => 'factory_girl'\" >> test/rails/config/environments/test.rb"
65
+
66
+ # Make a thing
67
+ system "cd test/rails && ./script/generate scaffold thing name:string mood:string"
68
+
69
+ FileUtils.mkdir_p("test/rails/vendor/plugins")
70
+ accessorize_root = File.expand_path(File.dirname(__FILE__))
71
+ system("ln -s #{accessorize_root} test/rails/vendor/plugins/accessorize")
72
+ end
73
+
74
+ desc "Prepares the application with an alternate database"
75
+ task :database do
76
+ puts "== Configuring the database =================================================="
77
+ system "cp config/database.yml.sample test/rails/config/database.yml"
78
+ system "cd test/rails && rake db:migrate:reset"
79
+ end
80
+
81
+ desc "Run the accessorize generator"
82
+ task :accessorize do
83
+ system "cd test/rails && ./script/generate accessorize && rake db:migrate db:test:prepare"
84
+ end
85
+
86
+ end
87
+
88
+ task :test => :check_dependencies
89
+
90
+ task :default => :test
91
+
92
+ require 'rake/rdoctask'
93
+ Rake::RDocTask.new do |rdoc|
94
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
95
+
96
+ rdoc.rdoc_dir = 'rdoc'
97
+ rdoc.title = "accessorize #{version}"
98
+ rdoc.rdoc_files.include('README*')
99
+ rdoc.rdoc_files.include('lib/**/*.rb')
100
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,9 @@
1
+ class AccessorizeGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', File.join('db', 'migrate'), :migration_file_name => 'create_accessors'
5
+ m.directory File.join('config', 'initializers')
6
+ m.template 'initializer.rb', File.join('config', 'initializers', 'accessorize.rb')
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ Accessorize.configure do |config|
2
+ # Specify the objects that you want to observe with accessorize
3
+ # config.observe :patients, :visits, :encounters
4
+ end
@@ -0,0 +1,25 @@
1
+ class CreateAccessors < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :accessors do |t|
4
+ t.integer :accessor_id
5
+ t.integer :reference_id
6
+ t.string :reference_type
7
+ t.string :event
8
+ t.string :tag
9
+ t.text :meta
10
+ t.timestamps
11
+ end
12
+
13
+ change_table :accessors do |t|
14
+ t.index [:reference_id, :reference_type]
15
+ t.index :accessor_id
16
+ t.index :event
17
+ t.index :tag
18
+ t.index :created_at
19
+ end
20
+ end
21
+
22
+ def self.down
23
+ drop_table :accessors
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ require 'accessorize/accessor'
2
+ require 'accessorize/base'
3
+ require 'accessorize/config'
4
+ require 'accessorize/extension'
5
+
6
+ module Accessorize
7
+ def self.configure
8
+ yield Accessorize::Config
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ module Accessorize
2
+ class Accessor < ActiveRecord::Base
3
+ end
4
+ end
@@ -0,0 +1,48 @@
1
+ module Accessorize
2
+ module Base
3
+ def self.included(base)
4
+ base.send :extend, ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def accessorize
9
+ send :include, InstanceMethods
10
+ has_many :accessors, :class_name => 'Accessorize::Accessor', :foreign_key => :reference_id, :conditions => {:reference_type => self.class_name.tableize}
11
+ after_create :create_access
12
+ after_update :update_access
13
+ after_destroy :destroy_access
14
+ end
15
+ end
16
+
17
+ module InstanceMethods
18
+ def create_access
19
+ create_accessor('create')
20
+ end
21
+
22
+ def update_access
23
+ create_accessor('update')
24
+ end
25
+
26
+ def destroy_access
27
+ create_accessor('destroy')
28
+ end
29
+
30
+ # This method is a performance killer and we are not expecting the base
31
+ # model to define it. If it is defined, this will replace it. In general
32
+ # if you want to define an additional after_find, call accessorize, then
33
+ # alias_method_chain the after_find.
34
+ def after_find
35
+ create_accessor('view')
36
+ end
37
+
38
+ def create_accessor(event)
39
+ accessors.create(:event => event,
40
+ :reference_type => self.class.name.tableize,
41
+ :accessor_id => Accessorize::Extension.accessor,
42
+ :meta => Accessorize::Extension.meta)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ ActiveRecord::Base.send :include, Accessorize::Base
@@ -0,0 +1,8 @@
1
+ module Accessorize
2
+ class Config
3
+ @@meta = :current_meta
4
+ @@accessor = :current_user
5
+ cattr_accessor :meta
6
+ cattr_accessor :accessor
7
+ end
8
+ end
@@ -0,0 +1,36 @@
1
+ module Accessorize
2
+ module Extension
3
+ @@meta = nil
4
+ @@accessor = nil
5
+
6
+ def self.included(base)
7
+ base.before_filter :set_extension_points
8
+ end
9
+
10
+ def self.meta
11
+ @@meta.respond_to?(:call) ? @@meta.call : @@meta
12
+ end
13
+
14
+ def self.accessor
15
+ @@accessor.respond_to?(:call) ? @@accessor.call : @@accessor
16
+ end
17
+
18
+ def self.meta=(value)
19
+ @@meta = value
20
+ end
21
+
22
+ def self.accessor=(value)
23
+ @@accessor = value
24
+ end
25
+
26
+ private
27
+
28
+ def set_extension_points
29
+ @@meta = lambda { self.send(Accessorize::Config.meta) rescue nil }
30
+ @@accessor = lambda { self.send(Accessorize::Config.accessor).id rescue nil }
31
+ end
32
+ end
33
+ end
34
+
35
+
36
+ ActionController::Base.send :include, Accessorize::Extension
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'accessorize')
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+
3
+ # Not really sure when to do this :)
4
+ Thing.accessorize
5
+ Struct.new("User", :id)
6
+
7
+ class ApplicationController < ActionController::Base
8
+ def current_user
9
+ Struct::User.new(87)
10
+ end
11
+
12
+ def current_meta
13
+ "Spilled milk"
14
+ end
15
+ end
16
+
17
+ class AccessorizeTest < ActiveSupport::TestCase
18
+ should "create an accessor record when creating a thing" do
19
+ assert_difference 'Accessorize::Accessor.count', 1 do
20
+ Thing.create
21
+ end
22
+ end
23
+
24
+ should "create an accessor record when updating a thing" do
25
+ thing = Thing.create
26
+ assert_difference 'Accessorize::Accessor.count', 1 do
27
+ thing.update_attributes(:mood => 'Hasslehoffish')
28
+ end
29
+ end
30
+
31
+ should "create an accessor record when destroying a thing" do
32
+ thing = Thing.create
33
+ assert_difference 'Accessorize::Accessor.count', 1 do
34
+ thing.destroy
35
+ end
36
+ end
37
+
38
+ should "create an accessor record when viewing a thing" do
39
+ thing = Thing.create
40
+ assert_difference 'Accessorize::Accessor.count', 1 do
41
+ mood = Thing.last.mood
42
+ end
43
+ end
44
+
45
+ should "set the accessor to the current user" do
46
+ Accessorize::Extension.accessor = 42
47
+ thing = Thing.create
48
+ assert_equal 42, Accessorize::Accessor.last.accessor_id
49
+ end
50
+
51
+ should "set the meta to the current meta" do
52
+ Accessorize::Extension.meta = "We were in the middle of tea"
53
+ thing = Thing.create
54
+ assert_equal "We were in the middle of tea", Accessorize::Accessor.last.meta
55
+ end
56
+ end
57
+
58
+ class ThingsControllerTest < ActionController::TestCase
59
+ test "should set the accessor to the current user" do
60
+ get :show, :id => things(:one).to_param
61
+ assert_response :success
62
+ assert_equal 87, Accessorize::Accessor.last.accessor_id
63
+ end
64
+
65
+ test "should set the meta to the current meta" do
66
+ get :show, :id => things(:one).to_param
67
+ assert_response :success
68
+ assert_equal "Spilled milk", Accessorize::Accessor.last.meta
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: accessorize
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Rafter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Sometimes you need to keep rigid logs of who created, updated and even accessed the data in your database. Accessorize simplifies the process.
26
+ email: jeff@socialrange.org
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - LICENSE
36
+ - README.rdoc
37
+ - Rakefile
38
+ - VERSION
39
+ - generators/accessorize/accessorize_generator.rb
40
+ - generators/accessorize/templates/initializer.rb
41
+ - generators/accessorize/templates/migration.rb
42
+ - lib/accessorize.rb
43
+ - lib/accessorize/accessor.rb
44
+ - lib/accessorize/base.rb
45
+ - lib/accessorize/config.rb
46
+ - lib/accessorize/extension.rb
47
+ - rails/init.rb
48
+ - test/accessorize_test.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/jeffrafter/accessorize
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.5
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Log all data access for your ActiveRecord models
77
+ test_files:
78
+ - test/accessorize_test.rb