timestamped_column 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,16 +1,32 @@
1
- Time-stamped Column
2
- ===================
1
+ # timestamped_column [![Build Status](https://secure.travis-ci.org/JamesBrooks/timestamped_column.png)](http://travis-ci.org/JamesBrooks/timestamped_column>) [![Dependency Status](https://gemnasium.com/JamesBrooks/timestamped_column.png)](https://gemnasium.com/JamesBrooks/timestamped_column)
3
2
 
4
- Records modified time for individual columns.
3
+ Records the modification time for specific database columns on individual records (using ActiveRecord).
5
4
 
6
- Usage (in a model)
7
- ------------------
8
5
 
9
- `timestamped_column :email_address`
6
+ ## Compatibility
10
7
 
11
- Records the most recent modification time of `:email_address` to `:email_address_updated_at` (defaults to `name_updated_at`)
8
+ Tested and works with:
12
9
 
10
+ * Ruby: 1.8.7, 1.9.2, 1.9.3 and REE.
11
+ * Rails: 3.0, 3.1, 3.2 and edge.
13
12
 
14
- `timestamped_column :email_address, :column => :email_address_changed_at`
15
13
 
16
- Records the most recent modification time of `:email_address` to `:email_address_changed_at`
14
+ ## Installation
15
+
16
+ Add `timestamped_column` to your `Gemfile`:
17
+
18
+ ```
19
+ gem 'timestamped_column'
20
+ ```
21
+
22
+
23
+ ## Usage
24
+
25
+ Usage is similar to how `created_at`/`updated_at` function in Rails. All you need to start tracking attribute modification times is to add a new column to store the modification value. The column that tracks the modification value should be suffxed with either `_updated_at` or `_updated_on`.
26
+
27
+
28
+ ## Example
29
+
30
+ If you have a model `User` with an attribute `name` that you want to track the modification time of you just simple add an column named `name_updated_at` (or `name_updated_on`) to the `users` table.
31
+
32
+ `timestamped_column` checked for the presence of columns named like this and automatically updates these when the attributes they track are changed.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ begin
9
+ require 'rdoc/task'
10
+ rescue LoadError
11
+ require 'rdoc/rdoc'
12
+ require 'rake/rdoctask'
13
+ RDoc::Task = Rake::RDocTask
14
+ end
15
+
16
+ require 'rspec/core/rake_task'
17
+ RSpec::Core::RakeTask.new(:spec)
18
+
19
+ RDoc::Task.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'TimestampedColumn'
22
+ rdoc.options << '--line-numbers'
23
+ rdoc.rdoc_files.include('README.rdoc')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ Bundler::GemHelper.install_tasks
28
+
29
+ task :default => :spec
@@ -0,0 +1,57 @@
1
+ module ActiveRecord
2
+ # = Active Record Column Timestamp
3
+ #
4
+ # Automatically timestamps when particular attributes (columns) have been changed
5
+ # if the table has fields suffixed with <tt>_updated_at/_updated_on</tt>
6
+ #
7
+ # Example: A table with a field <tt>user_name</tt> would have it's modification time
8
+ # recorded if a field named <tt>user_name_updated_at</tt> exists.
9
+ module TimestampedColumn
10
+ private
11
+ def create(*args) #:nodoc:
12
+ update_timestamp_attributes
13
+ super
14
+ end
15
+
16
+ def update(*args) #:nodoc:
17
+ update_timestamp_attributes
18
+ super
19
+ end
20
+
21
+ def update_timestamp_attributes #:nodoc:
22
+ current_time = current_time_from_proper_timezone
23
+
24
+ timestamped_attributes_in_model.each do |attribute, timestamp_attribute|
25
+ if attribute_changed?(attribute)
26
+ write_attribute(timestamp_attribute, current_time)
27
+ end
28
+ end
29
+ end
30
+
31
+ def timestamped_attributes_in_model #:nodoc:
32
+ {}.tap do |timestamped_attributes|
33
+ self.class.column_names.each do |column|
34
+ if attribute = timestamp_attribute_for_column(column)
35
+ timestamped_attributes[column] = attribute
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def timestamp_attribute_for_column(column) #:nodoc:
42
+ self.class.column_names.detect { |c| %r{(#{possible_timestamp_attributes_for_column(column).join('|')})$} =~ c }
43
+ end
44
+
45
+ def possible_timestamp_attributes_for_column(column) #:nodoc:
46
+ column_timestamp_attribute_suffixes.map { |suffix| [ column, suffix].join }
47
+ end
48
+
49
+ def column_timestamp_attribute_suffixes #:nodoc:
50
+ ['_updated_at', '_updated_on']
51
+ end
52
+
53
+ def current_time_from_proper_timezone # from ActiveRecord::Timestamp
54
+ self.class.default_timezone == :utc ? Time.now.utc : Time.now
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module TimestampedColumn
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,2 +1,6 @@
1
- require 'active_support/concern'
2
- require 'timestamped_column/active_record'
1
+ require "timestamped_column/version"
2
+ require "timestamped_column/active_record/timestamped_column"
3
+
4
+ module TimestampedColumn
5
+ ActiveRecord::Base.send :include, ActiveRecord::TimestampedColumn
6
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ # attr_accessible :title, :body
3
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ Bundler.require
6
+ require "timestamped_column"
7
+
8
+ module Dummy
9
+ class Application < Rails::Application
10
+ end
11
+ end
12
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ gemfile = File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ if File.exist?(gemfile)
5
+ ENV['BUNDLE_GEMFILE'] = gemfile
6
+ require 'bundler'
7
+ Bundler.setup
8
+ end
9
+
10
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,5 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/test.sqlite3
4
+ pool: 5
5
+ timeout: 5000
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ Dummy::Application.initialize!
@@ -0,0 +1,12 @@
1
+ Dummy::Application.configure do
2
+ config.cache_classes = true
3
+ config.serve_static_assets = true
4
+ config.static_cache_control = "public, max-age=3600"
5
+ config.whiny_nils = true
6
+ config.consider_all_requests_local = true
7
+ config.action_controller.perform_caching = false
8
+ config.action_dispatch.show_exceptions = false
9
+ config.action_controller.allow_forgery_protection = false
10
+ config.action_mailer.delivery_method = :test
11
+ config.active_support.deprecation = :stderr
12
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
@@ -0,0 +1,10 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :name, :email, :phone
5
+ t.datetime :name_updated_at, :email_updated_at
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 20120507214419) do
15
+
16
+ create_table "users", :force => true do |t|
17
+ t.string "name"
18
+ t.string "email"
19
+ t.string "phone"
20
+ t.datetime "name_updated_at"
21
+ t.datetime "email_updated_at"
22
+ t.datetime "created_at", :null => false
23
+ t.datetime "updated_at", :null => false
24
+ end
25
+
26
+ end
Binary file
@@ -0,0 +1,133 @@
1
+ SQL (0.2ms)  SELECT name
2
+ FROM sqlite_master
3
+ WHERE type = 'table' AND NOT name = 'sqlite_sequence'
4
+ 
5
+ SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.011480', NULL, NULL, 'Joe User', '2012-05-08 15:57:16.009622', NULL, '2012-05-08 15:57:16.011480')
6
+ SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.054429', NULL, NULL, 'Joe User', '2012-05-08 15:57:16.026902', NULL, '2012-05-08 15:57:16.054429')
7
+ SQL (0.4ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.060055', 'joe.user@email.com', '2012-05-08 15:57:16.058203', 'Joe User', '2012-05-08 15:57:16.058203', '123-456-7890', '2012-05-08 15:57:16.060055')
8
+ SQL (0.4ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.070242', 'joe.user@email.com', '2012-05-08 15:57:16.068367', 'Joe User', '2012-05-08 15:57:16.068367', '123-456-7890', '2012-05-08 15:57:16.070242')
9
+ SQL (0.4ms) UPDATE "users" SET "phone" = '000-000-0000', "updated_at" = '2012-05-08 15:57:16.075703' WHERE ("users"."id" = 1)
10
+ SQL (0.4ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.081214', 'joe.user@email.com', '2012-05-08 15:57:16.079271', 'Joe User', '2012-05-08 15:57:16.079271', '123-456-7890', '2012-05-08 15:57:16.081214')
11
+ SQL (0.4ms) UPDATE "users" SET "phone" = '000-000-0000', "updated_at" = '2012-05-08 15:57:16.084974' WHERE ("users"."id" = 1)
12
+ SQL (0.4ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.090262', 'joe.user@email.com', '2012-05-08 15:57:16.088239', 'Joe User', '2012-05-08 15:57:16.088239', '123-456-7890', '2012-05-08 15:57:16.090262')
13
+ SQL (0.4ms) UPDATE "users" SET "name" = 'John Blogs', "name_updated_at" = '2012-05-08 16:57:16.092567', "updated_at" = '2012-05-08 16:57:16.094518' WHERE ("users"."id" = 1)
14
+ SQL (0.3ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.100080', 'joe.user@email.com', '2012-05-08 15:57:16.098232', 'Joe User', '2012-05-08 15:57:16.098232', '123-456-7890', '2012-05-08 15:57:16.100080')
15
+ SQL (0.4ms) UPDATE "users" SET "name" = 'John Blogs', "name_updated_at" = '2012-05-08 16:57:16.102151', "updated_at" = '2012-05-08 16:57:16.104267' WHERE ("users"."id" = 1)
16
+ SQL (0.4ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES ('2012-05-08 15:57:16.111782', 'joe.user@email.com', '2012-05-08 15:57:16.109988', 'Joe User', '2012-05-08 15:57:16.109988', '123-456-7890', '2012-05-08 15:57:16.111782')
17
+ SQL (0.4ms) UPDATE "users" SET "name_updated_at" = '2012-05-07 15:57:16.113431', "updated_at" = '2012-05-08 15:57:16.118064' WHERE ("users"."id" = 1)
18
+  (0.5ms) begin transaction
19
+  (0.1ms) rollback transaction
20
+  (0.1ms) begin transaction
21
+  (0.1ms) rollback transaction
22
+  (0.1ms) begin transaction
23
+  (0.0ms) SAVEPOINT active_record_1
24
+ SQL (9.1ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", nil], ["email_updated_at", nil], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", nil], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
25
+  (0.1ms) RELEASE SAVEPOINT active_record_1
26
+  (0.5ms) rollback transaction
27
+  (0.1ms) begin transaction
28
+  (0.0ms) rollback transaction
29
+  (0.0ms) begin transaction
30
+  (0.0ms) SAVEPOINT active_record_1
31
+ SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", nil], ["email_updated_at", nil], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", nil], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
32
+  (0.0ms) RELEASE SAVEPOINT active_record_1
33
+  (10.5ms) rollback transaction
34
+  (0.1ms) begin transaction
35
+  (0.1ms) SAVEPOINT active_record_1
36
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
37
+  (0.0ms) RELEASE SAVEPOINT active_record_1
38
+  (2.4ms) rollback transaction
39
+  (0.1ms) begin transaction
40
+  (0.0ms) SAVEPOINT active_record_1
41
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
42
+  (0.0ms) RELEASE SAVEPOINT active_record_1
43
+  (0.1ms) SAVEPOINT active_record_1
44
+  (0.5ms) UPDATE "users" SET "phone" = '000-000-0000', "updated_at" = '2012-05-08 15:59:37.252409' WHERE "users"."id" = 1
45
+  (0.0ms) RELEASE SAVEPOINT active_record_1
46
+  (0.6ms) rollback transaction
47
+  (0.1ms) begin transaction
48
+  (0.0ms) SAVEPOINT active_record_1
49
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
50
+  (0.0ms) RELEASE SAVEPOINT active_record_1
51
+  (0.0ms) SAVEPOINT active_record_1
52
+  (0.4ms) UPDATE "users" SET "phone" = '000-000-0000', "updated_at" = '2012-05-08 15:59:37.263297' WHERE "users"."id" = 1
53
+  (0.0ms) RELEASE SAVEPOINT active_record_1
54
+  (2.8ms) rollback transaction
55
+  (0.1ms) begin transaction
56
+  (0.1ms) SAVEPOINT active_record_1
57
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
58
+  (0.1ms) RELEASE SAVEPOINT active_record_1
59
+  (2.7ms) rollback transaction
60
+  (0.1ms) begin transaction
61
+  (0.0ms) SAVEPOINT active_record_1
62
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
63
+  (0.0ms) RELEASE SAVEPOINT active_record_1
64
+  (3.1ms) rollback transaction
65
+  (0.1ms) begin transaction
66
+  (0.0ms) SAVEPOINT active_record_1
67
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:37 UTC +00:00]]
68
+  (0.0ms) RELEASE SAVEPOINT active_record_1
69
+  (0.1ms) SAVEPOINT active_record_1
70
+  (0.4ms) UPDATE "users" SET "name_updated_at" = '2012-05-07 15:59:37.289174', "updated_at" = '2012-05-08 15:59:37.293176' WHERE "users"."id" = 1
71
+  (0.0ms) RELEASE SAVEPOINT active_record_1
72
+  (0.6ms) rollback transaction
73
+  (0.5ms) begin transaction
74
+  (0.1ms) rollback transaction
75
+  (0.1ms) begin transaction
76
+  (0.1ms) rollback transaction
77
+  (0.1ms) begin transaction
78
+  (0.0ms) SAVEPOINT active_record_1
79
+ SQL (5.0ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["email", nil], ["email_updated_at", nil], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["phone", nil], ["updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00]]
80
+  (0.1ms) RELEASE SAVEPOINT active_record_1
81
+  (0.6ms) rollback transaction
82
+  (0.1ms) begin transaction
83
+  (0.1ms) rollback transaction
84
+  (0.0ms) begin transaction
85
+  (0.0ms) SAVEPOINT active_record_1
86
+ SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["email", nil], ["email_updated_at", nil], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["phone", nil], ["updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00]]
87
+  (0.1ms) RELEASE SAVEPOINT active_record_1
88
+  (0.6ms) rollback transaction
89
+  (0.1ms) begin transaction
90
+  (0.0ms) SAVEPOINT active_record_1
91
+ SQL (0.9ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00]]
92
+  (0.1ms) RELEASE SAVEPOINT active_record_1
93
+  (0.5ms) rollback transaction
94
+  (0.1ms) begin transaction
95
+  (0.0ms) SAVEPOINT active_record_1
96
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00]]
97
+  (0.1ms) RELEASE SAVEPOINT active_record_1
98
+  (0.1ms) SAVEPOINT active_record_1
99
+  (0.5ms) UPDATE "users" SET "phone" = '000-000-0000', "updated_at" = '2012-05-08 15:59:53.987355' WHERE "users"."id" = 1
100
+  (0.0ms) RELEASE SAVEPOINT active_record_1
101
+  (0.6ms) rollback transaction
102
+  (0.1ms) begin transaction
103
+  (0.1ms) SAVEPOINT active_record_1
104
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:53 UTC +00:00]]
105
+  (0.0ms) RELEASE SAVEPOINT active_record_1
106
+  (0.0ms) SAVEPOINT active_record_1
107
+  (0.4ms) UPDATE "users" SET "phone" = '000-000-0000', "updated_at" = '2012-05-08 15:59:53.998711' WHERE "users"."id" = 1
108
+  (0.1ms) RELEASE SAVEPOINT active_record_1
109
+  (0.5ms) rollback transaction
110
+  (0.1ms) begin transaction
111
+  (0.0ms) SAVEPOINT active_record_1
112
+ SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00]]
113
+  (0.0ms) RELEASE SAVEPOINT active_record_1
114
+  (0.1ms) SAVEPOINT active_record_1
115
+  (0.4ms) UPDATE "users" SET "name" = 'John Blogs', "name_updated_at" = '2012-05-08 16:59:54.006275', "updated_at" = '2012-05-08 16:59:54.008192' WHERE "users"."id" = 1
116
+  (0.0ms) RELEASE SAVEPOINT active_record_1
117
+  (0.9ms) rollback transaction
118
+  (0.1ms) begin transaction
119
+  (0.0ms) SAVEPOINT active_record_1
120
+ SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00]]
121
+  (0.0ms) RELEASE SAVEPOINT active_record_1
122
+  (0.1ms) SAVEPOINT active_record_1
123
+  (0.4ms) UPDATE "users" SET "name" = 'John Blogs', "name_updated_at" = '2012-05-08 16:59:54.016571', "updated_at" = '2012-05-08 16:59:54.018614' WHERE "users"."id" = 1
124
+  (0.0ms) RELEASE SAVEPOINT active_record_1
125
+  (0.6ms) rollback transaction
126
+  (0.1ms) begin transaction
127
+  (0.1ms) SAVEPOINT active_record_1
128
+ SQL (0.8ms) INSERT INTO "users" ("created_at", "email", "email_updated_at", "name", "name_updated_at", "phone", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["email", "joe.user@email.com"], ["email_updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["name", "Joe User"], ["name_updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00], ["phone", "123-456-7890"], ["updated_at", Tue, 08 May 2012 15:59:54 UTC +00:00]]
129
+  (0.1ms) RELEASE SAVEPOINT active_record_1
130
+  (0.1ms) SAVEPOINT active_record_1
131
+  (0.4ms) UPDATE "users" SET "name_updated_at" = '2012-05-07 15:59:54.026696', "updated_at" = '2012-05-08 15:59:54.030661' WHERE "users"."id" = 1
132
+  (0.0ms) RELEASE SAVEPOINT active_record_1
133
+  (0.6ms) rollback transaction
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,5 @@
1
+ FactoryGirl.define do
2
+ factory :user do
3
+ name 'Joe User'
4
+ end
5
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'User with timestamped columns' do
4
+ describe 'Sanity' do
5
+ before(:each) do
6
+ @user = FactoryGirl.build(:user)
7
+ end
8
+
9
+ it 'should initialize' do
10
+ @user.should be_a_kind_of User
11
+ end
12
+
13
+ it 'should have the specified factory defaults' do
14
+ @user.name.should match 'Joe User'
15
+ @user.email.should be_nil
16
+ @user.phone.should be_nil
17
+ end
18
+
19
+ it 'should persist' do
20
+ @user.save
21
+ @user.should be_persisted
22
+ end
23
+ end
24
+
25
+
26
+ describe 'Non-persisted models' do
27
+ before(:each) do
28
+ @user = FactoryGirl.build(:user)
29
+ end
30
+
31
+ it 'should not have timestamped columns set' do
32
+ @user.name_updated_at.should be_nil
33
+ @user.email_updated_at.should be_nil
34
+ end
35
+ end
36
+
37
+
38
+ describe 'Persisting models' do
39
+ before(:each) do
40
+ @user = FactoryGirl.build(:user)
41
+ end
42
+
43
+ it 'should set timestamped column values on create for attributes with set values' do
44
+ @user.save
45
+
46
+ @user.name_updated_at.should be_a_kind_of Time
47
+ @user.email_updated_at.should be_nil
48
+ end
49
+
50
+ it 'should set timestamped column values for multiple attributes' do
51
+ @user.email = 'joe.user@email.com'
52
+ @user.phone = '123-456-7890'
53
+ @user.save
54
+
55
+ @user.name_updated_at.should be_a_kind_of Time
56
+ @user.email_updated_at.should be_a_kind_of Time
57
+ end
58
+ end
59
+
60
+ describe 'Updating models' do
61
+ before(:each) do
62
+ @user = FactoryGirl.create(:user, {
63
+ :email => 'joe.user@email.com',
64
+ :phone => '123-456-7890'
65
+ })
66
+ end
67
+
68
+ it 'should update non-timestamped fields without updating any timestamped fields (part 1)' do
69
+ expect {
70
+ @user.phone = '000-000-0000'
71
+ @user.save
72
+ }.to_not change { @user.name_updated_at }
73
+ end
74
+
75
+ it 'should update non-timestamped fields without updating any timestamped fields (part 2)' do
76
+ expect {
77
+ @user.phone = '000-000-0000'
78
+ @user.save
79
+ }.to_not change { @user.email_updated_at }
80
+ end
81
+
82
+ it 'should update an attributes timestamped column if the attribute changes' do
83
+ in_the_future do
84
+ expect {
85
+ @user.name = 'John Blogs'
86
+ @user.save
87
+ }.to change { @user.name_updated_at }
88
+ end
89
+ end
90
+
91
+ it 'should not update another timestamp column if a different timestamped attribute changes' do
92
+ in_the_future do
93
+ expect {
94
+ @user.name = 'John Blogs'
95
+ @user.save
96
+ }.to_not change { @user.email_updated_at }
97
+ end
98
+ end
99
+
100
+ it 'should allow updating of timestamp columns without complaint' do
101
+ time = 1.day.ago
102
+
103
+ @user.name_updated_at = time
104
+ @user.name_updated_at.should equal time
105
+
106
+ @user.save
107
+ @user.name_updated_at.should equal time
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,14 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+
3
+ require File.expand_path("../dummy/config/environment", __FILE__)
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+ require 'factory_girl_rails'
7
+ require 'timecop'
8
+
9
+ Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
10
+
11
+ RSpec.configure do |config|
12
+ config.use_transactional_fixtures = true
13
+ config.infer_base_class_for_anonymous_controllers = false
14
+ end
@@ -0,0 +1,5 @@
1
+ def in_the_future
2
+ Timecop.travel(1.hour.from_now) do
3
+ yield
4
+ end
5
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timestamped_column
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,42 +9,94 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-23 00:00:00.000000000Z
12
+ date: 2012-05-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70338618301700 !ruby/object:Gem::Requirement
16
+ requirement: &70095850747460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: '3.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70338618301700
24
+ version_requirements: *70095850747460
25
25
  - !ruby/object:Gem::Dependency
