From fea3b8c99cf3c5fcd920f258bd7602e9b2134c4d Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 12:51:33 +0530 Subject: [PATCH 01/19] Added ability to specify various configurations for Userstamp models --- lib/mongoid/userstamp.rb | 66 ++++++++++---------------- lib/mongoid/userstamp/userstampable.rb | 60 +++++++++++++++++++++++ lib/mongoid_userstamp.rb | 1 + 3 files changed, 87 insertions(+), 40 deletions(-) create mode 100644 lib/mongoid/userstamp/userstampable.rb diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index 6f67b56..f4e7f72 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -5,47 +5,35 @@ module Userstamp extend ActiveSupport::Concern included do - field Userstamp.config.updated_column, Userstamp.field_opts(Userstamp.config.updated_column_opts) - field Userstamp.config.created_column, Userstamp.field_opts(Userstamp.config.created_column_opts) - - before_save :set_updater - before_create :set_creator - - define_method Userstamp.config.updated_accessor do - Userstamp.find_user self.send(Userstamp.config.updated_column) - end - - define_method Userstamp.config.created_accessor do - Userstamp.find_user self.send(Userstamp.config.created_column) - end - - define_method "#{Userstamp.config.updated_accessor}=" do |user| - self.send("#{Userstamp.config.updated_column}=", Userstamp.extract_bson_id(user)) - end + cattr_reader :userstamp_key, instance_reader: false + @@userstamp_key = :default + Mongoid::Userstamp.add(self) + end - define_method "#{Userstamp.config.created_accessor}=" do |user| - self.send("#{Userstamp.config.created_column}=", Userstamp.extract_bson_id(user)) + module ClassMethods + def mongoid_userstamp(config = :default) + set_userstamp_key(config.to_sym) + send(:include, Mongoid::Userstamp::Userstampable) end - protected - - def set_updater - return if !Userstamp.has_current_user? - self.send("#{Userstamp.config.updated_accessor}=", Userstamp.current_user) + def set_userstamp_key(config) + class_variable_set('@@userstamp_key', config) end - def set_creator - return if !Userstamp.has_current_user? || self.send(Userstamp.config.created_column) - self.send("#{Userstamp.config.created_accessor}=", Userstamp.current_user) + def userstamp_config + Mongoid::Userstamp.configs[userstamp_key] end end class << self - def config(&block) + attr_reader :configs, :timestamped_models + + def config(name = :default, &block) + @configs ||= { default: Userstamp::Config.new } if block_given? - @@config = Userstamp::Config.new(&block) + @configs[name] = Userstamp::Config.new(&block) else - @@config ||= Userstamp::Config.new + @configs[name] = Userstamp::Config.new end end @@ -59,14 +47,6 @@ def field_opts(opts) {type: ::Moped::BSON::ObjectId}.reverse_merge(opts || {}) end - def has_current_user? - config.user_model.respond_to?(:current) - end - - def current_user - config.user_model.try(:current) - end - def extract_bson_id(value) if value.respond_to?(:_id) value.try(:_id) @@ -77,13 +57,19 @@ def extract_bson_id(value) end end - def find_user(user_id) + def find_user(user_model, user_id) begin - user_id ? Userstamp.config.user_model.unscoped.find(user_id) : nil + user_id ? user_model.unscoped.find(user_id) : nil rescue Mongoid::Errors::DocumentNotFound => e nil end end + + def add(model) + @timestamped_models ||= [] + @timestamped_models << model + end + end end end diff --git a/lib/mongoid/userstamp/userstampable.rb b/lib/mongoid/userstamp/userstampable.rb new file mode 100644 index 0000000..edeb040 --- /dev/null +++ b/lib/mongoid/userstamp/userstampable.rb @@ -0,0 +1,60 @@ +# -*- encoding : utf-8 -*- + +module Mongoid + module Userstamp + module Userstampable + extend ActiveSupport::Concern + + included do + + field userstamp_config.updated_column, Mongoid::Userstamp.field_opts(userstamp_config.updated_column_opts) + field userstamp_config.created_column, Mongoid::Userstamp.field_opts(userstamp_config.created_column_opts) + + before_save :set_updater + before_create :set_creator + + def userstamp_config + self.class.userstamp_config + end + + define_method userstamp_config.updated_accessor do + Mongoid::Userstamp.find_user userstamp_config.user_model, self.send(userstamp_config.updated_column) + end + + define_method userstamp_config.created_accessor do + Mongoid::Userstamp.find_user userstamp_config.user_model, self.send(userstamp_config.created_column) + end + + define_method "#{userstamp_config.updated_accessor}=" do |user| + self.send("#{userstamp_config.updated_column}=", Mongoid::Userstamp.extract_bson_id(user)) + end + + define_method "#{userstamp_config.created_accessor}=" do |user| + self.send("#{userstamp_config.created_column}=", Mongoid::Userstamp.extract_bson_id(user)) + end + + protected + + def set_updater + return if !self.class.has_current_user? + self.send("#{userstamp_config.updated_accessor}=", self.class.current_user) + end + + def set_creator + return if !self.class.has_current_user? || self.send(userstamp_config.created_column) + self.send("#{userstamp_config.created_accessor}=", self.class.current_user) + end + end + + module ClassMethods + def has_current_user? + userstamp_config.user_model.respond_to?(:current) + end + + def current_user + userstamp_config.user_model.try(:current) + end + end + end + end +end diff --git a/lib/mongoid_userstamp.rb b/lib/mongoid_userstamp.rb index 3928234..a176db8 100644 --- a/lib/mongoid_userstamp.rb +++ b/lib/mongoid_userstamp.rb @@ -3,4 +3,5 @@ require 'mongoid/userstamp/version' require 'mongoid/userstamp/config' require 'mongoid/userstamp/user' +require 'mongoid/userstamp/userstampable' require 'mongoid/userstamp/railtie' if defined? Rails From 3de3216bd82b897ef89377a16521ada08c898682 Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 12:58:31 +0530 Subject: [PATCH 02/19] Raise error if configuration not found --- lib/mongoid/userstamp.rb | 4 +++- lib/mongoid/userstamp/error.rb | 22 ++++++++++++++++++++++ lib/mongoid_userstamp.rb | 1 + 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 lib/mongoid/userstamp/error.rb diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index f4e7f72..e071dbb 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -17,6 +17,8 @@ def mongoid_userstamp(config = :default) end def set_userstamp_key(config) + available = Mongoid::Userstamp.configs.has_key?(config) + raise ConfigurationNotFoundError.new(config) unless available class_variable_set('@@userstamp_key', config) end @@ -31,7 +33,7 @@ class << self def config(name = :default, &block) @configs ||= { default: Userstamp::Config.new } if block_given? - @configs[name] = Userstamp::Config.new(&block) + @configs[name] = Userstamp::Config.new(&block) else @configs[name] = Userstamp::Config.new end diff --git a/lib/mongoid/userstamp/error.rb b/lib/mongoid/userstamp/error.rb new file mode 100644 index 0000000..4bb7147 --- /dev/null +++ b/lib/mongoid/userstamp/error.rb @@ -0,0 +1,22 @@ +class ConfigurationNotFoundError < StandardError + + attr_reader :config + + def initialize(config) + @config = config + super message + end + + def message + <<-eos + Mongoid Userstamp Configuration for #{config} is not defined. + Please define the configuration using: + Mongoid::Userstamp.config(:#{config}) do |c| + ... + Your configuration comes here + ... + end + eos + end + +end diff --git a/lib/mongoid_userstamp.rb b/lib/mongoid_userstamp.rb index a176db8..d61c020 100644 --- a/lib/mongoid_userstamp.rb +++ b/lib/mongoid_userstamp.rb @@ -2,6 +2,7 @@ require 'mongoid/userstamp' require 'mongoid/userstamp/version' require 'mongoid/userstamp/config' +require 'mongoid/userstamp/error' require 'mongoid/userstamp/user' require 'mongoid/userstamp/userstampable' require 'mongoid/userstamp/railtie' if defined? Rails From 843c662d7a378b1037f0059d0e0f7a988cd97dcb Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 12:59:54 +0530 Subject: [PATCH 03/19] Prefixing the Thread.current_name with "mongoid_userstamp" --- lib/mongoid/userstamp/user.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/mongoid/userstamp/user.rb b/lib/mongoid/userstamp/user.rb index 9054219..1638f43 100644 --- a/lib/mongoid/userstamp/user.rb +++ b/lib/mongoid/userstamp/user.rb @@ -5,18 +5,22 @@ module User extend ActiveSupport::Concern included do + cattr_accessor :user_key do + "mongoid_userstamp/#{self.to_s.underscore}".to_sym + end + def current? - !Thread.current[:user].nil? && self._id == Thread.current[:user]._id + !Thread.current[user_key].nil? && self._id == Thread.current[user_key]._id end end module ClassMethods def current - Thread.current[:user] + Thread.current[user_key] end def current=(value) - Thread.current[:user] = value + Thread.current[user_key] = value end def do_as(user, &block) From 17771de8867fdecf8b78ac10376942d97d897c61 Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 13:03:17 +0530 Subject: [PATCH 04/19] Modified Railtie to allow for backwards compatibility, i.e. works w/o calling mongoid_userstamp in model --- lib/mongoid/userstamp/railtie.rb | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/mongoid/userstamp/railtie.rb b/lib/mongoid/userstamp/railtie.rb index 3237e56..ad6b1d7 100644 --- a/lib/mongoid/userstamp/railtie.rb +++ b/lib/mongoid/userstamp/railtie.rb @@ -4,19 +4,31 @@ module Userstamp class Railtie < Rails::Railtie ActiveSupport.on_load :action_controller do before_filter do |c| - unless Mongoid::Userstamp.config.user_model.respond_to? :current - Mongoid::Userstamp.config.user_model.send( - :include, - Mongoid::Userstamp::User - ) - end - begin - Mongoid::Userstamp.config.user_model.current = c.send(Mongoid::Userstamp.config.user_reader) + + #### The below code is added for backwards compatibility so that the below works as well. In this case :default config is used. + # + # class Article + # include Mongoid::Userstamp + # end + # + Mongoid::Userstamp.timestamped_models.each do |model| + unless model.included_modules.include?(Mongoid::Userstamp::Userstampable) + model.send(:include, Mongoid::Userstamp::Userstampable) + end + end if Mongoid::Userstamp.timestamped_models + + Mongoid::Userstamp.configs.each_pair do |key, config| + unless config.user_model.respond_to?(:current) + config.user_model.send(:include, Mongoid::Userstamp::User) + end + + config.user_model.current = c.send(config.user_reader) + end rescue end end end end end -end +end \ No newline at end of file From 3321cc021eb9e0f1047fe317e5d0031cf601c919 Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 13:54:01 +0530 Subject: [PATCH 05/19] Fix Bug - userstamp_key not retaining original value --- lib/mongoid/userstamp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index e071dbb..3476746 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -6,7 +6,7 @@ module Userstamp included do cattr_reader :userstamp_key, instance_reader: false - @@userstamp_key = :default + class_variable_set('@@userstamp_key', :default) Mongoid::Userstamp.add(self) end From 5fab99035f76965fe372d092046fc4da28b30bdc Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 14:47:14 +0530 Subject: [PATCH 06/19] updated specs for multiple configs --- spec/mongoid/userstamp_spec.rb | 194 ++++++++++++++++++--------------- spec/spec_helper.rb | 8 +- spec/support/admin.rb | 7 ++ spec/support/book.rb | 4 +- spec/support/config.rb | 12 ++ spec/support/post.rb | 9 ++ 6 files changed, 144 insertions(+), 90 deletions(-) create mode 100644 spec/support/admin.rb create mode 100644 spec/support/config.rb create mode 100644 spec/support/post.rb diff --git a/spec/mongoid/userstamp_spec.rb b/spec/mongoid/userstamp_spec.rb index 2966ffa..6e53f2a 100644 --- a/spec/mongoid/userstamp_spec.rb +++ b/spec/mongoid/userstamp_spec.rb @@ -2,114 +2,158 @@ require 'spec_helper' describe Mongoid::Userstamp do - subject { Book.new(name: 'Crafting Rails Applications') } + subject(:book) { Book.new(name: 'Crafting Rails Applications') } + subject(:post) { Post.new(title: 'Understanding Rails') } + let(:user_1) { User.create!(name: 'Charles Dikkens') } let(:user_2) { User.create!(name: 'Edmund Wells') } - - it { should respond_to :created_by } - it { should respond_to :creator } - it { should respond_to :updated_by } - it { should respond_to :updater } + let(:admin_1) { Admin.create!(name: 'JK Rowling') } + let(:admin_2) { Admin.create!(name: 'Stephan Norway') } + + describe 'configuration' do + it { Mongoid::Userstamp.timestamped_models.should include(Book) } + it { Mongoid::Userstamp.timestamped_models.should include(Post) } + + context 'when :default' do + it { Book.userstamp_key.should eq :default } + it { Book.userstamp_config.should eq Mongoid::Userstamp.configs[:default] } + + it { book.should respond_to :created_by } + it { book.should respond_to :writer } + it { book.should respond_to :updated_by } + it { book.should respond_to :editor } + end + context 'when :admin' do + it { Post.userstamp_key.should eq :admin } + it { Post.userstamp_config.should eq Mongoid::Userstamp.configs[:admin] } + + it { post.should respond_to :c_by } + it { post.should respond_to :creator } + it { post.should respond_to :u_by } + it { post.should respond_to :updater } + end + end describe '#current_user' do - subject{ Mongoid::Userstamp.current_user } + before { Admin.current = nil; User.current = nil } + subject(:book_user){ Book.current_user } + subject(:post_user){ Post.current_user } - context 'when current user is not set' do + context 'when current book user is not set' do before { User.current = nil } - it { should be_nil } + it { book_user.should be_nil } + it { post_user.should be_nil } end - context 'when current user is set' do + context 'when current book user is set' do before{ User.current = user_1 } - it { should eq user_1 } + it { book_user.should eq user_1 } + it { post_user.should be_nil } + end + + context 'when current post user is not set' do + before { Admin.current = nil } + it { book_user.should be_nil } + it { post_user.should be_nil } + end + + context 'when current post user is set' do + before{ Admin.current = admin_1 } + it { book_user.should be_nil } + it { post_user.should eq admin_1 } end end context 'when created without a user' do before do + Admin.current = admin_1 User.current = nil - subject.save! + book.save! end - it { subject.created_by.should be_nil } - it { subject.creator.should be_nil } - it { subject.updated_by.should be_nil } - it { subject.updater.should be_nil } + it { book.created_by.should be_nil } + it { book.writer.should be_nil } + it { book.updated_by.should be_nil } + it { book.editor.should be_nil } end context 'when creator is manually set' do - before{ User.current = user_1 } - + before do + User.current = user_1 + Admin.current = admin_1 + end + context 'set by id' do before do - subject.created_by = user_2._id - subject.save! + post.c_by = admin_2._id + post.save! end - + it 'should not be overridden when saved' do - subject.created_by.should eq user_2.id - subject.creator.should eq user_2 - subject.updated_by.should eq user_1.id - subject.updater.should eq user_1 + post.c_by.should eq admin_2.id + post.creator.should eq admin_2 + post.u_by.should eq admin_1.id + post.updater.should eq admin_1 end end context 'set by model' do before do - subject.creator = user_2 - subject.save! + post.creator = admin_2 + post.save! end it 'should not be overridden when saved' do - subject.created_by.should eq user_2.id - subject.creator.should eq user_2 - subject.updated_by.should eq user_1.id - subject.updater.should eq user_1 + post.c_by.should eq admin_2.id + post.creator.should eq admin_2 + post.u_by.should eq admin_1.id + post.updater.should eq admin_1 end end end - + context 'when created by a user' do before do + Admin.current = admin_1 User.current = user_1 - subject.save! + book.save! end - it { subject.created_by.should == user_1.id } - it { subject.creator.should == user_1 } - it { subject.updated_by.should == user_1.id } - it { subject.updater.should == user_1 } + it { book.created_by.should == user_1.id } + it { book.writer.should == user_1 } + it { book.updated_by.should == user_1.id } + it { book.editor.should == user_1 } context 'when updated by a user' do before do User.current = user_2 - subject.save! + book.save! end - it { subject.created_by.should == user_1.id } - it { subject.creator.should == user_1 } - it { subject.updated_by.should == user_2.id } - it { subject.updater.should == user_2 } + it { book.created_by.should == user_1.id } + it { book.writer.should == user_1 } + it { book.updated_by.should == user_2.id } + it { book.editor.should == user_2 } end context 'when user has been destroyed' do before do User.current = user_2 - subject.save! + book.save! user_1.destroy user_2.destroy end - it { subject.created_by.should == user_1.id } - it { subject.creator.should == nil } - it { subject.updated_by.should == user_2.id } - it { subject.updater.should == nil } + it { book.created_by.should == user_1.id } + it { book.writer.should be_nil } + it { book.updated_by.should == user_2.id } + it { book.editor.should be_nil } end end describe '#config' do before do - Mongoid::Userstamp.config do |c| - c.user_reader = :current_user + Mongoid::Userstamp.config(:test) do |c| + c.user_reader = :test_user c.user_model = :user c.created_column = :c_by @@ -120,44 +164,24 @@ c.updated_column_opts = {as: :updated_by_id} c.updated_accessor = :updated_by end - - # class definition must come after config - class Novel - include Mongoid::Document - include Mongoid::Userstamp - - field :name - end end - subject { Novel.new(name: 'Ethyl the Aardvark goes Quantity Surveying') } - context 'when created by a user' do - before do - User.current = user_1 - subject.save! - end + subject { Mongoid::Userstamp.configs[:test] } - it { subject.c_by.should == user_1.id } - it { subject.created_by_id.should == user_1.id } - it { subject.created_by.should == user_1 } - it { subject.u_by.should == user_1.id } - it { subject.updated_by_id.should == user_1.id } - it { subject.updated_by.should == user_1 } - - context 'when updated by a user' do - before do - User.current = user_2 - subject.save! - end - - it { subject.c_by.should == user_1.id } - it { subject.created_by_id.should == user_1.id } - it { subject.created_by.should == user_1 } - it { subject.u_by.should == user_2.id } - it { subject.updated_by_id.should == user_2.id } - it { subject.updated_by.should == user_2 } - end - end + it { Mongoid::Userstamp.should respond_to :config } + it { Mongoid::Userstamp.configs.should have_key(:test) } + + it { subject.user_reader.should == :test_user } + it { subject.user_model.should == User } + it { subject.created_column.should == :c_by } + it { subject.created_column_opts.should == {as: :created_by_id} } + it { subject.created_accessor.should == :created_by } + it { subject.updated_column.should == :u_by } + it { subject.updated_column_opts.should == {as: :updated_by_id} } + it { subject.updated_accessor.should == :updated_by } end -end + context 'when using an undefined configuration' do + it { ->{ Book.send(:mongoid_userstamp, :any_config) }.should raise_error(ConfigurationNotFoundError) } + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1a3892a..99c0c8e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,16 +7,16 @@ require 'mongoid' require 'mongoid_userstamp' +%w(config admin user book post).each do |file_name| + require "support/#{file_name}" +end + Mongoid.configure do |config| config.connect_to( 'mongoid_userstamp_test' ) end -Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |f| - require f -end - RSpec.configure do |config| config.mock_with :rspec diff --git a/spec/support/admin.rb b/spec/support/admin.rb new file mode 100644 index 0000000..5789a25 --- /dev/null +++ b/spec/support/admin.rb @@ -0,0 +1,7 @@ +# -*- encoding : utf-8 -*- +class Admin + include Mongoid::Document + include Mongoid::Userstamp::User + + field :name +end \ No newline at end of file diff --git a/spec/support/book.rb b/spec/support/book.rb index a81c348..faa8bb9 100644 --- a/spec/support/book.rb +++ b/spec/support/book.rb @@ -3,5 +3,7 @@ class Book include Mongoid::Document include Mongoid::Userstamp + mongoid_userstamp + field :name -end +end \ No newline at end of file diff --git a/spec/support/config.rb b/spec/support/config.rb new file mode 100644 index 0000000..040bf1b --- /dev/null +++ b/spec/support/config.rb @@ -0,0 +1,12 @@ +Mongoid::Userstamp.config do |c| + c.created_accessor = :writer + c.updated_accessor = :editor +end + +Mongoid::Userstamp.config(:admin) do |c| + c.user_reader = :current_admin + c.user_model = :admin + + c.created_column = :c_by + c.updated_column = :u_by +end \ No newline at end of file diff --git a/spec/support/post.rb b/spec/support/post.rb new file mode 100644 index 0000000..dd7d7c9 --- /dev/null +++ b/spec/support/post.rb @@ -0,0 +1,9 @@ +# -*- encoding : utf-8 -*- +class Post + include Mongoid::Document + include Mongoid::Userstamp + + mongoid_userstamp :admin + + field :title +end \ No newline at end of file From eaa723cc77c73016506c71ada0b2cf8c695f690b Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 15:11:29 +0530 Subject: [PATCH 07/19] updated gemspec and Readme for new syntax --- README.md | 41 +++++++++++++++++++++++++++++++++++++++ mongoid_userstamp.gemspec | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e04ac36..b6498ef 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,46 @@ MongoidUserstamp is tested on the following versions: p.creator = my_user # can be a Mongoid::Document or a BSON::ObjectID # => sets created_by to my_user._id ``` +## Multiple Configurations + +Mongoid::Userstamp provides ability to create multiple configurations. Simply create a new configuration as: + +```ruby + # Admin config + Mongoid::Userstamp.config :admin do |c| + + # Admin specific config values + # Defaults are considered for values not specified. + + c.user_reader = :current_admin + c.user_model = :admin + + end +``` + +Now to use this configuration instead of the default in any model use 'mongoid_userstamp' class method to specify configuration. + +``` + # Example model + class Book + include Mongoid::Document + include Mongoid::Userstamp + + # specifying the configuration to be used. If none then :default configuration is used. + mongoid_userstamp :admin + end + + # Create instance + b = Book.create + + b.updater = + + b.updated_by + # => BSON::ObjectId('4f7c719f476da850ba000039') + + b.updater + # => +``` ## Contributing @@ -84,6 +124,7 @@ Please use Ruby 1.9.3 hash syntax, as Mongoid 3 requires Ruby >= 1.9.3 * [Thomas Boerger](http://www.tbpro.de) * [John Shields](https://github.com/johnnyshields) +* [Bharat Gupta](https://github.com/Bharat311) ## Copyright diff --git a/mongoid_userstamp.gemspec b/mongoid_userstamp.gemspec index 6d2b115..14b9a3c 100644 --- a/mongoid_userstamp.gemspec +++ b/mongoid_userstamp.gemspec @@ -4,7 +4,7 @@ require 'mongoid/userstamp/version' Gem::Specification.new do |s| s.name = 'mongoid_userstamp' s.version = Mongoid::Userstamp::VERSION - s.authors = ['Thomas Boerger', 'Johnny Shields'] + s.authors = ['Thomas Boerger', 'Johnny Shields', 'Bharat Gupta'] s.homepage = 'https://github.com/tbpro/mongoid_userstamp' s.license = 'MIT' s.summary = 'Userstamp for Mongoid' From fd8c4fa68e02f38e5e353a2f2f4998ff18f0b4b6 Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Fri, 14 Feb 2014 15:14:48 +0530 Subject: [PATCH 08/19] Added demo app to README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index b6498ef..f7ba023 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,10 @@ Now to use this configuration instead of the default in any model use 'mongoid_u # => ``` +## Demo App + +A demo application demonstrating how to define and use multiple configurations in Mongoid::Userstamp can be found [here](https://github.com/Bharat311/mongoid_userstamp_demo). + ## Contributing Fork -> Patch -> Spec -> Push -> Pull Request From 87f933d26d6bbaa31ea6e2b6d30ccd75e34f39a6 Mon Sep 17 00:00:00 2001 From: Bharat Gupta Date: Tue, 18 Feb 2014 14:32:21 +0530 Subject: [PATCH 09/19] fix bug - a single missing user_reader module does not include module to other user_reader classes --- lib/mongoid/userstamp/railtie.rb | 34 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/mongoid/userstamp/railtie.rb b/lib/mongoid/userstamp/railtie.rb index ad6b1d7..2299ce2 100644 --- a/lib/mongoid/userstamp/railtie.rb +++ b/lib/mongoid/userstamp/railtie.rb @@ -2,33 +2,35 @@ module Mongoid module Userstamp class Railtie < Rails::Railtie + ActiveSupport.on_load :action_controller do before_filter do |c| - begin - - #### The below code is added for backwards compatibility so that the below works as well. In this case :default config is used. - # - # class Article - # include Mongoid::Userstamp - # end - # - Mongoid::Userstamp.timestamped_models.each do |model| - unless model.included_modules.include?(Mongoid::Userstamp::Userstampable) - model.send(:include, Mongoid::Userstamp::Userstampable) - end - end if Mongoid::Userstamp.timestamped_models + #### The below code is added for backwards compatibility so that the below works as well. In this case :default config is used. + # + # class Article + # include Mongoid::Userstamp + # end + # + Mongoid::Userstamp.timestamped_models.each do |model| + unless model.included_modules.include?(Mongoid::Userstamp::Userstampable) + model.send(:include, Mongoid::Userstamp::Userstampable) + end + end if Mongoid::Userstamp.timestamped_models - Mongoid::Userstamp.configs.each_pair do |key, config| + Mongoid::Userstamp.configs.each_pair do |key, config| + begin unless config.user_model.respond_to?(:current) config.user_model.send(:include, Mongoid::Userstamp::User) end config.user_model.current = c.send(config.user_reader) + rescue end - rescue end + end end + end end -end \ No newline at end of file +end From b21883e79b94281cdafebd55c6458a2b91b3a34c Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Sat, 22 Feb 2014 12:16:25 +0900 Subject: [PATCH 10/19] Experimental polymorphic classes --- CHANGELOG.md | 6 + README.md | 149 +++++++------ lib/mongoid/userstamp.rb | 69 +----- lib/mongoid/userstamp/config.rb | 30 --- lib/mongoid/userstamp/config/app_config.rb | 70 ++++++ lib/mongoid/userstamp/config/user_config.rb | 23 ++ lib/mongoid/userstamp/configurable.rb | 19 ++ lib/mongoid/userstamp/controller.rb | 67 ++++++ lib/mongoid/userstamp/error.rb | 22 -- lib/mongoid/userstamp/railtie.rb | 38 ++-- lib/mongoid/userstamp/user.rb | 52 +++-- lib/mongoid/userstamp/userstampable.rb | 67 +++--- lib/mongoid/userstamp/version.rb | 2 +- mongoid_userstamp.gemspec | 1 + spec/integration/config_spec.rb | 205 +++++++++++++++++ spec/integration/controller_spec.rb | 206 ++++++++++++++++++ .../userstamp_spec.rb | 0 spec/unit/app_config_spec.rb | 28 +++ spec/unit/user_config_spec.rb | 45 ++++ 19 files changed, 822 insertions(+), 277 deletions(-) delete mode 100644 lib/mongoid/userstamp/config.rb create mode 100644 lib/mongoid/userstamp/config/app_config.rb create mode 100644 lib/mongoid/userstamp/config/user_config.rb create mode 100644 lib/mongoid/userstamp/configurable.rb create mode 100644 lib/mongoid/userstamp/controller.rb delete mode 100644 lib/mongoid/userstamp/error.rb create mode 100644 spec/integration/config_spec.rb create mode 100644 spec/integration/controller_spec.rb rename spec/{mongoid => integration}/userstamp_spec.rb (100%) create mode 100644 spec/unit/app_config_spec.rb create mode 100644 spec/unit/user_config_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f86da3..2441c8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [0.4.0](https://github.com/tbpro/mongoid_userstamp/releases/tag/v0.4.0) - 2014-02-20 + +* BREAKING: Change userstamp keys to use Mongoid relations. Requires database migration. +* Add support for multiple user classes via polymorphic userstamps. +* Refactor to extract `Controller` and `Configurable` modules + ## [0.3.2](https://github.com/tbpro/mongoid_userstamp/releases/tag/v0.3.2) - 2014-01-12 * Fix bad gem release diff --git a/README.md b/README.md index f7ba023..ae60c92 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# MongoidUserstamp [![Build Status](https://secure.travis-ci.org/tbpro/mongoid_userstamp.png)](https://travis-ci.org/tbpro/mongoid_userstamp) [![Code Climate](https://codeclimate.com/github/tbpro/mongoid_userstamp.png)](https://codeclimate.com/github/tbpro/mongoid_userstamp) +# Mongoid::Userstamp [![Build Status](https://secure.travis-ci.org/tbpro/mongoid_userstamp.png)](https://travis-ci.org/tbpro/mongoid_userstamp) [![Code Climate](https://codeclimate.com/github/tbpro/mongoid_userstamp.png)](https://codeclimate.com/github/tbpro/mongoid_userstamp) -MongoidUserstamp adds stamp columns for created by and updated by +Mongoid::Userstamp adds stamp columns for created by and updated by information within Rails applications using Mongoid ORM. ## Version Support -MongoidUserstamp is tested on the following versions: +Mongoid::Userstamp is tested on the following versions: * Ruby 1.9.3 and 2.0.0 * Rails 3 @@ -19,104 +19,117 @@ MongoidUserstamp is tested on the following versions: ## Usage +Mongoid::Userstamp does the following: +* Defines Mongoid `belongs_to` relations to the user class for `created_by` and `updated_by` on each class where `Mongoid::Userstamp` is included +* Automatically tracks the current user via a `before_filter` (see Rails Integration below) +* Sets the `created_by` and `updated_by` values in `before_save` and `before_update` callbacks respectively on the target models. +* Adds methods to the user class to check for the current user. + ```ruby - # Default config + # Default config (optional unless you want to customize the values) Mongoid::Userstamp.config do |c| - - # Default config values - c.user_reader = :current_user c.user_model = :user - - c.created_column = :created_by - c.created_accessor = :creator - - c.updated_column = :updated_by - c.updated_accessor = :updater - - # Optional config values - - # c.created_alias = :c - # c.updated_alias = :u + c.created_by_name = :created_by + c.updated_by_name = :updated_by + c.polymorphic = false + c.use_request_store = false end # Example model - class Person + class Product include Mongoid::Document include Mongoid::Userstamp end # Create instance - p = Person.create + p = Product.create - # Updater ObjectID or nil - p.updated_by + # Creator ObjectID | Updater ObjectID + p.created_by_id | p.updated_by_id # => BSON::ObjectId('4f7c719f476da850ba000039') - # Updater instance or nil - p.updater + # Creator instance | Updater instance + p.created_by | p.updated_by # => - # Set updater manually (usually not required) - p.updater = my_user # can be a Mongoid::Document or a BSON::ObjectID - # => sets updated_by to my_user's ObjectID + # Set creator/updater manually (usually not required) + p.created_by = User.where(name: 'Will Smith') + p.updated_by = User.where(name: 'DJ Jazzy Jeff') +``` - # Creator ObjectID or nil - p.created_by - # => BSON::ObjectId('4f7c719f476da850ba000039') - # Creator instance or nil - p.creator - # => +## Rails Integration - # Set creator manually (usually not required) - p.creator = my_user # can be a Mongoid::Document or a BSON::ObjectID - # => sets created_by to my_user._id -``` -## Multiple Configurations +Popular Rails authentication frameworks such as Devise and Sorcery make a `current_user` method available in +your Controllers. Mongoid::Userstamp will automatically use this to set its user reference in a `before_filter` +on each request. (You can set an alternative method name via the `user_reader` config.) -Mongoid::Userstamp provides ability to create multiple configurations. Simply create a new configuration as: +*Gotcha:* If you have special controller actions which change/switch the current user to a new user, you will +need to set `Mongoid::Userstamp.current_user = new_user` after the switch occurs. -```ruby - # Admin config - Mongoid::Userstamp.config :admin do |c| - # Admin specific config values - # Defaults are considered for values not specified. +## Thread Safety - c.user_reader = :current_admin - c.user_model = :admin +By default, Mongoid::Userstamp stores all-related user variables in `Thread.current`. This may cause +erratic behavior on threaded web servers like Thin or Puma. Fortunately you can use the +[RequestStore](https://github.com/steveklabnik/request_store) gem as workaround by installing the gem and +setting `use_request_store = true` in your config. - end -``` -Now to use this configuration instead of the default in any model use 'mongoid_userstamp' class method to specify configuration. +## Advanced Usage: Polymorphic Userstamps -``` - # Example model - class Book - include Mongoid::Document - include Mongoid::Userstamp - - # specifying the configuration to be used. If none then :default configuration is used. - mongoid_userstamp :admin - end +In general, most Rails apps use a single user model. However, if you would like to use +Mongoid::Userstamp will track a separate current_user for each class. - # Create instance - b = Book.create +Please be aware of the following limitations of this approach: +* Enabling `use_polymorphic = true` will make every userstamped class in your application +to be polymorphic. +* You will have to manually add the `created_by_type` and `updated_by_type` fields +if you were not using them previously. +* Although multiple user classes may be logged in at once, the userstamp contains only one value by design. +The assumption is that there is only one actual user/person who does the given create/update action. - b.updater = +```ruby + # Example config for polymorphism + Mongoid::Userstamp.config do |c| + c.polymorphic = true - b.updated_by - # => BSON::ObjectId('4f7c719f476da850ba000039') + c.user_config do |u| + u.model = :merchant_user + u.reader = :current_merchant_user + end - b.updater - # => -``` + c.user_config do |u| + u.model = :customer_user + u.reader = :current_customer_user + end + end -## Demo App + # Example model (same as non-polymorphic case) + class Product + include Mongoid::Document + include Mongoid::Userstamp + end -A demo application demonstrating how to define and use multiple configurations in Mongoid::Userstamp can be found [here](https://github.com/Bharat311/mongoid_userstamp_demo). + # Set current user for each type + Mongoid::Userstamp.current_user = CustomerUser.where(name: 'Sir Mix-A-Lot') + Mongoid::Userstamp.current_user = MerchantUser.where(name: 'Biz Markie') + + # In your Controller action + product = Product.new('Baby Got Back Single') + Mongoid::Userstamp.user_class = 'customer_user' + product.save! + product.updated_by.name #=> 'Sir Mix-A-Lot' + product.updated_by_type #=> 'CustomerUser' + + # Alternative block syntax + Mongoid::Userstamp.with_user_class('merchant_user') do + product.save! + product.updated_by.name #=> 'Biz Markie' + product.updated_by_type #=> 'MerchantUser' + end +``` ## Contributing diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index 3476746..14250fe 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -4,74 +4,11 @@ module Mongoid module Userstamp extend ActiveSupport::Concern - included do - cattr_reader :userstamp_key, instance_reader: false - class_variable_set('@@userstamp_key', :default) - Mongoid::Userstamp.add(self) - end - - module ClassMethods - def mongoid_userstamp(config = :default) - set_userstamp_key(config.to_sym) - send(:include, Mongoid::Userstamp::Userstampable) - end - - def set_userstamp_key(config) - available = Mongoid::Userstamp.configs.has_key?(config) - raise ConfigurationNotFoundError.new(config) unless available - class_variable_set('@@userstamp_key', config) - end - - def userstamp_config - Mongoid::Userstamp.configs[userstamp_key] - end - end + include Mongoid::Userstamp::Userstampable class << self - attr_reader :configs, :timestamped_models - - def config(name = :default, &block) - @configs ||= { default: Userstamp::Config.new } - if block_given? - @configs[name] = Userstamp::Config.new(&block) - else - @configs[name] = Userstamp::Config.new - end - end - - # DEPRECATED - def configure(&block) - warn 'Mongoid::Userstamp.configure is deprecated. Please use Mongoid::Userstamp.config instead' - config(block) - end - - def field_opts(opts) - {type: ::Moped::BSON::ObjectId}.reverse_merge(opts || {}) - end - - def extract_bson_id(value) - if value.respond_to?(:_id) - value.try(:_id) - elsif value.present? - ::Moped::BSON::ObjectId.from_string(value.to_s) - else - nil - end - end - - def find_user(user_model, user_id) - begin - user_id ? user_model.unscoped.find(user_id) : nil - rescue Mongoid::Errors::DocumentNotFound => e - nil - end - end - - def add(model) - @timestamped_models ||= [] - @timestamped_models << model - end - + include Mongoid::Userstamp::Configurable + include Mongoid::Userstamp::Controller end end end diff --git a/lib/mongoid/userstamp/config.rb b/lib/mongoid/userstamp/config.rb deleted file mode 100644 index dd12bac..0000000 --- a/lib/mongoid/userstamp/config.rb +++ /dev/null @@ -1,30 +0,0 @@ -# -*- encoding : utf-8 -*- -module Mongoid - module Userstamp - class Config - attr_writer :user_model - attr_accessor :user_reader - attr_accessor :created_column - attr_accessor :created_column_opts - attr_accessor :created_accessor - attr_accessor :updated_column - attr_accessor :updated_column_opts - attr_accessor :updated_accessor - - def initialize(&block) - @user_model = :user - @user_reader = :current_user - @created_column = :created_by - @created_accessor = :creator - @updated_column = :updated_by - @updated_accessor = :updater - - instance_eval(&block) if block_given? - end - - def user_model - @user_model.to_s.classify.constantize - end - end - end -end diff --git a/lib/mongoid/userstamp/config/app_config.rb b/lib/mongoid/userstamp/config/app_config.rb new file mode 100644 index 0000000..7a6c579 --- /dev/null +++ b/lib/mongoid/userstamp/config/app_config.rb @@ -0,0 +1,70 @@ +# -*- encoding : utf-8 -*- +module Mongoid +module Userstamp +module Config + + module AppConfig + + attr_accessor :created_by_name + attr_reader :created_by_opts + attr_accessor :updated_by_name + attr_reader :updated_by_opts + attr_reader :use_request_store + attr_reader :user_configs + + + def initialize(&block) + + # intialize members + @created_by_name = :created_by + @updated_by_name = :updated_by + @use_request_store = false + + instance_eval(&block) if block_given? + + # initialize user config + user_config + @user_config_set = false + + end + + def use_request_store=(value) + @use_request_store = !!value + end + + def user_config(&block) + @user_configs = [] unless @user_config_set + @user_configs << Mongoid::Userstamp::Config::UserConfig.new(&block) + @user_config_set = true + end + + def user_model(value) + @user_configs.first.model = value + end + + def user_reader(value) + @user_configs.first.reader = value + end + + # @deprecated + def created_column=(value) + warn 'Mongoid::Userstamp `created_column` is deprecated as of v0.4.0. Please use `created_by_name` instead.' + created_by_name = value + end + + # @deprecated + def updated_column=(value) + warn 'Mongoid::Userstamp `created_column` is deprecated as of v0.4.0. Please use `created_by_name` instead.' + updated_by_name = value + end + end +end +end +end + + +# c.user_model = :'vesper/beauty/merchant_user' +# c.user_reader = :current_bs_merchant_user + +# c.user_model = :'table_solution/merchant_user' +# c.user_reader = :current_merchant_user diff --git a/lib/mongoid/userstamp/config/user_config.rb b/lib/mongoid/userstamp/config/user_config.rb new file mode 100644 index 0000000..38047d8 --- /dev/null +++ b/lib/mongoid/userstamp/config/user_config.rb @@ -0,0 +1,23 @@ +# -*- encoding : utf-8 -*- +module Mongoid +module Userstamp +module Config + + module UserConfig + + attr_writer :model + attr_accessor :reader + + def initialize(&block) + @model = :user + @reader = :current_user + instance_eval(&block) if block_given? + end + + def model + @model.to_s.classify.constantize + end + end +end +end +end diff --git a/lib/mongoid/userstamp/configurable.rb b/lib/mongoid/userstamp/configurable.rb new file mode 100644 index 0000000..d4bccae --- /dev/null +++ b/lib/mongoid/userstamp/configurable.rb @@ -0,0 +1,19 @@ +# -*- encoding : utf-8 -*- + +module Mongoid +module Userstamp + + module Configurable + + def config(&block) + @config ||= Mongoid::Userstamp::Config::AppConfig.new(&block) + end + + # @deprecated + def configure(&block) + warn 'Mongoid::Userstamp.configure is deprecated. Please use Mongoid::Userstamp.config instead' + config(&block) + end + end +end +end diff --git a/lib/mongoid/userstamp/controller.rb b/lib/mongoid/userstamp/controller.rb new file mode 100644 index 0000000..a0c4069 --- /dev/null +++ b/lib/mongoid/userstamp/controller.rb @@ -0,0 +1,67 @@ +# -*- encoding : utf-8 -*- + +module Mongoid +module Userstamp + + module Controller + + #THREAD_DOMAIN = 'mongoid_userstamp/' + + def userstamp_key(model) + # need to map default here + "mongoid_userstamp/#{model.to_s.underscore}".to_sym + end + + def has_current_user?(model = nil) + current_user.present + end + + def current_user(model = nil) + model ||= user_class + store[userstamp_key(model)] + end + + def current_user=(value) + store[userstamp_key(value.class)] = value + end + + def user_model + if Mongoid::Userstamp.config.polymorphic + store['mongoid_userstamp/user_class'] || :default + else + :default + end + end + + def user_model=(klass) + store['mongoid_userstamp/user_class'] = klass + end + + def user_class + case user_model + when :default, 'default' + Mongoid::Userstamp.config.user_configs.first.model.to_s.classify.constantize + when Class + user_model + when Symbol, String + user_class.classify.constantize + end + end + + def store + Mongoid::Userstamp.config.use_request_store ? RequestStore.store : Thread.current + end + + def with_user_class(klass, &block) + old_klass = user_class + begin + user_class = klass + response = block.call unless block.nil? + ensure + user_class = old_klass + end + response + end + end +end +end diff --git a/lib/mongoid/userstamp/error.rb b/lib/mongoid/userstamp/error.rb deleted file mode 100644 index 4bb7147..0000000 --- a/lib/mongoid/userstamp/error.rb +++ /dev/null @@ -1,22 +0,0 @@ -class ConfigurationNotFoundError < StandardError - - attr_reader :config - - def initialize(config) - @config = config - super message - end - - def message - <<-eos - Mongoid Userstamp Configuration for #{config} is not defined. - Please define the configuration using: - Mongoid::Userstamp.config(:#{config}) do |c| - ... - Your configuration comes here - ... - end - eos - end - -end diff --git a/lib/mongoid/userstamp/railtie.rb b/lib/mongoid/userstamp/railtie.rb index 2299ce2..3810c32 100644 --- a/lib/mongoid/userstamp/railtie.rb +++ b/lib/mongoid/userstamp/railtie.rb @@ -1,36 +1,26 @@ # -*- encoding : utf-8 -*- module Mongoid - module Userstamp - class Railtie < Rails::Railtie +module Userstamp - ActiveSupport.on_load :action_controller do - before_filter do |c| - #### The below code is added for backwards compatibility so that the below works as well. In this case :default config is used. - # - # class Article - # include Mongoid::Userstamp - # end - # - Mongoid::Userstamp.timestamped_models.each do |model| - unless model.included_modules.include?(Mongoid::Userstamp::Userstampable) - model.send(:include, Mongoid::Userstamp::Userstampable) - end - end if Mongoid::Userstamp.timestamped_models + class Railtie < Rails::Railtie - Mongoid::Userstamp.configs.each_pair do |key, config| - begin - unless config.user_model.respond_to?(:current) - config.user_model.send(:include, Mongoid::Userstamp::User) - end + ActiveSupport.on_load :action_controller do - config.user_model.current = c.send(config.user_reader) - rescue - end + before_filter do |c| + + Mongoid::Userstamp.config.user_configs.each do |user_config| + unless user_config.user_class.respond_to? :current + user_config.user_class.send(:include, Mongoid::Userstamp::User) end + # TODO FIX THIS + begin + user_config.user_class.user_model.current = c.send(user_config.reader) + rescue + end end end - end end end +end diff --git a/lib/mongoid/userstamp/user.rb b/lib/mongoid/userstamp/user.rb index 1638f43..ffdc919 100644 --- a/lib/mongoid/userstamp/user.rb +++ b/lib/mongoid/userstamp/user.rb @@ -1,41 +1,39 @@ # -*- encoding : utf-8 -*- module Mongoid - module Userstamp - module User - extend ActiveSupport::Concern +module Userstamp - included do - cattr_accessor :user_key do - "mongoid_userstamp/#{self.to_s.underscore}".to_sym - end + module User - def current? - !Thread.current[user_key].nil? && self._id == Thread.current[user_key]._id - end - end + extend ActiveSupport::Concern - module ClassMethods - def current - Thread.current[user_key] - end + included do - def current=(value) - Thread.current[user_key] = value - end + def current? + self._id == Mongoid::Userstamp.current_user(self.class).try(:_id) + end + end - def do_as(user, &block) - old = self.current + module ClassMethods - begin - self.current = user - response = block.call unless block.nil? - ensure - self.current = old - end + def current + Mongoid::Userstamp.current_user(self) + end - response + def current=(value) + Mongoid::Userstamp.current_user = value + end + + def do_as(user, &block) + old = self.current + begin + self.current = user + response = block.call unless block.nil? + ensure + self.current = old end + response end end end end +end diff --git a/lib/mongoid/userstamp/userstampable.rb b/lib/mongoid/userstamp/userstampable.rb index edeb040..c5456d2 100644 --- a/lib/mongoid/userstamp/userstampable.rb +++ b/lib/mongoid/userstamp/userstampable.rb @@ -1,60 +1,49 @@ # -*- encoding : utf-8 -*- module Mongoid - module Userstamp - module Userstampable - extend ActiveSupport::Concern +module Userstamp - included do + module Userstampable - field userstamp_config.updated_column, Mongoid::Userstamp.field_opts(userstamp_config.updated_column_opts) - field userstamp_config.created_column, Mongoid::Userstamp.field_opts(userstamp_config.created_column_opts) + extend ActiveSupport::Concern - before_save :set_updater - before_create :set_creator + included do - def userstamp_config - self.class.userstamp_config - end - - define_method userstamp_config.updated_accessor do - Mongoid::Userstamp.find_user userstamp_config.user_model, self.send(userstamp_config.updated_column) - end + belongs_to Mongoid::Userstamp.config.created_by_name, + Mongoid::Userstamp::Userstampable.relation_opts(Mongoid::Userstamp.config.updated_column_opts) - define_method userstamp_config.created_accessor do - Mongoid::Userstamp.find_user userstamp_config.user_model, self.send(userstamp_config.created_column) - end + belongs_to Mongoid::Userstamp.config.updated_by_name, + Mongoid::Userstamp::Userstampable.relation_opts(Mongoid::Userstamp.config.updated_column_opts) - define_method "#{userstamp_config.updated_accessor}=" do |user| - self.send("#{userstamp_config.updated_column}=", Mongoid::Userstamp.extract_bson_id(user)) - end + before_create :set_created_by - define_method "#{userstamp_config.created_accessor}=" do |user| - self.send("#{userstamp_config.created_column}=", Mongoid::Userstamp.extract_bson_id(user)) - end + before_save :set_updated_by - protected + protected - def set_updater - return if !self.class.has_current_user? - self.send("#{userstamp_config.updated_accessor}=", self.class.current_user) - end + def set_created_by + return if !Mongoid::Userstamp.has_current_user? || self.send(Mongoid::Userstamp.config.created_by_name) + self.send("#{Mongoid::Userstamp.config.created_by_name}=", Mongoid::Userstamp.current_user) + end - def set_creator - return if !self.class.has_current_user? || self.send(userstamp_config.created_column) - self.send("#{userstamp_config.created_accessor}=", self.class.current_user) - end + def set_updated_by + return if !Mongoid::Userstamp.has_current_user? + self.send("#{Mongoid::Userstamp.config.updated_by_name}=", Mongoid::Userstamp.current_user) end + end - module ClassMethods - def has_current_user? - userstamp_config.user_model.respond_to?(:current) - end + class << self - def current_user - userstamp_config.user_model.try(:current) + def relation_opts(opts) + opts ||= {} + if Mongoid::Userstamp.config.polymorphic + opts.merge!({polymorphic: Mongoid::Userstamp.config.polymorphic}) + else + opts.merge!({class_name: Mongoid::Userstamp.config.user_configs.first.model}) end + opts end end end end +end diff --git a/lib/mongoid/userstamp/version.rb b/lib/mongoid/userstamp/version.rb index de89086..d428c3a 100644 --- a/lib/mongoid/userstamp/version.rb +++ b/lib/mongoid/userstamp/version.rb @@ -1,6 +1,6 @@ # -*- encoding : utf-8 -*- module Mongoid module Userstamp - VERSION = '0.3.2' + VERSION = '0.4.0' end end diff --git a/mongoid_userstamp.gemspec b/mongoid_userstamp.gemspec index 14b9a3c..350bc1f 100644 --- a/mongoid_userstamp.gemspec +++ b/mongoid_userstamp.gemspec @@ -23,4 +23,5 @@ Gem::Specification.new do |s| s.add_development_dependency 'rspec', '>= 2.13.0' s.add_development_dependency 'yard' s.add_development_dependency 'gem-release' + s.add_development_dependency 'request_store' end diff --git a/spec/integration/config_spec.rb b/spec/integration/config_spec.rb new file mode 100644 index 0000000..f9249f3 --- /dev/null +++ b/spec/integration/config_spec.rb @@ -0,0 +1,205 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe 'Mongoid::Userstamp config' do + + describe '#config' do + before do + Mongoid::Userstamp.config(:test) do |c| + c.user_reader = :test_user + c.user_model = :user + + c.created_column = :c_by + c.created_column_opts = {as: :created_by_id} + c.created_accessor = :created_by + + c.updated_column = :u_by + c.updated_column_opts = {as: :updated_by_id} + c.updated_accessor = :updated_by + end + end + + subject { Mongoid::Userstamp.configs[:test] } + + it { Mongoid::Userstamp.should respond_to :config } + it { Mongoid::Userstamp.configs.should have_key(:test) } + + it { subject.user_reader.should == :test_user } + it { subject.user_model.should == User } + it { subject.created_column.should == :c_by } + it { subject.created_column_opts.should == {as: :created_by_id} } + it { subject.created_accessor.should == :created_by } + it { subject.updated_column.should == :u_by } + it { subject.updated_column_opts.should == {as: :updated_by_id} } + it { subject.updated_accessor.should == :updated_by } + end + + + + + + + + + + + + + + + + + + #subject(:book) { Book.new(name: 'Crafting Rails Applications') } + #subject(:post) { Post.new(title: 'Understanding Rails') } + # + #let(:user_1) { User.create!(name: 'Charles Dikkens') } + #let(:user_2) { User.create!(name: 'Edmund Wells') } + #let(:admin_1) { Admin.create!(name: 'JK Rowling') } + #let(:admin_2) { Admin.create!(name: 'Stephan Norway') } + # + #describe 'configuration' do + # it { Mongoid::Userstamp.timestamped_models.should include(Book) } + # it { Mongoid::Userstamp.timestamped_models.should include(Post) } + # + # context 'when :default' do + # it { Book.userstamp_key.should eq :default } + # it { Book.userstamp_config.should eq Mongoid::Userstamp.configs[:default] } + # + # it { book.should respond_to :created_by } + # it { book.should respond_to :writer } + # it { book.should respond_to :updated_by } + # it { book.should respond_to :editor } + # end + # context 'when :admin' do + # it { Post.userstamp_key.should eq :admin } + # it { Post.userstamp_config.should eq Mongoid::Userstamp.configs[:admin] } + # + # it { post.should respond_to :c_by } + # it { post.should respond_to :creator } + # it { post.should respond_to :u_by } + # it { post.should respond_to :updater } + # end + #end + # + #describe '#current_user' do + # before { Admin.current = nil; User.current = nil } + # subject(:book_user){ Book.current_user } + # subject(:post_user){ Post.current_user } + # + # context 'when current book user is not set' do + # before { User.current = nil } + # it { book_user.should be_nil } + # it { post_user.should be_nil } + # end + # + # context 'when current book user is set' do + # before{ User.current = user_1 } + # it { book_user.should eq user_1 } + # it { post_user.should be_nil } + # end + # + # context 'when current post user is not set' do + # before { Admin.current = nil } + # it { book_user.should be_nil } + # it { post_user.should be_nil } + # end + # + # context 'when current post user is set' do + # before{ Admin.current = admin_1 } + # it { book_user.should be_nil } + # it { post_user.should eq admin_1 } + # end + #end + # + #context 'when created without a user' do + # before do + # Admin.current = admin_1 + # User.current = nil + # book.save! + # end + # + # it { book.created_by.should be_nil } + # it { book.writer.should be_nil } + # it { book.updated_by.should be_nil } + # it { book.editor.should be_nil } + #end + # + #context 'when creator is manually set' do + # before do + # User.current = user_1 + # Admin.current = admin_1 + # end + # + # context 'set by id' do + # before do + # post.c_by = admin_2._id + # post.save! + # end + # + # it 'should not be overridden when saved' do + # post.c_by.should eq admin_2.id + # post.creator.should eq admin_2 + # post.u_by.should eq admin_1.id + # post.updater.should eq admin_1 + # end + # end + # context 'set by model' do + # before do + # post.creator = admin_2 + # post.save! + # end + # + # it 'should not be overridden when saved' do + # post.c_by.should eq admin_2.id + # post.creator.should eq admin_2 + # post.u_by.should eq admin_1.id + # post.updater.should eq admin_1 + # end + # end + #end + # + #context 'when created by a user' do + # before do + # Admin.current = admin_1 + # User.current = user_1 + # book.save! + # end + # + # it { book.created_by.should == user_1.id } + # it { book.writer.should == user_1 } + # it { book.updated_by.should == user_1.id } + # it { book.editor.should == user_1 } + # + # context 'when updated by a user' do + # before do + # User.current = user_2 + # book.save! + # end + # + # it { book.created_by.should == user_1.id } + # it { book.writer.should == user_1 } + # it { book.updated_by.should == user_2.id } + # it { book.editor.should == user_2 } + # end + # + # context 'when user has been destroyed' do + # before do + # User.current = user_2 + # book.save! + # user_1.destroy + # user_2.destroy + # end + # + # it { book.created_by.should == user_1.id } + # it { book.writer.should be_nil } + # it { book.updated_by.should == user_2.id } + # it { book.editor.should be_nil } + # end + #end + # + # + #context 'when using an undefined configuration' do + # it { ->{ Book.send(:mongoid_userstamp, :any_config) }.should raise_error(ConfigurationNotFoundError) } + #end +end \ No newline at end of file diff --git a/spec/integration/controller_spec.rb b/spec/integration/controller_spec.rb new file mode 100644 index 0000000..9e26fc9 --- /dev/null +++ b/spec/integration/controller_spec.rb @@ -0,0 +1,206 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe 'Mongoid::Userstamp config' do + + + + + + + + + + + + + + + + + + + + subject(:book) { Book.new(name: 'Crafting Rails Applications') } + subject(:post) { Post.new(title: 'Understanding Rails') } + + let(:user_1) { User.create!(name: 'Charles Dikkens') } + let(:user_2) { User.create!(name: 'Edmund Wells') } + let(:admin_1) { Admin.create!(name: 'JK Rowling') } + let(:admin_2) { Admin.create!(name: 'Stephan Norway') } + + describe 'configuration' do + it { Mongoid::Userstamp.timestamped_models.should include(Book) } + it { Mongoid::Userstamp.timestamped_models.should include(Post) } + + context 'when :default' do + it { Book.userstamp_key.should eq :default } + it { Book.userstamp_config.should eq Mongoid::Userstamp.configs[:default] } + + it { book.should respond_to :created_by } + it { book.should respond_to :writer } + it { book.should respond_to :updated_by } + it { book.should respond_to :editor } + end + context 'when :admin' do + it { Post.userstamp_key.should eq :admin } + it { Post.userstamp_config.should eq Mongoid::Userstamp.configs[:admin] } + + it { post.should respond_to :c_by } + it { post.should respond_to :creator } + it { post.should respond_to :u_by } + it { post.should respond_to :updater } + end + end + + describe '#current_user' do + before { Admin.current = nil; User.current = nil } + subject(:book_user){ Book.current_user } + subject(:post_user){ Post.current_user } + + context 'when current book user is not set' do + before { User.current = nil } + it { book_user.should be_nil } + it { post_user.should be_nil } + end + + context 'when current book user is set' do + before{ User.current = user_1 } + it { book_user.should eq user_1 } + it { post_user.should be_nil } + end + + context 'when current post user is not set' do + before { Admin.current = nil } + it { book_user.should be_nil } + it { post_user.should be_nil } + end + + context 'when current post user is set' do + before{ Admin.current = admin_1 } + it { book_user.should be_nil } + it { post_user.should eq admin_1 } + end + end + + context 'when created without a user' do + before do + Admin.current = admin_1 + User.current = nil + book.save! + end + + it { book.created_by.should be_nil } + it { book.writer.should be_nil } + it { book.updated_by.should be_nil } + it { book.editor.should be_nil } + end + + context 'when creator is manually set' do + before do + User.current = user_1 + Admin.current = admin_1 + end + + context 'set by id' do + before do + post.c_by = admin_2._id + post.save! + end + + it 'should not be overridden when saved' do + post.c_by.should eq admin_2.id + post.creator.should eq admin_2 + post.u_by.should eq admin_1.id + post.updater.should eq admin_1 + end + end + context 'set by model' do + before do + post.creator = admin_2 + post.save! + end + + it 'should not be overridden when saved' do + post.c_by.should eq admin_2.id + post.creator.should eq admin_2 + post.u_by.should eq admin_1.id + post.updater.should eq admin_1 + end + end + end + + context 'when created by a user' do + before do + Admin.current = admin_1 + User.current = user_1 + book.save! + end + + it { book.created_by.should == user_1.id } + it { book.writer.should == user_1 } + it { book.updated_by.should == user_1.id } + it { book.editor.should == user_1 } + + context 'when updated by a user' do + before do + User.current = user_2 + book.save! + end + + it { book.created_by.should == user_1.id } + it { book.writer.should == user_1 } + it { book.updated_by.should == user_2.id } + it { book.editor.should == user_2 } + end + + context 'when user has been destroyed' do + before do + User.current = user_2 + book.save! + user_1.destroy + user_2.destroy + end + + it { book.created_by.should == user_1.id } + it { book.writer.should be_nil } + it { book.updated_by.should == user_2.id } + it { book.editor.should be_nil } + end + end + + describe '#config' do + before do + Mongoid::Userstamp.config(:test) do |c| + c.user_reader = :test_user + c.user_model = :user + + c.created_column = :c_by + c.created_column_opts = {as: :created_by_id} + c.created_accessor = :created_by + + c.updated_column = :u_by + c.updated_column_opts = {as: :updated_by_id} + c.updated_accessor = :updated_by + end + end + + subject { Mongoid::Userstamp.configs[:test] } + + it { Mongoid::Userstamp.should respond_to :config } + it { Mongoid::Userstamp.configs.should have_key(:test) } + + it { subject.user_reader.should == :test_user } + it { subject.user_model.should == User } + it { subject.created_column.should == :c_by } + it { subject.created_column_opts.should == {as: :created_by_id} } + it { subject.created_accessor.should == :created_by } + it { subject.updated_column.should == :u_by } + it { subject.updated_column_opts.should == {as: :updated_by_id} } + it { subject.updated_accessor.should == :updated_by } + end + + context 'when using an undefined configuration' do + it { ->{ Book.send(:mongoid_userstamp, :any_config) }.should raise_error(ConfigurationNotFoundError) } + end +end \ No newline at end of file diff --git a/spec/mongoid/userstamp_spec.rb b/spec/integration/userstamp_spec.rb similarity index 100% rename from spec/mongoid/userstamp_spec.rb rename to spec/integration/userstamp_spec.rb diff --git a/spec/unit/app_config_spec.rb b/spec/unit/app_config_spec.rb new file mode 100644 index 0000000..a24728d --- /dev/null +++ b/spec/unit/app_config_spec.rb @@ -0,0 +1,28 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Mongoid::Userstamp::Config::AppConfig do + + subject { Mongoid::Userstamp::Config::AppConfig.new } + + describe '#initialize' do + + context 'without block' do + its(:model) { should eq :user } + its(:reader){ should eq :current_user } + end + + context 'with block' do + + subject do + Mongoid::Userstamp::Config::UserConfig.new do |u| + u.model = :custom_user + u.reader = :custom_current_user + end + end + + its(:model) { should eq :custom_user } + its(:reader){ should eq :custom_current_user } + end + end +end diff --git a/spec/unit/user_config_spec.rb b/spec/unit/user_config_spec.rb new file mode 100644 index 0000000..bb30fc7 --- /dev/null +++ b/spec/unit/user_config_spec.rb @@ -0,0 +1,45 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Mongoid::Userstamp::Config::UserConfig do + + subject { Mongoid::Userstamp::Config::UserConfig.new } + + describe '#initialize' do + + context 'without block' do + its(:model) { should eq :user } + its(:reader){ should eq :current_user } + end + + context 'with block' do + subject do + Mongoid::Userstamp::Config::UserConfig.new do |u| + u.model = :custom_user + u.reader = :custom_current_user + end + end + its(:model) { should eq :custom_user } + its(:reader){ should eq :custom_current_user } + end + end + + describe '#initialize' do + + context 'without block' do + its(:model) { should eq :user } + its(:reader){ should eq :current_user } + end + + context 'with block' do + subject do + Mongoid::Userstamp::Config::UserConfig.new do |u| + u.model = :custom_user + u.reader = :custom_current_user + end + end + its(:model) { should eq :custom_user } + its(:reader){ should eq :custom_current_user } + end + end +end From 600768c74337eff9b0d447dd609e645bce78cf34 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Mon, 24 Feb 2014 01:13:15 +0900 Subject: [PATCH 11/19] Add multi-user support --- CHANGELOG.md | 16 +- README.md | 108 +++++----- lib/mongoid/userstamp.rb | 70 ++++++- lib/mongoid/userstamp/config/app_config.rb | 62 ++---- lib/mongoid/userstamp/config/model_config.rb | 27 +++ lib/mongoid/userstamp/config/user_config.rb | 18 +- lib/mongoid/userstamp/configurable.rb | 19 -- lib/mongoid/userstamp/controller.rb | 67 ------ lib/mongoid/userstamp/mixins/model.rb | 41 ++++ lib/mongoid/userstamp/{ => mixins}/user.rb | 12 +- lib/mongoid/userstamp/railtie.rb | 38 +++- lib/mongoid/userstamp/userstampable.rb | 49 ----- lib/mongoid/userstamp/version.rb | 1 + lib/mongoid_userstamp.rb | 10 +- spec/integration/config_spec.rb | 205 ------------------ spec/integration/controller_spec.rb | 206 ------------------- spec/integration/userstamp_spec.rb | 187 ----------------- spec/spec_helper.rb | 7 +- spec/support/book.rb | 2 +- spec/support/config.rb | 12 -- spec/support/post.rb | 4 +- spec/unit/app_config_spec.rb | 38 +++- spec/unit/model_config_spec.rb | 31 +++ spec/unit/model_spec.rb | 120 +++++++++++ spec/unit/user_config_spec.rb | 42 +--- spec/unit/user_spec.rb | 76 +++++++ spec/unit/userstamp_spec.rb | 120 +++++++++++ 27 files changed, 663 insertions(+), 925 deletions(-) create mode 100644 lib/mongoid/userstamp/config/model_config.rb delete mode 100644 lib/mongoid/userstamp/configurable.rb delete mode 100644 lib/mongoid/userstamp/controller.rb create mode 100644 lib/mongoid/userstamp/mixins/model.rb rename lib/mongoid/userstamp/{ => mixins}/user.rb (68%) delete mode 100644 lib/mongoid/userstamp/userstampable.rb delete mode 100644 spec/integration/config_spec.rb delete mode 100644 spec/integration/controller_spec.rb delete mode 100644 spec/integration/userstamp_spec.rb delete mode 100644 spec/support/config.rb create mode 100644 spec/unit/model_config_spec.rb create mode 100644 spec/unit/model_spec.rb create mode 100644 spec/unit/user_spec.rb create mode 100644 spec/unit/userstamp_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 2441c8b..0fc7904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,18 @@ # Changelog -## [0.4.0](https://github.com/tbpro/mongoid_userstamp/releases/tag/v0.4.0) - 2014-02-20 +## [0.4.0](https://github.com/tbpro/mongoid_userstamp/releases/tag/v0.4.0) - 2014-02-24 -* BREAKING: Change userstamp keys to use Mongoid relations. Requires database migration. -* Add support for multiple user classes via polymorphic userstamps. -* Refactor to extract `Controller` and `Configurable` modules +* Improvement + * BREAKING: Change userstamp keys to use Mongoid relations. This will change the underlying database field names, and as such will require a migration. + * Mongoid::Userstamp config initializer is now optional. + * Add support for multiple user classes. + * Add class-level config override capability for both users and userstamped model classes. + * Add automatic support for `RequestStore` gem as drop-in replacement for `Thread.current` +* Refactor + * DEPRECATION: `created_column` config is now `created_name` + * DEPRECATION: `created_updated` config is now `created_updated` + * DEPRECATION: `user_model` config is no longer used. Instead, include Mongoid::Userstamp::User in your user model. + * Substantial refactoring of all classes and test cases. Among other changes, all access to `Thread.current` variables is now done in the Mongoid::Userstamp module singleton. ## [0.3.2](https://github.com/tbpro/mongoid_userstamp/releases/tag/v0.3.2) - 2014-01-12 diff --git a/README.md b/README.md index ae60c92..4dfdb7c 100644 --- a/README.md +++ b/README.md @@ -29,19 +29,30 @@ Mongoid::Userstamp does the following: # Default config (optional unless you want to customize the values) Mongoid::Userstamp.config do |c| c.user_reader = :current_user - c.user_model = :user - c.created_by_name = :created_by - c.updated_by_name = :updated_by - c.polymorphic = false - c.use_request_store = false + c.created_name = :created_by + c.updated_name = :updated_by end - # Example model + # Example model class class Product include Mongoid::Document include Mongoid::Userstamp + + # optional class-level config override + # mongoid_userstamp user_model: 'MyUser', + # created_name: :creator, + # updated_name: :updater, end + # Example user class (you can skip this step you have a single user class is named "User") + class MyUser + include Mongoid::Document + include Mongoid::Userstamp::User + + # optional class-level config override + # mongoid_userstamp_user reader: :current_my_user + end + # Create instance p = Product.create @@ -54,8 +65,8 @@ Mongoid::Userstamp does the following: # => # Set creator/updater manually (usually not required) - p.created_by = User.where(name: 'Will Smith') - p.updated_by = User.where(name: 'DJ Jazzy Jeff') + p.created_by = MyUser.where(name: 'Will Smith') + p.updated_by = MyUser.where(name: 'DJ Jazzy Jeff') ``` @@ -66,69 +77,66 @@ your Controllers. Mongoid::Userstamp will automatically use this to set its user on each request. (You can set an alternative method name via the `user_reader` config.) *Gotcha:* If you have special controller actions which change/switch the current user to a new user, you will -need to set `Mongoid::Userstamp.current_user = new_user` after the switch occurs. +need to set `User.current = new_user` after the switch occurs. ## Thread Safety -By default, Mongoid::Userstamp stores all-related user variables in `Thread.current`. This may cause -erratic behavior on threaded web servers like Thin or Puma. Fortunately you can use the -[RequestStore](https://github.com/steveklabnik/request_store) gem as workaround by installing the gem and -setting `use_request_store = true` in your config. +By default, Mongoid::Userstamp stores all-related user variables in `Thread.current`. +If the [RequestStore](https://github.com/steveklabnik/request_store) gem is installed, Mongoid::Userstamp +will automatically store variables in the `RequestStore.store` instead. RequestStore is recommended +for threaded web servers like Thin or Puma. -## Advanced Usage: Polymorphic Userstamps +## Advanced Usage: Multiple User Classes -In general, most Rails apps use a single user model. However, if you would like to use -Mongoid::Userstamp will track a separate current_user for each class. +Most Rails apps use a single user model. However, Mongoid::Userstamp supports using multiple user models +at once, and will track a separate current_user for each class. -Please be aware of the following limitations of this approach: -* Enabling `use_polymorphic = true` will make every userstamped class in your application -to be polymorphic. -* You will have to manually add the `created_by_type` and `updated_by_type` fields -if you were not using them previously. -* Although multiple user classes may be logged in at once, the userstamp contains only one value by design. -The assumption is that there is only one actual user/person who does the given create/update action. +Please note that each model may subscribe to only one user type for its userstamps, set via the +`:user_model` option. ```ruby - # Example config for polymorphism - Mongoid::Userstamp.config do |c| - c.polymorphic = true + class Admin + include Mongoid::Document + include Mongoid::Userstamp::User - c.user_config do |u| - u.model = :merchant_user - u.reader = :current_merchant_user - end + mongoid_userstamp_user reader: :current_admin + end + + class Customer + include Mongoid::Document + include Mongoid::Userstamp::User - c.user_config do |u| - u.model = :customer_user - u.reader = :current_customer_user - end + mongoid_userstamp_user reader: :current_customer end - # Example model (same as non-polymorphic case) - class Product + class Album include Mongoid::Document include Mongoid::Userstamp + + mongoid_userstamp user_model: 'Customer' + end + + class Label + include Mongoid::Document + include Mongoid::Userstamp + + mongoid_userstamp user_model: 'Admin' end # Set current user for each type - Mongoid::Userstamp.current_user = CustomerUser.where(name: 'Sir Mix-A-Lot') - Mongoid::Userstamp.current_user = MerchantUser.where(name: 'Biz Markie') + Admin.current = Admin.where(name: 'Biz Markie') + Customer.current = Customer.where(name: 'Sir Mix-A-Lot') # In your Controller action - product = Product.new('Baby Got Back Single') - Mongoid::Userstamp.user_class = 'customer_user' - product.save! - product.updated_by.name #=> 'Sir Mix-A-Lot' - product.updated_by_type #=> 'CustomerUser' - - # Alternative block syntax - Mongoid::Userstamp.with_user_class('merchant_user') do - product.save! - product.updated_by.name #=> 'Biz Markie' - product.updated_by_type #=> 'MerchantUser' - end + album = Album.new('Baby Got Back Single') + album.save! + album.created_by.name #=> 'Sir Mix-A-Lot' + + label = Label.new('Cold Chillin Records') + label.save! + label.created_by.name #=> 'Biz Markie' ``` ## Contributing diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index 14250fe..fbb84b1 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -1,14 +1,78 @@ # -*- encoding : utf-8 -*- module Mongoid + module Userstamp extend ActiveSupport::Concern - include Mongoid::Userstamp::Userstampable + included do + Mongoid::Userstamp.add_model_class(self) + end + + module ClassMethods + + def mongoid_userstamp(opts = {}) + mongoid_userstamp_config(opts) + self.send(:include, Mongoid::Userstamp::Model) + end + + def mongoid_userstamp_config(opts = {}) + @mongoid_userstamp_config ||= Mongoid::Userstamp::ModelConfig.new(opts) + end + end class << self - include Mongoid::Userstamp::Configurable - include Mongoid::Userstamp::Controller + + def config(&block) + @config ||= Mongoid::Userstamp::AppConfig.new(&block) + end + + # @deprecated + def configure(&block) + warn 'Mongoid::Userstamp.configure is deprecated. Please use Mongoid::Userstamp.config instead' + config(&block) + end + + def current_user(user_class = nil) + user_class ||= user_classes.first + store[userstamp_key(user_class)] + end + + def current_user=(value) + set_current_user(value) + end + + # It is better to provide the user class, in case the value is nil. + def set_current_user(value, user_class = nil) + user_class ||= value ? value.class : user_classes.first + store[userstamp_key(user_class)] = value + end + + def model_classes + (@model_classes || []).map{|c| c.is_a?(Class) ? c : c.to_s.constantize } + end + + def add_model_class(model) + @model_classes ||= [] + @model_classes << model + end + + def user_classes + (@user_classes || ['User']).map{|c| c.is_a?(Class) ? c : c.to_s.constantize } + end + + def add_user_class(user) + @user_classes ||= [] + @user_classes << user + end + + def userstamp_key(model) + "mongoid_userstamp/#{model.to_s.underscore}".to_sym + end + + def store + defined?(RequestStore) ? RequestStore.store : Thread.current + end end end end diff --git a/lib/mongoid/userstamp/config/app_config.rb b/lib/mongoid/userstamp/config/app_config.rb index 7a6c579..9bd4966 100644 --- a/lib/mongoid/userstamp/config/app_config.rb +++ b/lib/mongoid/userstamp/config/app_config.rb @@ -1,70 +1,38 @@ # -*- encoding : utf-8 -*- + module Mongoid module Userstamp -module Config - - module AppConfig - attr_accessor :created_by_name - attr_reader :created_by_opts - attr_accessor :updated_by_name - attr_reader :updated_by_opts - attr_reader :use_request_store - attr_reader :user_configs + class AppConfig + attr_accessor :created_name + attr_accessor :updated_name + attr_accessor :user_reader def initialize(&block) - - # intialize members - @created_by_name = :created_by - @updated_by_name = :updated_by - @use_request_store = false + @created_name = :created_by + @updated_name = :updated_by + @user_reader = :current_user instance_eval(&block) if block_given? - - # initialize user config - user_config - @user_config_set = false - - end - - def use_request_store=(value) - @use_request_store = !!value - end - - def user_config(&block) - @user_configs = [] unless @user_config_set - @user_configs << Mongoid::Userstamp::Config::UserConfig.new(&block) - @user_config_set = true - end - - def user_model(value) - @user_configs.first.model = value end - def user_reader(value) - @user_configs.first.reader = value + # @deprecated + def user_model=(value) + warn 'Mongoid::Userstamp `user_model` config is removed as of v0.4.0. If using a model named other than `User`, please include `Mongoid::Userstamp::User` in your user model instead.' end # @deprecated def created_column=(value) - warn 'Mongoid::Userstamp `created_column` is deprecated as of v0.4.0. Please use `created_by_name` instead.' - created_by_name = value + warn 'Mongoid::Userstamp `created_column` is deprecated as of v0.4.0. Please use `created_name` instead.' + @created_name = value end # @deprecated def updated_column=(value) - warn 'Mongoid::Userstamp `created_column` is deprecated as of v0.4.0. Please use `created_by_name` instead.' - updated_by_name = value + warn 'Mongoid::Userstamp `created_column` is deprecated as of v0.4.0. Please use `created_name` instead.' + @updated_name = value end end end end -end - - -# c.user_model = :'vesper/beauty/merchant_user' -# c.user_reader = :current_bs_merchant_user - -# c.user_model = :'table_solution/merchant_user' -# c.user_reader = :current_merchant_user diff --git a/lib/mongoid/userstamp/config/model_config.rb b/lib/mongoid/userstamp/config/model_config.rb new file mode 100644 index 0000000..2802e88 --- /dev/null +++ b/lib/mongoid/userstamp/config/model_config.rb @@ -0,0 +1,27 @@ +# -*- encoding : utf-8 -*- + +module Mongoid +module Userstamp + + class ModelConfig + + def initialize(opts = {}) + @user_model = opts.delete(:user_model) + @created_name = opts.delete(:created_name) + @updated_name = opts.delete(:updated_name) + end + + def user_model + @user_model || Mongoid::Userstamp.user_classes.first + end + + def created_name + @created_name || Mongoid::Userstamp.config.created_name + end + + def updated_name + @updated_name || Mongoid::Userstamp.config.updated_name + end + end +end +end diff --git a/lib/mongoid/userstamp/config/user_config.rb b/lib/mongoid/userstamp/config/user_config.rb index 38047d8..5554a58 100644 --- a/lib/mongoid/userstamp/config/user_config.rb +++ b/lib/mongoid/userstamp/config/user_config.rb @@ -1,23 +1,17 @@ # -*- encoding : utf-8 -*- + module Mongoid module Userstamp -module Config - - module UserConfig - attr_writer :model - attr_accessor :reader + class UserConfig - def initialize(&block) - @model = :user - @reader = :current_user - instance_eval(&block) if block_given? + def initialize(opts = {}) + @reader = opts.delete(:reader) end - def model - @model.to_s.classify.constantize + def reader + @reader || Mongoid::Userstamp.config.user_reader end end end end -end diff --git a/lib/mongoid/userstamp/configurable.rb b/lib/mongoid/userstamp/configurable.rb deleted file mode 100644 index d4bccae..0000000 --- a/lib/mongoid/userstamp/configurable.rb +++ /dev/null @@ -1,19 +0,0 @@ -# -*- encoding : utf-8 -*- - -module Mongoid -module Userstamp - - module Configurable - - def config(&block) - @config ||= Mongoid::Userstamp::Config::AppConfig.new(&block) - end - - # @deprecated - def configure(&block) - warn 'Mongoid::Userstamp.configure is deprecated. Please use Mongoid::Userstamp.config instead' - config(&block) - end - end -end -end diff --git a/lib/mongoid/userstamp/controller.rb b/lib/mongoid/userstamp/controller.rb deleted file mode 100644 index a0c4069..0000000 --- a/lib/mongoid/userstamp/controller.rb +++ /dev/null @@ -1,67 +0,0 @@ -# -*- encoding : utf-8 -*- - -module Mongoid -module Userstamp - - module Controller - - #THREAD_DOMAIN = 'mongoid_userstamp/' - - def userstamp_key(model) - # need to map default here - "mongoid_userstamp/#{model.to_s.underscore}".to_sym - end - - def has_current_user?(model = nil) - current_user.present - end - - def current_user(model = nil) - model ||= user_class - store[userstamp_key(model)] - end - - def current_user=(value) - store[userstamp_key(value.class)] = value - end - - def user_model - if Mongoid::Userstamp.config.polymorphic - store['mongoid_userstamp/user_class'] || :default - else - :default - end - end - - def user_model=(klass) - store['mongoid_userstamp/user_class'] = klass - end - - def user_class - case user_model - when :default, 'default' - Mongoid::Userstamp.config.user_configs.first.model.to_s.classify.constantize - when Class - user_model - when Symbol, String - user_class.classify.constantize - end - end - - def store - Mongoid::Userstamp.config.use_request_store ? RequestStore.store : Thread.current - end - - def with_user_class(klass, &block) - old_klass = user_class - begin - user_class = klass - response = block.call unless block.nil? - ensure - user_class = old_klass - end - response - end - end -end -end diff --git a/lib/mongoid/userstamp/mixins/model.rb b/lib/mongoid/userstamp/mixins/model.rb new file mode 100644 index 0000000..3e6493f --- /dev/null +++ b/lib/mongoid/userstamp/mixins/model.rb @@ -0,0 +1,41 @@ +# -*- encoding : utf-8 -*- + +module Mongoid +module Userstamp + + module Model + + extend ActiveSupport::Concern + + included do + + belongs_to mongoid_userstamp_config.created_name, class_name: mongoid_userstamp_config.user_model + belongs_to mongoid_userstamp_config.updated_name, class_name: mongoid_userstamp_config.user_model + + before_create :set_created_by + before_save :set_updated_by + + protected + + def set_created_by + current_user = Mongoid::Userstamp.current_user(self.class.mongoid_userstamp_config.user_model) + return if current_user.blank? || self.send(self.class.mongoid_userstamp_config.created_name) + self.send("#{self.class.mongoid_userstamp_config.created_name}=", current_user) + end + + def set_updated_by + current_user = Mongoid::Userstamp.current_user(self.class.mongoid_userstamp_config.user_model) + return if current_user.blank? + self.send("#{self.class.mongoid_userstamp_config.updated_name}=", current_user) + end + end + + module ClassMethods + + def current_user + Mongoid::Userstamp.current_user(mongoid_userstamp_config.user_model) + end + end + end +end +end diff --git a/lib/mongoid/userstamp/user.rb b/lib/mongoid/userstamp/mixins/user.rb similarity index 68% rename from lib/mongoid/userstamp/user.rb rename to lib/mongoid/userstamp/mixins/user.rb index ffdc919..31cd519 100644 --- a/lib/mongoid/userstamp/user.rb +++ b/lib/mongoid/userstamp/mixins/user.rb @@ -1,4 +1,5 @@ # -*- encoding : utf-8 -*- + module Mongoid module Userstamp @@ -8,6 +9,8 @@ module User included do + Mongoid::Userstamp.add_user_class(self) + def current? self._id == Mongoid::Userstamp.current_user(self.class).try(:_id) end @@ -20,7 +23,7 @@ def current end def current=(value) - Mongoid::Userstamp.current_user = value + Mongoid::Userstamp.set_current_user(value, self) end def do_as(user, &block) @@ -33,6 +36,13 @@ def do_as(user, &block) end response end + + module ClassMethods + + def mongoid_userstamp_user(opts = {}) + @mongoid_userstamp_user ||= Mongoid::Userstamp::UserConfig.new(opts = {}) + end + end end end end diff --git a/lib/mongoid/userstamp/railtie.rb b/lib/mongoid/userstamp/railtie.rb index 3810c32..540ec37 100644 --- a/lib/mongoid/userstamp/railtie.rb +++ b/lib/mongoid/userstamp/railtie.rb @@ -1,22 +1,38 @@ # -*- encoding : utf-8 -*- + module Mongoid module Userstamp class Railtie < Rails::Railtie - ActiveSupport.on_load :action_controller do - - before_filter do |c| + # Include Mongoid::Userstamp::User into User class, if not already done + initializer 'mongoid_userstamp.setup_user_classes' do |app| + Mongoid::Userstamp.user_classes.each do |user_class| + unless user_class.included_modules.include?(Mongoid::Userstamp::User) + user_class.send(:include, Mongoid::Userstamp::User) + end + end + end - Mongoid::Userstamp.config.user_configs.each do |user_config| - unless user_config.user_class.respond_to? :current - user_config.user_class.send(:include, Mongoid::Userstamp::User) - end + # Add userstamp to models where Mongoid::Userstamp was included, but + # mongoid_userstamp was not explicitly called + initializer 'mongoid_userstamp.setup_model_classes' do |app| + Mongoid::Userstamp.model_classes.each do |model_class| + unless model_class.included_modules.include?(Mongoid::Userstamp::Model) + model_class.send(:include, Mongoid::Userstamp::Model) + end + end + end - # TODO FIX THIS - begin - user_config.user_class.user_model.current = c.send(user_config.reader) - rescue + # Set current_user from controller reader method + initializer 'mongoid_userstamp.setup_current_user_before_filter' do |app| + ActiveSupport.on_load :action_controller do + before_filter do |c| + Mongoid::Userstamp.user_classes.each do |user_class| + begin + user_class.current = c.send(user_class.mongoid_userstamp_user.reader) + rescue + end end end end diff --git a/lib/mongoid/userstamp/userstampable.rb b/lib/mongoid/userstamp/userstampable.rb deleted file mode 100644 index c5456d2..0000000 --- a/lib/mongoid/userstamp/userstampable.rb +++ /dev/null @@ -1,49 +0,0 @@ -# -*- encoding : utf-8 -*- - -module Mongoid -module Userstamp - - module Userstampable - - extend ActiveSupport::Concern - - included do - - belongs_to Mongoid::Userstamp.config.created_by_name, - Mongoid::Userstamp::Userstampable.relation_opts(Mongoid::Userstamp.config.updated_column_opts) - - belongs_to Mongoid::Userstamp.config.updated_by_name, - Mongoid::Userstamp::Userstampable.relation_opts(Mongoid::Userstamp.config.updated_column_opts) - - before_create :set_created_by - - before_save :set_updated_by - - protected - - def set_created_by - return if !Mongoid::Userstamp.has_current_user? || self.send(Mongoid::Userstamp.config.created_by_name) - self.send("#{Mongoid::Userstamp.config.created_by_name}=", Mongoid::Userstamp.current_user) - end - - def set_updated_by - return if !Mongoid::Userstamp.has_current_user? - self.send("#{Mongoid::Userstamp.config.updated_by_name}=", Mongoid::Userstamp.current_user) - end - end - - class << self - - def relation_opts(opts) - opts ||= {} - if Mongoid::Userstamp.config.polymorphic - opts.merge!({polymorphic: Mongoid::Userstamp.config.polymorphic}) - else - opts.merge!({class_name: Mongoid::Userstamp.config.user_configs.first.model}) - end - opts - end - end - end -end -end diff --git a/lib/mongoid/userstamp/version.rb b/lib/mongoid/userstamp/version.rb index d428c3a..67dbdd5 100644 --- a/lib/mongoid/userstamp/version.rb +++ b/lib/mongoid/userstamp/version.rb @@ -1,4 +1,5 @@ # -*- encoding : utf-8 -*- + module Mongoid module Userstamp VERSION = '0.4.0' diff --git a/lib/mongoid_userstamp.rb b/lib/mongoid_userstamp.rb index d61c020..9b80a11 100644 --- a/lib/mongoid_userstamp.rb +++ b/lib/mongoid_userstamp.rb @@ -1,8 +1,10 @@ # -*- encoding : utf-8 -*- + require 'mongoid/userstamp' require 'mongoid/userstamp/version' -require 'mongoid/userstamp/config' -require 'mongoid/userstamp/error' -require 'mongoid/userstamp/user' -require 'mongoid/userstamp/userstampable' +require 'mongoid/userstamp/config/app_config' +require 'mongoid/userstamp/config/model_config' +require 'mongoid/userstamp/config/user_config' +require 'mongoid/userstamp/mixins/user' +require 'mongoid/userstamp/mixins/model' require 'mongoid/userstamp/railtie' if defined? Rails diff --git a/spec/integration/config_spec.rb b/spec/integration/config_spec.rb deleted file mode 100644 index f9249f3..0000000 --- a/spec/integration/config_spec.rb +++ /dev/null @@ -1,205 +0,0 @@ -# -*- encoding : utf-8 -*- -require 'spec_helper' - -describe 'Mongoid::Userstamp config' do - - describe '#config' do - before do - Mongoid::Userstamp.config(:test) do |c| - c.user_reader = :test_user - c.user_model = :user - - c.created_column = :c_by - c.created_column_opts = {as: :created_by_id} - c.created_accessor = :created_by - - c.updated_column = :u_by - c.updated_column_opts = {as: :updated_by_id} - c.updated_accessor = :updated_by - end - end - - subject { Mongoid::Userstamp.configs[:test] } - - it { Mongoid::Userstamp.should respond_to :config } - it { Mongoid::Userstamp.configs.should have_key(:test) } - - it { subject.user_reader.should == :test_user } - it { subject.user_model.should == User } - it { subject.created_column.should == :c_by } - it { subject.created_column_opts.should == {as: :created_by_id} } - it { subject.created_accessor.should == :created_by } - it { subject.updated_column.should == :u_by } - it { subject.updated_column_opts.should == {as: :updated_by_id} } - it { subject.updated_accessor.should == :updated_by } - end - - - - - - - - - - - - - - - - - - #subject(:book) { Book.new(name: 'Crafting Rails Applications') } - #subject(:post) { Post.new(title: 'Understanding Rails') } - # - #let(:user_1) { User.create!(name: 'Charles Dikkens') } - #let(:user_2) { User.create!(name: 'Edmund Wells') } - #let(:admin_1) { Admin.create!(name: 'JK Rowling') } - #let(:admin_2) { Admin.create!(name: 'Stephan Norway') } - # - #describe 'configuration' do - # it { Mongoid::Userstamp.timestamped_models.should include(Book) } - # it { Mongoid::Userstamp.timestamped_models.should include(Post) } - # - # context 'when :default' do - # it { Book.userstamp_key.should eq :default } - # it { Book.userstamp_config.should eq Mongoid::Userstamp.configs[:default] } - # - # it { book.should respond_to :created_by } - # it { book.should respond_to :writer } - # it { book.should respond_to :updated_by } - # it { book.should respond_to :editor } - # end - # context 'when :admin' do - # it { Post.userstamp_key.should eq :admin } - # it { Post.userstamp_config.should eq Mongoid::Userstamp.configs[:admin] } - # - # it { post.should respond_to :c_by } - # it { post.should respond_to :creator } - # it { post.should respond_to :u_by } - # it { post.should respond_to :updater } - # end - #end - # - #describe '#current_user' do - # before { Admin.current = nil; User.current = nil } - # subject(:book_user){ Book.current_user } - # subject(:post_user){ Post.current_user } - # - # context 'when current book user is not set' do - # before { User.current = nil } - # it { book_user.should be_nil } - # it { post_user.should be_nil } - # end - # - # context 'when current book user is set' do - # before{ User.current = user_1 } - # it { book_user.should eq user_1 } - # it { post_user.should be_nil } - # end - # - # context 'when current post user is not set' do - # before { Admin.current = nil } - # it { book_user.should be_nil } - # it { post_user.should be_nil } - # end - # - # context 'when current post user is set' do - # before{ Admin.current = admin_1 } - # it { book_user.should be_nil } - # it { post_user.should eq admin_1 } - # end - #end - # - #context 'when created without a user' do - # before do - # Admin.current = admin_1 - # User.current = nil - # book.save! - # end - # - # it { book.created_by.should be_nil } - # it { book.writer.should be_nil } - # it { book.updated_by.should be_nil } - # it { book.editor.should be_nil } - #end - # - #context 'when creator is manually set' do - # before do - # User.current = user_1 - # Admin.current = admin_1 - # end - # - # context 'set by id' do - # before do - # post.c_by = admin_2._id - # post.save! - # end - # - # it 'should not be overridden when saved' do - # post.c_by.should eq admin_2.id - # post.creator.should eq admin_2 - # post.u_by.should eq admin_1.id - # post.updater.should eq admin_1 - # end - # end - # context 'set by model' do - # before do - # post.creator = admin_2 - # post.save! - # end - # - # it 'should not be overridden when saved' do - # post.c_by.should eq admin_2.id - # post.creator.should eq admin_2 - # post.u_by.should eq admin_1.id - # post.updater.should eq admin_1 - # end - # end - #end - # - #context 'when created by a user' do - # before do - # Admin.current = admin_1 - # User.current = user_1 - # book.save! - # end - # - # it { book.created_by.should == user_1.id } - # it { book.writer.should == user_1 } - # it { book.updated_by.should == user_1.id } - # it { book.editor.should == user_1 } - # - # context 'when updated by a user' do - # before do - # User.current = user_2 - # book.save! - # end - # - # it { book.created_by.should == user_1.id } - # it { book.writer.should == user_1 } - # it { book.updated_by.should == user_2.id } - # it { book.editor.should == user_2 } - # end - # - # context 'when user has been destroyed' do - # before do - # User.current = user_2 - # book.save! - # user_1.destroy - # user_2.destroy - # end - # - # it { book.created_by.should == user_1.id } - # it { book.writer.should be_nil } - # it { book.updated_by.should == user_2.id } - # it { book.editor.should be_nil } - # end - #end - # - # - #context 'when using an undefined configuration' do - # it { ->{ Book.send(:mongoid_userstamp, :any_config) }.should raise_error(ConfigurationNotFoundError) } - #end -end \ No newline at end of file diff --git a/spec/integration/controller_spec.rb b/spec/integration/controller_spec.rb deleted file mode 100644 index 9e26fc9..0000000 --- a/spec/integration/controller_spec.rb +++ /dev/null @@ -1,206 +0,0 @@ -# -*- encoding : utf-8 -*- -require 'spec_helper' - -describe 'Mongoid::Userstamp config' do - - - - - - - - - - - - - - - - - - - - subject(:book) { Book.new(name: 'Crafting Rails Applications') } - subject(:post) { Post.new(title: 'Understanding Rails') } - - let(:user_1) { User.create!(name: 'Charles Dikkens') } - let(:user_2) { User.create!(name: 'Edmund Wells') } - let(:admin_1) { Admin.create!(name: 'JK Rowling') } - let(:admin_2) { Admin.create!(name: 'Stephan Norway') } - - describe 'configuration' do - it { Mongoid::Userstamp.timestamped_models.should include(Book) } - it { Mongoid::Userstamp.timestamped_models.should include(Post) } - - context 'when :default' do - it { Book.userstamp_key.should eq :default } - it { Book.userstamp_config.should eq Mongoid::Userstamp.configs[:default] } - - it { book.should respond_to :created_by } - it { book.should respond_to :writer } - it { book.should respond_to :updated_by } - it { book.should respond_to :editor } - end - context 'when :admin' do - it { Post.userstamp_key.should eq :admin } - it { Post.userstamp_config.should eq Mongoid::Userstamp.configs[:admin] } - - it { post.should respond_to :c_by } - it { post.should respond_to :creator } - it { post.should respond_to :u_by } - it { post.should respond_to :updater } - end - end - - describe '#current_user' do - before { Admin.current = nil; User.current = nil } - subject(:book_user){ Book.current_user } - subject(:post_user){ Post.current_user } - - context 'when current book user is not set' do - before { User.current = nil } - it { book_user.should be_nil } - it { post_user.should be_nil } - end - - context 'when current book user is set' do - before{ User.current = user_1 } - it { book_user.should eq user_1 } - it { post_user.should be_nil } - end - - context 'when current post user is not set' do - before { Admin.current = nil } - it { book_user.should be_nil } - it { post_user.should be_nil } - end - - context 'when current post user is set' do - before{ Admin.current = admin_1 } - it { book_user.should be_nil } - it { post_user.should eq admin_1 } - end - end - - context 'when created without a user' do - before do - Admin.current = admin_1 - User.current = nil - book.save! - end - - it { book.created_by.should be_nil } - it { book.writer.should be_nil } - it { book.updated_by.should be_nil } - it { book.editor.should be_nil } - end - - context 'when creator is manually set' do - before do - User.current = user_1 - Admin.current = admin_1 - end - - context 'set by id' do - before do - post.c_by = admin_2._id - post.save! - end - - it 'should not be overridden when saved' do - post.c_by.should eq admin_2.id - post.creator.should eq admin_2 - post.u_by.should eq admin_1.id - post.updater.should eq admin_1 - end - end - context 'set by model' do - before do - post.creator = admin_2 - post.save! - end - - it 'should not be overridden when saved' do - post.c_by.should eq admin_2.id - post.creator.should eq admin_2 - post.u_by.should eq admin_1.id - post.updater.should eq admin_1 - end - end - end - - context 'when created by a user' do - before do - Admin.current = admin_1 - User.current = user_1 - book.save! - end - - it { book.created_by.should == user_1.id } - it { book.writer.should == user_1 } - it { book.updated_by.should == user_1.id } - it { book.editor.should == user_1 } - - context 'when updated by a user' do - before do - User.current = user_2 - book.save! - end - - it { book.created_by.should == user_1.id } - it { book.writer.should == user_1 } - it { book.updated_by.should == user_2.id } - it { book.editor.should == user_2 } - end - - context 'when user has been destroyed' do - before do - User.current = user_2 - book.save! - user_1.destroy - user_2.destroy - end - - it { book.created_by.should == user_1.id } - it { book.writer.should be_nil } - it { book.updated_by.should == user_2.id } - it { book.editor.should be_nil } - end - end - - describe '#config' do - before do - Mongoid::Userstamp.config(:test) do |c| - c.user_reader = :test_user - c.user_model = :user - - c.created_column = :c_by - c.created_column_opts = {as: :created_by_id} - c.created_accessor = :created_by - - c.updated_column = :u_by - c.updated_column_opts = {as: :updated_by_id} - c.updated_accessor = :updated_by - end - end - - subject { Mongoid::Userstamp.configs[:test] } - - it { Mongoid::Userstamp.should respond_to :config } - it { Mongoid::Userstamp.configs.should have_key(:test) } - - it { subject.user_reader.should == :test_user } - it { subject.user_model.should == User } - it { subject.created_column.should == :c_by } - it { subject.created_column_opts.should == {as: :created_by_id} } - it { subject.created_accessor.should == :created_by } - it { subject.updated_column.should == :u_by } - it { subject.updated_column_opts.should == {as: :updated_by_id} } - it { subject.updated_accessor.should == :updated_by } - end - - context 'when using an undefined configuration' do - it { ->{ Book.send(:mongoid_userstamp, :any_config) }.should raise_error(ConfigurationNotFoundError) } - end -end \ No newline at end of file diff --git a/spec/integration/userstamp_spec.rb b/spec/integration/userstamp_spec.rb deleted file mode 100644 index 6e53f2a..0000000 --- a/spec/integration/userstamp_spec.rb +++ /dev/null @@ -1,187 +0,0 @@ -# -*- encoding : utf-8 -*- -require 'spec_helper' - -describe Mongoid::Userstamp do - subject(:book) { Book.new(name: 'Crafting Rails Applications') } - subject(:post) { Post.new(title: 'Understanding Rails') } - - let(:user_1) { User.create!(name: 'Charles Dikkens') } - let(:user_2) { User.create!(name: 'Edmund Wells') } - let(:admin_1) { Admin.create!(name: 'JK Rowling') } - let(:admin_2) { Admin.create!(name: 'Stephan Norway') } - - describe 'configuration' do - it { Mongoid::Userstamp.timestamped_models.should include(Book) } - it { Mongoid::Userstamp.timestamped_models.should include(Post) } - - context 'when :default' do - it { Book.userstamp_key.should eq :default } - it { Book.userstamp_config.should eq Mongoid::Userstamp.configs[:default] } - - it { book.should respond_to :created_by } - it { book.should respond_to :writer } - it { book.should respond_to :updated_by } - it { book.should respond_to :editor } - end - context 'when :admin' do - it { Post.userstamp_key.should eq :admin } - it { Post.userstamp_config.should eq Mongoid::Userstamp.configs[:admin] } - - it { post.should respond_to :c_by } - it { post.should respond_to :creator } - it { post.should respond_to :u_by } - it { post.should respond_to :updater } - end - end - - describe '#current_user' do - before { Admin.current = nil; User.current = nil } - subject(:book_user){ Book.current_user } - subject(:post_user){ Post.current_user } - - context 'when current book user is not set' do - before { User.current = nil } - it { book_user.should be_nil } - it { post_user.should be_nil } - end - - context 'when current book user is set' do - before{ User.current = user_1 } - it { book_user.should eq user_1 } - it { post_user.should be_nil } - end - - context 'when current post user is not set' do - before { Admin.current = nil } - it { book_user.should be_nil } - it { post_user.should be_nil } - end - - context 'when current post user is set' do - before{ Admin.current = admin_1 } - it { book_user.should be_nil } - it { post_user.should eq admin_1 } - end - end - - context 'when created without a user' do - before do - Admin.current = admin_1 - User.current = nil - book.save! - end - - it { book.created_by.should be_nil } - it { book.writer.should be_nil } - it { book.updated_by.should be_nil } - it { book.editor.should be_nil } - end - - context 'when creator is manually set' do - before do - User.current = user_1 - Admin.current = admin_1 - end - - context 'set by id' do - before do - post.c_by = admin_2._id - post.save! - end - - it 'should not be overridden when saved' do - post.c_by.should eq admin_2.id - post.creator.should eq admin_2 - post.u_by.should eq admin_1.id - post.updater.should eq admin_1 - end - end - context 'set by model' do - before do - post.creator = admin_2 - post.save! - end - - it 'should not be overridden when saved' do - post.c_by.should eq admin_2.id - post.creator.should eq admin_2 - post.u_by.should eq admin_1.id - post.updater.should eq admin_1 - end - end - end - - context 'when created by a user' do - before do - Admin.current = admin_1 - User.current = user_1 - book.save! - end - - it { book.created_by.should == user_1.id } - it { book.writer.should == user_1 } - it { book.updated_by.should == user_1.id } - it { book.editor.should == user_1 } - - context 'when updated by a user' do - before do - User.current = user_2 - book.save! - end - - it { book.created_by.should == user_1.id } - it { book.writer.should == user_1 } - it { book.updated_by.should == user_2.id } - it { book.editor.should == user_2 } - end - - context 'when user has been destroyed' do - before do - User.current = user_2 - book.save! - user_1.destroy - user_2.destroy - end - - it { book.created_by.should == user_1.id } - it { book.writer.should be_nil } - it { book.updated_by.should == user_2.id } - it { book.editor.should be_nil } - end - end - - describe '#config' do - before do - Mongoid::Userstamp.config(:test) do |c| - c.user_reader = :test_user - c.user_model = :user - - c.created_column = :c_by - c.created_column_opts = {as: :created_by_id} - c.created_accessor = :created_by - - c.updated_column = :u_by - c.updated_column_opts = {as: :updated_by_id} - c.updated_accessor = :updated_by - end - end - - subject { Mongoid::Userstamp.configs[:test] } - - it { Mongoid::Userstamp.should respond_to :config } - it { Mongoid::Userstamp.configs.should have_key(:test) } - - it { subject.user_reader.should == :test_user } - it { subject.user_model.should == User } - it { subject.created_column.should == :c_by } - it { subject.created_column_opts.should == {as: :created_by_id} } - it { subject.created_accessor.should == :created_by } - it { subject.updated_column.should == :u_by } - it { subject.updated_column_opts.should == {as: :updated_by_id} } - it { subject.updated_accessor.should == :updated_by } - end - - context 'when using an undefined configuration' do - it { ->{ Book.send(:mongoid_userstamp, :any_config) }.should raise_error(ConfigurationNotFoundError) } - end -end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 99c0c8e..5b4137c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ # -*- encoding : utf-8 -*- require 'rubygems' +require 'ostruct' $:.push File.expand_path('../../lib', __FILE__) @@ -7,14 +8,12 @@ require 'mongoid' require 'mongoid_userstamp' -%w(config admin user book post).each do |file_name| +%w(admin user book post).each do |file_name| require "support/#{file_name}" end Mongoid.configure do |config| - config.connect_to( - 'mongoid_userstamp_test' - ) + config.connect_to 'mongoid_userstamp_test' end RSpec.configure do |config| diff --git a/spec/support/book.rb b/spec/support/book.rb index faa8bb9..d32b005 100644 --- a/spec/support/book.rb +++ b/spec/support/book.rb @@ -3,7 +3,7 @@ class Book include Mongoid::Document include Mongoid::Userstamp - mongoid_userstamp + mongoid_userstamp user_model: 'User' field :name end \ No newline at end of file diff --git a/spec/support/config.rb b/spec/support/config.rb deleted file mode 100644 index 040bf1b..0000000 --- a/spec/support/config.rb +++ /dev/null @@ -1,12 +0,0 @@ -Mongoid::Userstamp.config do |c| - c.created_accessor = :writer - c.updated_accessor = :editor -end - -Mongoid::Userstamp.config(:admin) do |c| - c.user_reader = :current_admin - c.user_model = :admin - - c.created_column = :c_by - c.updated_column = :u_by -end \ No newline at end of file diff --git a/spec/support/post.rb b/spec/support/post.rb index dd7d7c9..12a729c 100644 --- a/spec/support/post.rb +++ b/spec/support/post.rb @@ -3,7 +3,9 @@ class Post include Mongoid::Document include Mongoid::Userstamp - mongoid_userstamp :admin + mongoid_userstamp user_model: 'Admin', + created_name: :writer, + updated_name: :editor field :title end \ No newline at end of file diff --git a/spec/unit/app_config_spec.rb b/spec/unit/app_config_spec.rb index a24728d..04eaaa8 100644 --- a/spec/unit/app_config_spec.rb +++ b/spec/unit/app_config_spec.rb @@ -1,28 +1,46 @@ # -*- encoding : utf-8 -*- require 'spec_helper' -describe Mongoid::Userstamp::Config::AppConfig do +describe Mongoid::Userstamp::AppConfig do - subject { Mongoid::Userstamp::Config::AppConfig.new } + subject { Mongoid::Userstamp::AppConfig.new } describe '#initialize' do context 'without block' do - its(:model) { should eq :user } - its(:reader){ should eq :current_user } + it { should be_a Mongoid::Userstamp::AppConfig } + its(:created_name){ should eq :created_by } + its(:updated_name){ should eq :updated_by } + its(:user_reader){ should eq :current_user } end context 'with block' do - subject do - Mongoid::Userstamp::Config::UserConfig.new do |u| - u.model = :custom_user - u.reader = :custom_current_user + Mongoid::Userstamp::AppConfig.new do |u| + u.created_name = :c_by + u.updated_name = :u_by + u.user_reader = :foo end end - its(:model) { should eq :custom_user } - its(:reader){ should eq :custom_current_user } + it { should be_a Mongoid::Userstamp::AppConfig } + its(:created_name){ should eq :c_by } + its(:updated_name){ should eq :u_by } + its(:user_reader){ should eq :foo } + end + end + + describe 'deprecated methods' do + subject do + Mongoid::Userstamp::AppConfig.new do |u| + u.user_model = :bar + u.created_column = :bing + u.updated_column = :baz + end end + it { ->{ subject }.should_not raise_error } + it { should be_a Mongoid::Userstamp::AppConfig } + its(:created_name){ should eq :bing } + its(:updated_name){ should eq :baz } end end diff --git a/spec/unit/model_config_spec.rb b/spec/unit/model_config_spec.rb new file mode 100644 index 0000000..8ab557a --- /dev/null +++ b/spec/unit/model_config_spec.rb @@ -0,0 +1,31 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Mongoid::Userstamp::ModelConfig do + + subject { Mongoid::Userstamp::ModelConfig.new } + before { Mongoid::Userstamp.stub('config').and_return(OpenStruct.new(created_name: :created_by, + updated_name: :updated_by)) } + before { Mongoid::Userstamp.stub('user_classes').and_return(['User']) } + + describe '#initialize' do + + context 'with opts hash' do + subject { Mongoid::Userstamp::ModelConfig.new(user_model: :bar, + created_name: :c_by, + updated_name: :u_by) } + + it { should be_a Mongoid::Userstamp::ModelConfig } + its(:user_model){ should eq :bar } + its(:created_name){ should eq :c_by } + its(:updated_name){ should eq :u_by } + end + + context 'without opts hash' do + it { should be_a Mongoid::Userstamp::ModelConfig } + its(:user_model){ should eq 'User' } + its(:created_name){ should eq :created_by } + its(:updated_name){ should eq :updated_by } + end + end +end diff --git a/spec/unit/model_spec.rb b/spec/unit/model_spec.rb new file mode 100644 index 0000000..10bd125 --- /dev/null +++ b/spec/unit/model_spec.rb @@ -0,0 +1,120 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Mongoid::Userstamp::Model do + + subject(:book) { Book.new(name: 'Crafting Rails Applications') } + subject(:post) { Post.new(title: 'Understanding Rails') } + + let(:user_1) { User.create!(name: 'Charles Dikkens') } + let(:user_2) { User.create!(name: 'Edmund Wells') } + let(:admin_1) { Admin.create!(name: 'JK Rowling') } + let(:admin_2) { Admin.create!(name: 'Stephan Norway') } + + #describe '::mongoid_userstamp' do + #end + + #describe '::mongoid_userstamp_config' do + #end + + describe '::current_user' do + + before { Admin.current = nil; User.current = nil } + + context 'when current book user is not set' do + it { Book.current_user.should be_nil } + it { Post.current_user.should be_nil } + end + + context 'when current book user is set' do + before{ User.current = user_1 } + it { Book.current_user.should eq user_1 } + it { Post.current_user.should be_nil } + end + + context 'when current post user is set' do + before{ Admin.current = admin_1 } + it { Book.current_user.should be_nil } + it { Post.current_user.should eq admin_1 } + end + end + + describe 'relations and callbacks' do + + context 'when created without a user' do + before do + User.current = nil + Admin.current = nil + book.save! + post.save! + end + + it { book.created_by.should be_nil } + it { book.updated_by.should be_nil } + it { post.writer.should be_nil } + it { post.editor.should be_nil } + end + + context 'when created with a user' do + before do + User.current = user_1 + Admin.current = admin_1 + book.save! + post.save! + end + + it { book.created_by.should eq user_1 } + it { book.updated_by.should eq user_1 } + it { post.writer.should eq admin_1 } + it { post.editor.should eq admin_1 } + end + + context 'when creator is manually set' do + before do + User.current = user_1 + Admin.current = admin_1 + book.created_by = user_2 + book.save! + post.writer = admin_2 + post.save! + end + + it { book.created_by.should eq user_2 } + it { book.updated_by.should eq user_1 } + it { post.writer.should eq admin_2 } + it { post.editor.should eq admin_1 } + end + + context 'when updater is manually set' do + before do + User.current = user_1 + Admin.current = admin_1 + book.updated_by = user_2 + book.save! + post.editor = admin_2 + post.save! + end + + it { book.created_by.should eq user_1 } + it { book.updated_by.should eq user_1 } + it { post.writer.should eq admin_1 } + it { post.editor.should eq admin_1 } + end + + context 'when user has been destroyed' do + before do + User.current = user_1 + Admin.current = admin_1 + book.save! + post.save! + user_1.destroy + admin_1.destroy + end + + it { Book.first.created_by.should be_nil } + it { Book.first.updated_by.should be_nil } + it { Post.first.writer.should be_nil } + it { Post.first.editor.should be_nil } + end + end +end \ No newline at end of file diff --git a/spec/unit/user_config_spec.rb b/spec/unit/user_config_spec.rb index bb30fc7..2872a69 100644 --- a/spec/unit/user_config_spec.rb +++ b/spec/unit/user_config_spec.rb @@ -1,45 +1,23 @@ # -*- encoding : utf-8 -*- require 'spec_helper' -describe Mongoid::Userstamp::Config::UserConfig do +describe Mongoid::Userstamp::UserConfig do - subject { Mongoid::Userstamp::Config::UserConfig.new } + subject { Mongoid::Userstamp::UserConfig.new } + before { Mongoid::Userstamp.stub('config').and_return(OpenStruct.new(user_reader: :foo)) } describe '#initialize' do - context 'without block' do - its(:model) { should eq :user } - its(:reader){ should eq :current_user } - end - - context 'with block' do - subject do - Mongoid::Userstamp::Config::UserConfig.new do |u| - u.model = :custom_user - u.reader = :custom_current_user - end - end - its(:model) { should eq :custom_user } - its(:reader){ should eq :custom_current_user } - end - end - - describe '#initialize' do + context 'with opts hash' do + subject { Mongoid::Userstamp::UserConfig.new({reader: :bar}) } - context 'without block' do - its(:model) { should eq :user } - its(:reader){ should eq :current_user } + it { should be_a Mongoid::Userstamp::UserConfig } + its(:reader){ should eq :bar } end - context 'with block' do - subject do - Mongoid::Userstamp::Config::UserConfig.new do |u| - u.model = :custom_user - u.reader = :custom_current_user - end - end - its(:model) { should eq :custom_user } - its(:reader){ should eq :custom_current_user } + context 'without opts hash' do + it { should be_a Mongoid::Userstamp::UserConfig } + its(:reader){ should eq :foo } end end end diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb new file mode 100644 index 0000000..741a541 --- /dev/null +++ b/spec/unit/user_spec.rb @@ -0,0 +1,76 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Mongoid::Userstamp::User do + + subject(:book) { Book.new(name: 'Crafting Rails Applications') } + subject(:post) { Post.new(title: 'Understanding Rails') } + + let(:user_1) { User.create!(name: 'Charles Dikkens') } + let(:user_2) { User.create!(name: 'Edmund Wells') } + let(:admin_1) { Admin.create!(name: 'JK Rowling') } + let(:admin_2) { Admin.create!(name: 'Stephan Norway') } + + describe '::current and #current?' do + before { Admin.current = nil; User.current = nil } + + context 'when current users are not set' do + it { Admin.current.should be_nil } + it { User.current.should be_nil } + it { admin_1.current?.should be_false } + it { admin_2.current?.should be_false } + it { user_1.current?.should be_false } + it { user_2.current?.should be_false } + end + + context 'when current User is set' do + before{ User.current = user_1 } + it { User.current.should eq user_1 } + it { Admin.current.should be_nil } + it { admin_1.current?.should be_false } + it { admin_2.current?.should be_false } + it { user_1.current?.should be_true } + it { user_2.current?.should be_false } + end + + context 'when current Admin is set' do + before{ Admin.current = admin_1 } + it { User.current.should be_nil } + it { Admin.current.should eq admin_1 } + it { admin_1.current?.should be_true } + it { admin_2.current?.should be_false } + it { user_1.current?.should be_false } + it { user_2.current?.should be_false } + end + end + + describe '::do_as' do + it 'should set the current user' do + Admin.current = admin_1 + Admin.do_as admin_2 do + Admin.current.should eq admin_2 + end + Admin.current.should eq admin_1 + end + + it 'should return the value of the block' do + Admin.do_as admin_2 do + 'foo' + end.should eq 'foo' + end + + it 'should revert user in case of error' do + Admin.current = admin_1 + begin + Admin.do_as admin_2 do + raise + end + rescue + end + Admin.current.should eq admin_1 + end + end + + #describe '::mongoid_userstamp_user' do + #end +end diff --git a/spec/unit/userstamp_spec.rb b/spec/unit/userstamp_spec.rb new file mode 100644 index 0000000..7fab66b --- /dev/null +++ b/spec/unit/userstamp_spec.rb @@ -0,0 +1,120 @@ +# -*- encoding : utf-8 -*- +require 'spec_helper' + +describe Mongoid::Userstamp do + + subject{ Mongoid::Userstamp } + + let(:user_1){ User.create!(name: 'Edmund Wells') } + let(:user_2){ Admin.create!(name: 'JK Rowling') } + + describe '#config' do + + before { Mongoid::Userstamp.instance_variable_set(:'@config', nil) } + + context 'without block' do + subject{ Mongoid::Userstamp.config } + it { should be_a Mongoid::Userstamp::AppConfig } + its(:created_name){ should eq :created_by } + its(:updated_name){ should eq :updated_by } + its(:user_reader){ should eq :current_user } + end + + context 'with block' do + subject do + Mongoid::Userstamp.config do |u| + u.created_name = :c_by + u.updated_name = :u_by + u.user_reader = :foo + end + end + it { should be_a Mongoid::Userstamp::AppConfig } + its(:created_name){ should eq :c_by } + its(:updated_name){ should eq :u_by } + its(:user_reader){ should eq :foo } + end + + context 'deprecated method' do + subject{ Mongoid::Userstamp.configure } + it { should be_a Mongoid::Userstamp::AppConfig } + end + end + + describe '#current_user' do + before do + Mongoid::Userstamp.set_current_user(user_1) + Mongoid::Userstamp.set_current_user(user_2) + end + context 'when user_class is User' do + subject{ Mongoid::Userstamp.current_user('User') } + it{ should eq user_1 } + end + context 'when user_class is Admin' do + subject{ Mongoid::Userstamp.current_user('Admin') } + it{ should eq user_2 } + end + context 'when user_class is other' do + subject{ Mongoid::Userstamp.current_user('foobar') } + it{ should be_nil } + end + context 'when user_class is not given' do + subject{ Mongoid::Userstamp.current_user } + it 'should use the default user_class' do + should eq user_2 + end + end + end + + describe '#model_classes' do + before { Mongoid::Userstamp.instance_variable_set(:'@model_classes', nil) } + context 'default value' do + its(:model_classes){ should eq [] } + end + context 'setting values' do + before do + subject.add_model_class 'Book' + subject.add_model_class 'Post' + end + its(:model_classes){ should eq [Book, Post] } + end + end + + describe '#user_classes' do + before { Mongoid::Userstamp.instance_variable_set(:'@user_classes', nil) } + context 'default value' do + its(:user_classes){ should eq [User] } + end + context 'setting values' do + before do + subject.add_user_class 'Book' + subject.add_user_class 'Post' + end + its(:user_classes){ should eq [Book, Post] } + end + end + + describe '#store' do + context 'when RequestStore is defined' do + before do + stub_const('RequestStore', Object.new) + RequestStore.stub('store').and_return('foobar') + end + its(:store){ should eq RequestStore.store } + end + context 'when RequestStore is not defined' do + before{ hide_const('RequestStore') } + its(:store){ should eq Thread.current } + end + end + + describe '#userstamp_key' do + context 'when model is a Class' do + subject{ Mongoid::Userstamp.userstamp_key(User) } + it{ should eq :"mongoid_userstamp/user" } + end + context 'when model is a String' do + subject{ Mongoid::Userstamp.userstamp_key('MyNamespace::User') } + it{ should eq :"mongoid_userstamp/my_namespace/user" } + end + end +end From 7fb6950585b838307eb358541706d2b6b69f53ef Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Mon, 24 Feb 2014 02:26:04 +0900 Subject: [PATCH 12/19] Rename AppConfig to GemConfig --- README.md | 4 ++-- lib/mongoid/userstamp.rb | 6 +++--- .../config/{app_config.rb => gem_config.rb} | 2 +- lib/mongoid_userstamp.rb | 2 +- .../{app_config_spec.rb => gem_config_spec.rb} | 14 +++++++------- spec/unit/userstamp_spec.rb | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) rename lib/mongoid/userstamp/config/{app_config.rb => gem_config.rb} (98%) rename spec/unit/{app_config_spec.rb => gem_config_spec.rb} (71%) diff --git a/README.md b/README.md index 4dfdb7c..b137abe 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,8 @@ need to set `User.current = new_user` after the switch occurs. ## Thread Safety -By default, Mongoid::Userstamp stores all-related user variables in `Thread.current`. -If the [RequestStore](https://github.com/steveklabnik/request_store) gem is installed, Mongoid::Userstamp +Mongoid::Userstamp stores all-related user variables in `Thread.current`. If the +[RequestStore](https://github.com/steveklabnik/request_store) gem is installed, Mongoid::Userstamp will automatically store variables in the `RequestStore.store` instead. RequestStore is recommended for threaded web servers like Thin or Puma. diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index fbb84b1..a264363 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -24,7 +24,7 @@ def mongoid_userstamp_config(opts = {}) class << self def config(&block) - @config ||= Mongoid::Userstamp::AppConfig.new(&block) + @config ||= Mongoid::Userstamp::GemConfig.new(&block) end # @deprecated @@ -49,7 +49,7 @@ def set_current_user(value, user_class = nil) end def model_classes - (@model_classes || []).map{|c| c.is_a?(Class) ? c : c.to_s.constantize } + (@model_classes || []).map{|c| c.is_a?(Class) ? c : c.to_s.classify.constantize } end def add_model_class(model) @@ -58,7 +58,7 @@ def add_model_class(model) end def user_classes - (@user_classes || ['User']).map{|c| c.is_a?(Class) ? c : c.to_s.constantize } + (@user_classes || ['User']).map{|c| c.is_a?(Class) ? c : c.to_s.classify.constantize } end def add_user_class(user) diff --git a/lib/mongoid/userstamp/config/app_config.rb b/lib/mongoid/userstamp/config/gem_config.rb similarity index 98% rename from lib/mongoid/userstamp/config/app_config.rb rename to lib/mongoid/userstamp/config/gem_config.rb index 9bd4966..04f7b21 100644 --- a/lib/mongoid/userstamp/config/app_config.rb +++ b/lib/mongoid/userstamp/config/gem_config.rb @@ -3,7 +3,7 @@ module Mongoid module Userstamp - class AppConfig + class GemConfig attr_accessor :created_name attr_accessor :updated_name diff --git a/lib/mongoid_userstamp.rb b/lib/mongoid_userstamp.rb index 9b80a11..5ed7c13 100644 --- a/lib/mongoid_userstamp.rb +++ b/lib/mongoid_userstamp.rb @@ -2,7 +2,7 @@ require 'mongoid/userstamp' require 'mongoid/userstamp/version' -require 'mongoid/userstamp/config/app_config' +require 'mongoid/userstamp/config/gem_config' require 'mongoid/userstamp/config/model_config' require 'mongoid/userstamp/config/user_config' require 'mongoid/userstamp/mixins/user' diff --git a/spec/unit/app_config_spec.rb b/spec/unit/gem_config_spec.rb similarity index 71% rename from spec/unit/app_config_spec.rb rename to spec/unit/gem_config_spec.rb index 04eaaa8..9bc6a60 100644 --- a/spec/unit/app_config_spec.rb +++ b/spec/unit/gem_config_spec.rb @@ -1,14 +1,14 @@ # -*- encoding : utf-8 -*- require 'spec_helper' -describe Mongoid::Userstamp::AppConfig do +describe Mongoid::Userstamp::GemConfig do - subject { Mongoid::Userstamp::AppConfig.new } + subject { Mongoid::Userstamp::GemConfig.new } describe '#initialize' do context 'without block' do - it { should be_a Mongoid::Userstamp::AppConfig } + it { should be_a Mongoid::Userstamp::GemConfig } its(:created_name){ should eq :created_by } its(:updated_name){ should eq :updated_by } its(:user_reader){ should eq :current_user } @@ -16,14 +16,14 @@ context 'with block' do subject do - Mongoid::Userstamp::AppConfig.new do |u| + Mongoid::Userstamp::GemConfig.new do |u| u.created_name = :c_by u.updated_name = :u_by u.user_reader = :foo end end - it { should be_a Mongoid::Userstamp::AppConfig } + it { should be_a Mongoid::Userstamp::GemConfig } its(:created_name){ should eq :c_by } its(:updated_name){ should eq :u_by } its(:user_reader){ should eq :foo } @@ -32,14 +32,14 @@ describe 'deprecated methods' do subject do - Mongoid::Userstamp::AppConfig.new do |u| + Mongoid::Userstamp::GemConfig.new do |u| u.user_model = :bar u.created_column = :bing u.updated_column = :baz end end it { ->{ subject }.should_not raise_error } - it { should be_a Mongoid::Userstamp::AppConfig } + it { should be_a Mongoid::Userstamp::GemConfig } its(:created_name){ should eq :bing } its(:updated_name){ should eq :baz } end diff --git a/spec/unit/userstamp_spec.rb b/spec/unit/userstamp_spec.rb index 7fab66b..e3616d0 100644 --- a/spec/unit/userstamp_spec.rb +++ b/spec/unit/userstamp_spec.rb @@ -14,7 +14,7 @@ context 'without block' do subject{ Mongoid::Userstamp.config } - it { should be_a Mongoid::Userstamp::AppConfig } + it { should be_a Mongoid::Userstamp::GemConfig } its(:created_name){ should eq :created_by } its(:updated_name){ should eq :updated_by } its(:user_reader){ should eq :current_user } @@ -28,7 +28,7 @@ u.user_reader = :foo end end - it { should be_a Mongoid::Userstamp::AppConfig } + it { should be_a Mongoid::Userstamp::GemConfig } its(:created_name){ should eq :c_by } its(:updated_name){ should eq :u_by } its(:user_reader){ should eq :foo } @@ -36,7 +36,7 @@ context 'deprecated method' do subject{ Mongoid::Userstamp.configure } - it { should be_a Mongoid::Userstamp::AppConfig } + it { should be_a Mongoid::Userstamp::GemConfig } end end From 455d312e5a4fb2d26785c6f9e948ee990e4ab182 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Mon, 24 Feb 2014 17:13:22 +0900 Subject: [PATCH 13/19] Second attempt at better Railtie --- lib/mongoid/userstamp/railtie.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/mongoid/userstamp/railtie.rb b/lib/mongoid/userstamp/railtie.rb index 540ec37..2f821e8 100644 --- a/lib/mongoid/userstamp/railtie.rb +++ b/lib/mongoid/userstamp/railtie.rb @@ -6,7 +6,7 @@ module Userstamp class Railtie < Rails::Railtie # Include Mongoid::Userstamp::User into User class, if not already done - initializer 'mongoid_userstamp.setup_user_classes' do |app| + config.to_prepare do Mongoid::Userstamp.user_classes.each do |user_class| unless user_class.included_modules.include?(Mongoid::Userstamp::User) user_class.send(:include, Mongoid::Userstamp::User) @@ -16,7 +16,7 @@ class Railtie < Rails::Railtie # Add userstamp to models where Mongoid::Userstamp was included, but # mongoid_userstamp was not explicitly called - initializer 'mongoid_userstamp.setup_model_classes' do |app| + config.to_prepare do Mongoid::Userstamp.model_classes.each do |model_class| unless model_class.included_modules.include?(Mongoid::Userstamp::Model) model_class.send(:include, Mongoid::Userstamp::Model) @@ -25,14 +25,12 @@ class Railtie < Rails::Railtie end # Set current_user from controller reader method - initializer 'mongoid_userstamp.setup_current_user_before_filter' do |app| - ActiveSupport.on_load :action_controller do - before_filter do |c| - Mongoid::Userstamp.user_classes.each do |user_class| - begin - user_class.current = c.send(user_class.mongoid_userstamp_user.reader) - rescue - end + ActiveSupport.on_load :action_controller do + before_filter do |c| + Mongoid::Userstamp.user_classes.each do |user_class| + begin + user_class.current = c.send(user_class.mongoid_userstamp_user.reader) + rescue end end end From f02d64a29d35c4e062f66a26ec764a10f6916064 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Mon, 24 Feb 2014 17:41:06 +0900 Subject: [PATCH 14/19] Fix syntax --- lib/mongoid/userstamp/mixins/user.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/mongoid/userstamp/mixins/user.rb b/lib/mongoid/userstamp/mixins/user.rb index 31cd519..0508928 100644 --- a/lib/mongoid/userstamp/mixins/user.rb +++ b/lib/mongoid/userstamp/mixins/user.rb @@ -37,11 +37,8 @@ def do_as(user, &block) response end - module ClassMethods - - def mongoid_userstamp_user(opts = {}) - @mongoid_userstamp_user ||= Mongoid::Userstamp::UserConfig.new(opts = {}) - end + def mongoid_userstamp_user(opts = {}) + @mongoid_userstamp_user ||= Mongoid::Userstamp::UserConfig.new(opts = {}) end end end From df0e4a0592564045f02825380fce893b5d7ae328 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Mon, 24 Feb 2014 20:19:44 +0900 Subject: [PATCH 15/19] Fix stupid error --- lib/mongoid/userstamp/mixins/user.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mongoid/userstamp/mixins/user.rb b/lib/mongoid/userstamp/mixins/user.rb index 0508928..36acd6f 100644 --- a/lib/mongoid/userstamp/mixins/user.rb +++ b/lib/mongoid/userstamp/mixins/user.rb @@ -38,7 +38,7 @@ def do_as(user, &block) end def mongoid_userstamp_user(opts = {}) - @mongoid_userstamp_user ||= Mongoid::Userstamp::UserConfig.new(opts = {}) + @mongoid_userstamp_user ||= Mongoid::Userstamp::UserConfig.new(opts) end end end From 4e933ded057800fffefe062d6dc898c5ffca6893 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Mon, 24 Feb 2014 21:27:27 +0900 Subject: [PATCH 16/19] Add specs for config methods --- lib/mongoid/userstamp.rb | 2 +- lib/mongoid/userstamp/config/gem_config.rb | 2 +- lib/mongoid/userstamp/config/model_config.rb | 2 +- spec/unit/model_spec.rb | 45 ++++++++++++++++++-- spec/unit/user_spec.rb | 23 +++++++++- 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index a264363..93f95ec 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -13,7 +13,7 @@ module ClassMethods def mongoid_userstamp(opts = {}) mongoid_userstamp_config(opts) - self.send(:include, Mongoid::Userstamp::Model) + self.send(:include, Mongoid::Userstamp::Model) unless self.included_modules.include?(Mongoid::Userstamp::Model) end def mongoid_userstamp_config(opts = {}) diff --git a/lib/mongoid/userstamp/config/gem_config.rb b/lib/mongoid/userstamp/config/gem_config.rb index 04f7b21..09d17ef 100644 --- a/lib/mongoid/userstamp/config/gem_config.rb +++ b/lib/mongoid/userstamp/config/gem_config.rb @@ -12,7 +12,7 @@ class GemConfig def initialize(&block) @created_name = :created_by @updated_name = :updated_by - @user_reader = :current_user + @user_reader = :current_user instance_eval(&block) if block_given? end diff --git a/lib/mongoid/userstamp/config/model_config.rb b/lib/mongoid/userstamp/config/model_config.rb index 2802e88..1705fe2 100644 --- a/lib/mongoid/userstamp/config/model_config.rb +++ b/lib/mongoid/userstamp/config/model_config.rb @@ -6,7 +6,7 @@ module Userstamp class ModelConfig def initialize(opts = {}) - @user_model = opts.delete(:user_model) + @user_model = opts.delete(:user_model) @created_name = opts.delete(:created_name) @updated_name = opts.delete(:updated_name) end diff --git a/spec/unit/model_spec.rb b/spec/unit/model_spec.rb index 10bd125..a382c8b 100644 --- a/spec/unit/model_spec.rb +++ b/spec/unit/model_spec.rb @@ -11,11 +11,48 @@ let(:admin_1) { Admin.create!(name: 'JK Rowling') } let(:admin_2) { Admin.create!(name: 'Stephan Norway') } - #describe '::mongoid_userstamp' do - #end + describe '::mongoid_userstamp_config' do + before do + @config = Book.instance_variable_get(:'@mongoid_userstamp_config') + Book.instance_variable_set(:'@mongoid_userstamp_config', nil) + end + + after do + Book.instance_variable_set(:'@mongoid_userstamp_config', @config) + end - #describe '::mongoid_userstamp_config' do - #end + context 'when options are not given' do + subject{ Book.mongoid_userstamp_config } + it { should be_a Mongoid::Userstamp::ModelConfig } + its(:user_model) { should eq Admin } + its(:created_name) { should eq :created_by } + its(:updated_name) { should eq :updated_by } + end + + context 'when options are given' do + subject{ Book.mongoid_userstamp_config(user_model: 'User', created_name: :foo, updated_name: :bar) } + it { should be_a Mongoid::Userstamp::ModelConfig } + its(:user_model) { should eq 'User' } + its(:created_name) { should eq :foo } + its(:updated_name) { should eq :bar } + end + + context 'when mongoid_userstamp_user has been set' do + subject{ Book.mongoid_userstamp_config; Book.mongoid_userstamp_config(user_model: 'User', created_name: :foo, updated_name: :bar) } + it { should be_a Mongoid::Userstamp::ModelConfig } + its(:user_model) { should eq Admin } + its(:created_name) { should eq :created_by } + its(:updated_name) { should eq :updated_by } + end + + context 'when set via mongoid_userstamp method' do + subject{ Book.mongoid_userstamp(user_model: 'User', created_name: :foo, updated_name: :bar); Book.mongoid_userstamp_config } + it { should be_a Mongoid::Userstamp::ModelConfig } + its(:user_model) { should eq 'User' } + its(:created_name) { should eq :foo } + its(:updated_name) { should eq :bar } + end + end describe '::current_user' do diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb index 741a541..0b28cb8 100644 --- a/spec/unit/user_spec.rb +++ b/spec/unit/user_spec.rb @@ -71,6 +71,25 @@ end end - #describe '::mongoid_userstamp_user' do - #end + describe '::mongoid_userstamp_user' do + before{ User.instance_variable_set(:'@mongoid_userstamp_user', nil) } + + context 'when options are not given' do + subject{ User.mongoid_userstamp_user } + it { should be_a Mongoid::Userstamp::UserConfig } + its(:reader) { should eq :current_user } + end + + context 'when options are given' do + subject{ User.mongoid_userstamp_user(reader: :foo) } + it { should be_a Mongoid::Userstamp::UserConfig } + its(:reader) { should eq :foo } + end + + context 'when mongoid_userstamp_user has been set' do + subject{ User.mongoid_userstamp_user; User.mongoid_userstamp_user(reader: :foo) } + it { should be_a Mongoid::Userstamp::UserConfig } + its(:reader) { should eq :current_user } + end + end end From 0d50511a50cbf049f54c16de8cf477a677c93cf6 Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Thu, 31 Jul 2014 04:23:34 +0900 Subject: [PATCH 17/19] Upgrade RSpec to 3.0.0 --- mongoid_userstamp.gemspec | 2 +- spec/unit/gem_config_spec.rb | 16 ++++++++-------- spec/unit/model_config_spec.rb | 12 ++++++------ spec/unit/model_spec.rb | 24 ++++++++++++------------ spec/unit/user_config_spec.rb | 4 ++-- spec/unit/user_spec.rb | 30 +++++++++++++++--------------- spec/unit/userstamp_spec.rb | 24 ++++++++++++------------ 7 files changed, 56 insertions(+), 56 deletions(-) diff --git a/mongoid_userstamp.gemspec b/mongoid_userstamp.gemspec index 350bc1f..4dd9353 100644 --- a/mongoid_userstamp.gemspec +++ b/mongoid_userstamp.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'mongoid', '>= 3.0.4' s.add_development_dependency 'rake' - s.add_development_dependency 'rspec', '>= 2.13.0' + s.add_development_dependency 'rspec', '>= 3.0.0' s.add_development_dependency 'yard' s.add_development_dependency 'gem-release' s.add_development_dependency 'request_store' diff --git a/spec/unit/gem_config_spec.rb b/spec/unit/gem_config_spec.rb index 9bc6a60..2475dd6 100644 --- a/spec/unit/gem_config_spec.rb +++ b/spec/unit/gem_config_spec.rb @@ -9,9 +9,9 @@ context 'without block' do it { should be_a Mongoid::Userstamp::GemConfig } - its(:created_name){ should eq :created_by } - its(:updated_name){ should eq :updated_by } - its(:user_reader){ should eq :current_user } + it { subject.created_name.should eq :created_by } + it { subject.updated_name.should eq :updated_by } + it { subject.user_reader.should eq :current_user } end context 'with block' do @@ -24,9 +24,9 @@ end it { should be_a Mongoid::Userstamp::GemConfig } - its(:created_name){ should eq :c_by } - its(:updated_name){ should eq :u_by } - its(:user_reader){ should eq :foo } + it { subject.created_name.should eq :c_by } + it { subject.updated_name.should eq :u_by } + it { subject.user_reader.should eq :foo } end end @@ -40,7 +40,7 @@ end it { ->{ subject }.should_not raise_error } it { should be_a Mongoid::Userstamp::GemConfig } - its(:created_name){ should eq :bing } - its(:updated_name){ should eq :baz } + it { subject.created_name.should eq :bing } + it { subject.updated_name.should eq :baz } end end diff --git a/spec/unit/model_config_spec.rb b/spec/unit/model_config_spec.rb index 8ab557a..4fdb905 100644 --- a/spec/unit/model_config_spec.rb +++ b/spec/unit/model_config_spec.rb @@ -16,16 +16,16 @@ updated_name: :u_by) } it { should be_a Mongoid::Userstamp::ModelConfig } - its(:user_model){ should eq :bar } - its(:created_name){ should eq :c_by } - its(:updated_name){ should eq :u_by } + it { subject.user_model.should eq :bar } + it { subject.created_name.should eq :c_by } + it { subject.updated_name.should eq :u_by } end context 'without opts hash' do it { should be_a Mongoid::Userstamp::ModelConfig } - its(:user_model){ should eq 'User' } - its(:created_name){ should eq :created_by } - its(:updated_name){ should eq :updated_by } + it { subject.user_model.should eq 'User' } + it { subject.created_name.should eq :created_by } + it { subject.updated_name.should eq :updated_by } end end end diff --git a/spec/unit/model_spec.rb b/spec/unit/model_spec.rb index a382c8b..e99edae 100644 --- a/spec/unit/model_spec.rb +++ b/spec/unit/model_spec.rb @@ -24,33 +24,33 @@ context 'when options are not given' do subject{ Book.mongoid_userstamp_config } it { should be_a Mongoid::Userstamp::ModelConfig } - its(:user_model) { should eq Admin } - its(:created_name) { should eq :created_by } - its(:updated_name) { should eq :updated_by } + it { subject.user_model.should eq Admin } + it { subject.created_name.should eq :created_by } + it { subject.updated_name.should eq :updated_by } end context 'when options are given' do subject{ Book.mongoid_userstamp_config(user_model: 'User', created_name: :foo, updated_name: :bar) } it { should be_a Mongoid::Userstamp::ModelConfig } - its(:user_model) { should eq 'User' } - its(:created_name) { should eq :foo } - its(:updated_name) { should eq :bar } + it { subject.user_model.should eq 'User' } + it { subject.created_name.should eq :foo } + it { subject.updated_name.should eq :bar } end context 'when mongoid_userstamp_user has been set' do subject{ Book.mongoid_userstamp_config; Book.mongoid_userstamp_config(user_model: 'User', created_name: :foo, updated_name: :bar) } it { should be_a Mongoid::Userstamp::ModelConfig } - its(:user_model) { should eq Admin } - its(:created_name) { should eq :created_by } - its(:updated_name) { should eq :updated_by } + it { subject.user_model.should eq Admin } + it { subject.created_name.should eq :created_by } + it { subject.updated_name.should eq :updated_by } end context 'when set via mongoid_userstamp method' do subject{ Book.mongoid_userstamp(user_model: 'User', created_name: :foo, updated_name: :bar); Book.mongoid_userstamp_config } it { should be_a Mongoid::Userstamp::ModelConfig } - its(:user_model) { should eq 'User' } - its(:created_name) { should eq :foo } - its(:updated_name) { should eq :bar } + it { subject.user_model.should eq 'User' } + it { subject.created_name.should eq :foo } + it { subject.updated_name.should eq :bar } end end diff --git a/spec/unit/user_config_spec.rb b/spec/unit/user_config_spec.rb index 2872a69..dfc22c8 100644 --- a/spec/unit/user_config_spec.rb +++ b/spec/unit/user_config_spec.rb @@ -12,12 +12,12 @@ subject { Mongoid::Userstamp::UserConfig.new({reader: :bar}) } it { should be_a Mongoid::Userstamp::UserConfig } - its(:reader){ should eq :bar } + it { subject.reader.should eq :bar } end context 'without opts hash' do it { should be_a Mongoid::Userstamp::UserConfig } - its(:reader){ should eq :foo } + it { subject.reader.should eq :foo } end end end diff --git a/spec/unit/user_spec.rb b/spec/unit/user_spec.rb index 0b28cb8..64ae267 100644 --- a/spec/unit/user_spec.rb +++ b/spec/unit/user_spec.rb @@ -17,30 +17,30 @@ context 'when current users are not set' do it { Admin.current.should be_nil } it { User.current.should be_nil } - it { admin_1.current?.should be_false } - it { admin_2.current?.should be_false } - it { user_1.current?.should be_false } - it { user_2.current?.should be_false } + it { admin_1.current?.should be_falsey } + it { admin_2.current?.should be_falsey } + it { user_1.current?.should be_falsey } + it { user_2.current?.should be_falsey } end context 'when current User is set' do before{ User.current = user_1 } it { User.current.should eq user_1 } it { Admin.current.should be_nil } - it { admin_1.current?.should be_false } - it { admin_2.current?.should be_false } - it { user_1.current?.should be_true } - it { user_2.current?.should be_false } + it { admin_1.current?.should be_falsey } + it { admin_2.current?.should be_falsey } + it { user_1.current?.should be_truthy } + it { user_2.current?.should be_falsey } end context 'when current Admin is set' do before{ Admin.current = admin_1 } it { User.current.should be_nil } it { Admin.current.should eq admin_1 } - it { admin_1.current?.should be_true } - it { admin_2.current?.should be_false } - it { user_1.current?.should be_false } - it { user_2.current?.should be_false } + it { admin_1.current?.should be_truthy } + it { admin_2.current?.should be_falsey } + it { user_1.current?.should be_falsey } + it { user_2.current?.should be_falsey } end end @@ -77,19 +77,19 @@ context 'when options are not given' do subject{ User.mongoid_userstamp_user } it { should be_a Mongoid::Userstamp::UserConfig } - its(:reader) { should eq :current_user } + it { subject.reader.should eq :current_user } end context 'when options are given' do subject{ User.mongoid_userstamp_user(reader: :foo) } it { should be_a Mongoid::Userstamp::UserConfig } - its(:reader) { should eq :foo } + it { subject.reader.should eq :foo } end context 'when mongoid_userstamp_user has been set' do subject{ User.mongoid_userstamp_user; User.mongoid_userstamp_user(reader: :foo) } it { should be_a Mongoid::Userstamp::UserConfig } - its(:reader) { should eq :current_user } + it { subject.reader.should eq :current_user } end end end diff --git a/spec/unit/userstamp_spec.rb b/spec/unit/userstamp_spec.rb index e3616d0..267a4a6 100644 --- a/spec/unit/userstamp_spec.rb +++ b/spec/unit/userstamp_spec.rb @@ -15,9 +15,9 @@ context 'without block' do subject{ Mongoid::Userstamp.config } it { should be_a Mongoid::Userstamp::GemConfig } - its(:created_name){ should eq :created_by } - its(:updated_name){ should eq :updated_by } - its(:user_reader){ should eq :current_user } + it { subject.created_name.should eq :created_by } + it { subject.updated_name.should eq :updated_by } + it { subject.user_reader.should eq :current_user } end context 'with block' do @@ -29,9 +29,9 @@ end end it { should be_a Mongoid::Userstamp::GemConfig } - its(:created_name){ should eq :c_by } - its(:updated_name){ should eq :u_by } - its(:user_reader){ should eq :foo } + it { subject.created_name.should eq :c_by } + it { subject.updated_name.should eq :u_by } + it { subject.user_reader.should eq :foo } end context 'deprecated method' do @@ -68,28 +68,28 @@ describe '#model_classes' do before { Mongoid::Userstamp.instance_variable_set(:'@model_classes', nil) } context 'default value' do - its(:model_classes){ should eq [] } + it { subject.model_classes.should eq [] } end context 'setting values' do before do subject.add_model_class 'Book' subject.add_model_class 'Post' end - its(:model_classes){ should eq [Book, Post] } + it { subject.model_classes.should eq [Book, Post] } end end describe '#user_classes' do before { Mongoid::Userstamp.instance_variable_set(:'@user_classes', nil) } context 'default value' do - its(:user_classes){ should eq [User] } + it { subject.user_classes.should eq [User] } end context 'setting values' do before do subject.add_user_class 'Book' subject.add_user_class 'Post' end - its(:user_classes){ should eq [Book, Post] } + it { subject.user_classes.should eq [Book, Post] } end end @@ -99,11 +99,11 @@ stub_const('RequestStore', Object.new) RequestStore.stub('store').and_return('foobar') end - its(:store){ should eq RequestStore.store } + it { subject.store.should eq RequestStore.store } end context 'when RequestStore is not defined' do before{ hide_const('RequestStore') } - its(:store){ should eq Thread.current } + it { subject.store.should eq Thread.current } end end From 39105797657fc1dfcc35f0ff06271d78cf71cf6f Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Thu, 31 Jul 2014 04:24:29 +0900 Subject: [PATCH 18/19] Add inverse_of to relations, to prevent ambiguity when the user model has another relation to the userstamped model --- lib/mongoid/userstamp/mixins/model.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mongoid/userstamp/mixins/model.rb b/lib/mongoid/userstamp/mixins/model.rb index 3e6493f..d866d75 100644 --- a/lib/mongoid/userstamp/mixins/model.rb +++ b/lib/mongoid/userstamp/mixins/model.rb @@ -9,8 +9,8 @@ module Model included do - belongs_to mongoid_userstamp_config.created_name, class_name: mongoid_userstamp_config.user_model - belongs_to mongoid_userstamp_config.updated_name, class_name: mongoid_userstamp_config.user_model + belongs_to mongoid_userstamp_config.created_name, class_name: mongoid_userstamp_config.user_model, inverse_of: nil + belongs_to mongoid_userstamp_config.updated_name, class_name: mongoid_userstamp_config.user_model, inverse_of: nil before_create :set_created_by before_save :set_updated_by From 14d4b185d963267754b30af59e65e6d318126d4d Mon Sep 17 00:00:00 2001 From: Johnny Shields Date: Sat, 9 Aug 2014 16:20:26 +0900 Subject: [PATCH 19/19] Do not include Mongoid::Userstamp in "User" class by default. --- CHANGELOG.md | 1 + lib/mongoid/userstamp.rb | 2 +- spec/unit/userstamp_spec.rb | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc7904..da6b9fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Improvement * BREAKING: Change userstamp keys to use Mongoid relations. This will change the underlying database field names, and as such will require a migration. + * BREAKING: Do not include Mongoid::Userstamp in "User" class by default. * Mongoid::Userstamp config initializer is now optional. * Add support for multiple user classes. * Add class-level config override capability for both users and userstamped model classes. diff --git a/lib/mongoid/userstamp.rb b/lib/mongoid/userstamp.rb index 93f95ec..3003daf 100644 --- a/lib/mongoid/userstamp.rb +++ b/lib/mongoid/userstamp.rb @@ -58,7 +58,7 @@ def add_model_class(model) end def user_classes - (@user_classes || ['User']).map{|c| c.is_a?(Class) ? c : c.to_s.classify.constantize } + (@user_classes || []).map{|c| c.is_a?(Class) ? c : c.to_s.classify.constantize } end def add_user_class(user) diff --git a/spec/unit/userstamp_spec.rb b/spec/unit/userstamp_spec.rb index 267a4a6..3a1bf2e 100644 --- a/spec/unit/userstamp_spec.rb +++ b/spec/unit/userstamp_spec.rb @@ -82,7 +82,7 @@ describe '#user_classes' do before { Mongoid::Userstamp.instance_variable_set(:'@user_classes', nil) } context 'default value' do - it { subject.user_classes.should eq [User] } + it { subject.user_classes.should eq [] } end context 'setting values' do before do