forked from reidmix/userstamps
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added updated_by and stamped_by for both.
Refactored to DRY things up. Backwards compatible with created_by.
- Loading branch information
Reid MacDonald
committed
Jan 31, 2010
1 parent
35cfdb9
commit 7ea9ec7
Showing
5 changed files
with
193 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,64 @@ | ||
= CreatedBy | ||
= UserStamps | ||
|
||
Adds a simple +belongs_to+ association to a +creator+ model based on a magic column | ||
+created_by+ as it's foreign key. | ||
Adds a simple +belongs_to+ associations to a user model based on a magic columns | ||
+created_by+ and +updated_by+ as it's foreign key. | ||
|
||
== Example | ||
|
||
class User < ActiveRecord::Base | ||
end | ||
|
||
class Item < ActiveRecord::Base | ||
stamped_by :user | ||
end | ||
|
||
i = Item.find(1) | ||
i.created_by #=> 3 | ||
i.creator #=> #<User id:3> | ||
i.updated_by #=> 5 | ||
i.updator #=> #<User id:5> | ||
|
||
== Configuration | ||
|
||
You can specify configure how your +creator+ and +updator+ can be specified but | ||
you have to pass options to +created_by+ and +updated_by+ separately: | ||
|
||
class Item < ActiveRecord::Base | ||
created_by :user | ||
updated_by :admin | ||
end | ||
|
||
i = Item.find(1) | ||
i.created_by #=> 3 | ||
i.creator #=> #<User id:3> | ||
i.updated_by #=> 1 | ||
i.updator #=> #<Admin id:1> | ||
|
||
== Options | ||
|
||
By default, the creator is required, you can turn this off with a :required option: | ||
|
||
created_by :user, :required => false | ||
|
||
You could pass a :foriegn_key option to set a specific +created_by+ foriegn key but | ||
you might as well just setup the association yourself at that point. | ||
By default, the updator is _not_ required because on create you will need to specify | ||
an updator, but you can turn this on with a :required option: | ||
|
||
updated_by :admin, :required => true | ||
|
||
You could pass a :foriegn_key option to set a specific +created_by+ or +updated_by+ | ||
foriegn key but you might as well just setup the association yourself at that point. | ||
|
||
== Using only Created By | ||
|
||
If you only care about creators you can just specify a +created_by+ instead of | ||
+stamped_by+ as an option. | ||
|
||
class Item < ActiveRecord::Base | ||
created_by :user | ||
end | ||
|
||
i = Item.find(1) | ||
i.created_by #=> 3 | ||
i.creator #=> #<User id:3> | ||
|
||
Copyright (c) 2009 Reid MacDonald <reid@laruby.com>, released under the MIT license | ||
Copyright (c) 2010 Reid MacDonald <reid@laruby.com>, released under the MIT license |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
module ActiveRecord # :nodoc: | ||
module Associations # :nodoc: | ||
module UserStamps # :nodoc: | ||
## | ||
# Extends ActiveRecord::Base with ClassMethods | ||
def self.included base | ||
base.extend(ClassMethods) | ||
end | ||
|
||
## | ||
# Methods added to ActiveRecord::Base | ||
module ClassMethods | ||
## | ||
# Creates associations for +created_by+ and +updated_by+ using the respective configuration of each. | ||
def stamped_by user_model | ||
created_by user_model | ||
updated_by user_model | ||
end | ||
|
||
## | ||
# Creates an association on the +created_by+ column to the supplied +user_model+ argument. | ||
# You can override the +created_by+ column name with :foriegn_key but at that point you might | ||
# as well set up the relationship yourself. | ||
# | ||
# Required by default. | ||
def created_by user_model, options = {} | ||
user_association :creator, user_model, options.reverse_merge(:foreign_key => 'created_by', :required => true) | ||
end | ||
|
||
## | ||
# Creates an association on the +updated_by+ column to the supplied +user_model+ argument. | ||
# You can override the +updated_by+ column name with :foriegn_key but at that point you might | ||
# as well set up the relationship yourself. | ||
# | ||
# Not required by default. | ||
def updated_by user_model, options = {} | ||
user_association :updator, user_model, options.reverse_merge(:foreign_key => 'updated_by', :required => false) | ||
end | ||
|
||
private | ||
def user_association association, user_model, options | ||
configuration = {:class_name => user_model.to_s.classify}.merge!(options) | ||
|
||
belongs_to association, :foreign_key => configuration[:foreign_key], :class_name => configuration[:class_name] | ||
validates_presence_of association if configuration[:required] | ||
end | ||
end | ||
end | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
require File.dirname(__FILE__) + '/spec_helper' | ||
|
||
class MockActiveRecord < ActiveRecord::Base | ||
def self.column_names | ||
%w[id created_by updated_by] | ||
end | ||
|
||
def self.columns | ||
column_names.map do |name| | ||
ActiveRecord::ConnectionAdapters::Column.new(name.to_s, nil) | ||
end | ||
end | ||
end | ||
|
||
describe ActiveRecord::Base do | ||
it "includes ActiveRecord::Assocations::UserStamps::ClassMethods" do | ||
ActiveRecord::Base.methods.should be_member('stamped_by') | ||
ActiveRecord::Base.methods.should be_member('created_by') | ||
ActiveRecord::Base.methods.should be_member('updated_by') | ||
end | ||
end | ||
|
||
describe :created_by do | ||
describe :belongs_to do | ||
it "creates the belongs_to :creator association with default options" do | ||
MockActiveRecord.should_receive(:belongs_to).with(:creator, :class_name => 'MockCreator', :foreign_key => 'created_by') | ||
MockActiveRecord.created_by :mock_creator | ||
end | ||
|
||
it "creates the belongs_to association with alternate foreign_key" do | ||
MockActiveRecord.should_receive(:belongs_to).with(:creator, :class_name => 'MockCreator', :foreign_key => 'creator_id') | ||
MockActiveRecord.created_by :mock_creator, :foreign_key => 'creator_id' | ||
end | ||
|
||
it "creates the belongs_to association with alternate class_name (but why?)" do | ||
MockActiveRecord.should_receive(:belongs_to).with(:creator, :class_name => 'AnotherClassName', :foreign_key => 'created_by') | ||
MockActiveRecord.created_by :mock_creator, :class_name => 'AnotherClassName' | ||
end | ||
|
||
it 'ignores all other options' do | ||
MockActiveRecord.should_receive(:belongs_to).with(:creator, :class_name => 'MockCreator', :foreign_key => 'created_by') | ||
MockActiveRecord.created_by :mock_creator, :foo => 'Bar' | ||
end | ||
end | ||
|
||
describe :validates_presence_of do | ||
it 'is added by default' do | ||
MockActiveRecord.should_receive(:validates_presence_of).with(:creator) | ||
MockActiveRecord.created_by :mock_creator | ||
end | ||
|
||
it 'turns off validation for creator' do | ||
MockActiveRecord.should_not_receive(:validates_presence_of) | ||
MockActiveRecord.created_by :mock_creator, :required => false | ||
end | ||
end | ||
end | ||
|
||
describe :updated_by do | ||
describe :belongs_to do | ||
it "creates the belongs_to :updator association with default options" do | ||
MockActiveRecord.should_receive(:belongs_to).with(:updator, :class_name => 'MockUpdator', :foreign_key => 'updated_by') | ||
MockActiveRecord.updated_by :mock_updator | ||
end | ||
|
||
it "creates the belongs_to association with alternate foreign_key" do | ||
MockActiveRecord.should_receive(:belongs_to).with(:updator, :class_name => 'MockUpdator', :foreign_key => 'updator_id') | ||
MockActiveRecord.updated_by :mock_updator, :foreign_key => 'updator_id' | ||
end | ||
|
||
it "creates the belongs_to association with alternate class_name (but why?)" do | ||
MockActiveRecord.should_receive(:belongs_to).with(:updator, :class_name => 'AnotherClassName', :foreign_key => 'updated_by') | ||
MockActiveRecord.updated_by :mock_updator, :class_name => 'AnotherClassName' | ||
end | ||
|
||
it 'ignores all other options' do | ||
MockActiveRecord.should_receive(:belongs_to).with(:updator, :class_name => 'MockUpdator', :foreign_key => 'updated_by') | ||
MockActiveRecord.updated_by :mock_updator, :foo => 'Bar' | ||
end | ||
end | ||
|
||
describe :validates_presence_of do | ||
it 'is not added by default' do | ||
MockActiveRecord.should_not_receive(:validates_presence_of).with(:updator) | ||
MockActiveRecord.updated_by :mock_updator | ||
end | ||
|
||
it 'turns on validation for updator' do | ||
MockActiveRecord.should_receive(:validates_presence_of) | ||
MockActiveRecord.updated_by :mock_updator, :required => true | ||
end | ||
end | ||
end | ||
|
||
describe :stamped_by do | ||
it 'uses the same model on created_by and updated_by' do | ||
MockActiveRecord.should_receive(:created_by).with(:user) | ||
MockActiveRecord.should_receive(:updated_by).with(:user) | ||
MockActiveRecord.stamped_by :user | ||
end | ||
end |