26
- name: activesupport
27
- requirement: &70338618301280 !ruby/object:Gem::Requirement
26
+ name: sqlite3
27
+ requirement: &70095850746380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
- - - ! '>='
30
+ - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :runtime
32
+ version: 1.3.6
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70095850746380
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec-rails
38
+ requirement: &70095850745760 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '2.10'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70095850745760
47
+ - !ruby/object:Gem::Dependency
48
+ name: factory_girl_rails
49
+ requirement: &70095850744840 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70095850744840
58
+ - !ruby/object:Gem::Dependency
59
+ name: timecop
60
+ requirement: &70095850744260 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 0.3.5
66
+ type: :development
34
67
  prerelease: false
35
- version_requirements: *70338618301280
36
- description: Records modified time for individual columns.
68
+ version_requirements: *70095850744260
69
+ description: Records modification time for specified database columns on a per-row
70
+ basis (ActiveRecord).
37
71
  email:
38
72
  - james@jamesbrooks.net
39
73
  executables: []
40
74
  extensions: []
41
75
  extra_rdoc_files: []
42
76
  files:
43
- - lib/timestamped_column/active_record.rb
77
+ - lib/timestamped_column/active_record/timestamped_column.rb
44
78
  - lib/timestamped_column/version.rb
45
79
  - lib/timestamped_column.rb
46
80
  - MIT-LICENSE
81
+ - Rakefile
47
82
  - README.md
83
+ - spec/dummy/app/models/user.rb
84
+ - spec/dummy/config/application.rb
85
+ - spec/dummy/config/boot.rb
86
+ - spec/dummy/config/database.yml
87
+ - spec/dummy/config/environment.rb
88
+ - spec/dummy/config/environments/test.rb
89
+ - spec/dummy/config.ru
90
+ - spec/dummy/db/migrate/20120507214419_create_users.rb
91
+ - spec/dummy/db/schema.rb
92
+ - spec/dummy/db/test.sqlite3
93
+ - spec/dummy/log/test.log
94
+ - spec/dummy/Rakefile
95
+ - spec/dummy/script/rails
96
+ - spec/factories/user.rb
97
+ - spec/models/user_spec.rb
98
+ - spec/spec_helper.rb
99
+ - spec/support/timecop.rb
48
100
  homepage: https://github.com/JamesBrooks/timestamped_column
49
101
  licenses: []
50
102
  post_install_message:
@@ -65,8 +117,25 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
117
  version: '0'
66
118
  requirements: []
67
119
  rubyforge_project:
68
- rubygems_version: 1.8.6
120
+ rubygems_version: 1.8.17
69
121
  signing_key:
70
122
  specification_version: 3
71
- summary: Records modified time for individual columns.
72
- test_files: []
123
+ summary: Records column modification times.
124
+ test_files:
125
+ - spec/dummy/app/models/user.rb
126
+ - spec/dummy/config/application.rb
127
+ - spec/dummy/config/boot.rb
128
+ - spec/dummy/config/database.yml
129
+ - spec/dummy/config/environment.rb
130
+ - spec/dummy/config/environments/test.rb
131
+ - spec/dummy/config.ru
132
+ - spec/dummy/db/migrate/20120507214419_create_users.rb
133
+ - spec/dummy/db/schema.rb
134
+ - spec/dummy/db/test.sqlite3
135
+ - spec/dummy/log/test.log
136
+ - spec/dummy/Rakefile
137
+ - spec/dummy/script/rails
138
+ - spec/factories/user.rb
139
+ - spec/models/user_spec.rb
140
+ - spec/spec_helper.rb
141
+ - spec/support/timecop.rb
@@ -1,36 +0,0 @@
1
- module TimestampedColumn
2
- module ActiveRecord
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- before_save :update_timestamped_column_times
7
- cattr_accessor :timestamped_columns
8
- end
9
-
10
- module ClassMethods
11
- def timestamped_column(column, opts={})
12
- timestamp_column = opts[:column] || "#{column}_updated_at"
13
-
14
- self.timestamped_columns ||= {}
15
- self.timestamped_columns[column] = timestamp_column
16
- end
17
- end
18
-
19
- module InstanceMethods
20
- private
21
- def update_timestamped_column_times
22
- if self.timestamped_columns && changes.any?
23
- self.timestamped_columns.each do |column, timestamp_column|
24
- if changes[column.to_s]
25
- send "#{timestamp_column}=", Time.zone.now
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
33
-
34
- class ActiveRecord::Base
35
- include TimestampedColumn::ActiveRecord
36
- end