Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

* Finished a few more test. Still could use more but I need to think …

…of a good way to test this (cucumber, maybe?)

* Added `pry` gem
  • Loading branch information...
commit de68ad9a61724de014118645798e22da751149cf 1 parent a4e8543
@coryschires coryschires authored
View
8 Gemfile.lock
@@ -36,6 +36,7 @@ GEM
multi_json (~> 1.0)
arel (3.0.2)
builder (3.0.0)
+ coderay (1.0.7)
diff-lcs (1.1.3)
erubis (2.7.0)
hike (1.2.1)
@@ -49,9 +50,14 @@ GEM
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
+ method_source (0.8)
mime-types (1.19)
multi_json (1.3.6)
polyglot (0.3.3)
+ pry (0.9.10)
+ coderay (~> 1.0.5)
+ method_source (~> 0.8)
+ slop (~> 3.3.1)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
@@ -90,6 +96,7 @@ GEM
activesupport (>= 3.0)
railties (>= 3.0)
rspec (~> 2.11.0)
+ slop (3.3.2)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
@@ -107,6 +114,7 @@ PLATFORMS
DEPENDENCIES
jquery-rails
+ pry
rspec-rails
sqlite3
timber!
View
65 README.rdoc
@@ -7,7 +7,7 @@ Timber helps you create flexible, unobtrusive activity logs using rails notifica
Frank published "Autumnal Bliss"
Andy... and so on
-=== Installation
+== Installation
Include the gem to your Gemfile:
gem 'timber'
@@ -15,7 +15,7 @@ Install and run the necessary migrations:
rake timber_engine:install:migrations
rake db:migrate
-=== Usage
+== Usage
Let's say your application has authors, posts, and publishers:
class Author < ActiveRecord::Base
@@ -35,10 +35,9 @@ Let's say your application has authors, posts, and publishers:
And you want to create a log item whenever a post is created or updated.
-First, you need to set up an initializer at +config/initializers/timber.rb+:
+First, you need to set up an initializer at +config/initializers/timber.rb+.
Timber.registration do
-
subscribe "posts#create" do |event|
post = Post.find_by_title(event.params[:post][:title])
Timber::Activity.create(
@@ -48,50 +47,56 @@ First, you need to set up an initializer at +config/initializers/timber.rb+:
parameters: { author_name: post.author.name }
)
end
+ end
- subscribe "posts#update" do |event|
- post = Post.find(event.params[:post_id])
- Timber::Activity.create(
- trackable: post,
- owner: post.publisher,
- key: "timber.posts.update",
- parameters: {
- author_name: post.author.name,
- editorial_comment: 'Corrected misspelling'
- }
- )
- end
+Inside the +Timber.registration+ block, you can +subscribe+ to as many +controller#action+ events as you like. In order to create an activity record, each subscription should include a call to <tt>Timber::Activity.create</tt>:
- end
+ Timber::Activity.create(
+ # The object being acted on (i.e. created, updated, etc.). Polymorphic association.
+ trackable: post,
-Next, create a yaml file to specify your templates in +config/locales/timber+:
+ # The object being acted on (i.e. created, updated, etc.). Polymorphic association.
+ owner: post.publisher,
+
+ # The key path to use when looking up the text template in +timber.en.yml+
+ key: "timber.posts.create",
+
+ # A serialized hash of arbitrary data. This is a good place to stuff miscellaneous
+ # data in order to cut down on database queries when rendering the activity +text+.
+ # But keep in mind that {active record doesn't make it easy to query serialized
+ parameters: { author_name: post.author.name }
+ )
+
+
+Next, create a yaml file to specify your templates in +config/locales/timber.en.yml+. Within this file, you have access to the activity instance, allowing you to make dynamic activity messages:
- # Within in a given snippet, you can interpolate values by calling methods off the activity:
- #
timber:
posts:
create: "<%= owner.name %> created a post titled <%= trackable.title %>"
update: "<%= owner.name %> edited <%= trackable.title %>: <%= parameters[:editorial_comment] %>"
-Add an association in your model:
+Then you'll need to somehow fetch a collection of activities. Timber deliberately add no magical methods to you models; you'll need to write them yourself. An +activities+ association, for example, might look like:
- class Publisher
- has_many :activities, foreign_key: :owner_id, class_name: 'Timber::Activity'
- end
+ has_many :activities, foreign_key: :owner_id, class_name: 'Timber::Activity'
-And display the log items in your view:
+Finally, you need to display the activities in your view:
<ul>
- <%= @publisher.activities.each do |item| %>
- <li><% item.text %></li>
+ <% @publisher.activities.each do |item| %>
+ <li><%= item.text %></li>
<% end %>
</ul>
-=== More about the <tt>Timber::Activity</tt> model
+== Contributing
+Fork the project, make your changes, and submit a pull request. Please ensure the tests pass:
+
+ rspec .
+
+This gem is a based on {public_activity}[https://github.com/pokonski/public_activity]. Thanks to @pokonski for his good ideas, especially the use of i18n for generating the activity text.
-+Timber::Activity+ has two polymorphic associations: +trackable+ and +owner+. You're free to use them however you like. That said, the +trackable+ associations is intended to be the object that is being acted on (i.e. created, updated, destroyed, etc).
+== License
-+Timber::Activity+ also includes a serialized +parameters+ column. This is a good place to stuff miscellaneous data in order to cut down on database queries when rendering the activity +text+. But keep in mind that {active record doesn't make it easy to query serialized data}[http://stackoverflow.com/questions/9814622/].
+This project uses {MIT-LICENSE}[https://github.com/scholastica/timber/blob/master/MIT-LICENSE].
View
33 app/models/timber/activity.rb
@@ -8,38 +8,37 @@ class Activity < ActiveRecord::Base
attr_accessible :key, :owner, :parameters, :trackable
def self.template
- YAML.load_file("#{Rails.root}/config/locales/activity_logger.en.yml")
+ YAML.load_file("#{Rails.root}/config/locales/timber.en.yml")
end
def text(params = {})
begin
- erb_template = resolveTemplate(key)
- if !erb_template.nil?
- parameters.merge! params
+ erb_template = resolve_template(key)
+ if erb_template.nil?
+ "Could not locate template"
+ else
+ parameters.merge!(params)
renderer = ERB.new(erb_template)
renderer.result(binding)
- else
- "Template not defined"
end
- rescue
- "Template not defined"
+ rescue => error
+ Rails.logger.warn error.message
+ puts error.message
+ puts error.backtrace
+ "There was a problem rendering activity message"
end
end
private
- def resolveTemplate(key)
- res = nil
- if !self.template.nil?
+ def resolve_template(key)
+ snippet = nil
+ unless Activity.template.nil?
key.split(".").each do |k|
- if res.nil?
- res = self.template[k]
- else
- res = res[k]
- end
+ snippet = snippet.nil? ? Activity.template[k] : snippet[k]
end
end
- res
+ snippet
end
end
View
BIN  doc/timber.psd
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
65 spec/dummy/app/controllers/users_controller.rb
@@ -1,83 +1,46 @@
class UsersController < ApplicationController
- # GET /users
- # GET /users.json
+
+ def events
+ @user = User.find(params[:id])
+ @activities = @user.activities
+ end
+
def index
@users = User.all
-
- respond_to do |format|
- format.html # index.html.erb
- format.json { render json: @users }
- end
end
- # GET /users/1
- # GET /users/1.json
def show
@user = User.find(params[:id])
-
- respond_to do |format|
- format.html # show.html.erb
- format.json { render json: @user }
- end
end
- # GET /users/new
- # GET /users/new.json
def new
@user = User.new
-
- respond_to do |format|
- format.html # new.html.erb
- format.json { render json: @user }
- end
end
- # GET /users/1/edit
def edit
@user = User.find(params[:id])
end
- # POST /users
- # POST /users.json
def create
@user = User.new(params[:user])
-
- respond_to do |format|
- if @user.save
- format.html { redirect_to @user, notice: 'User was successfully created.' }
- format.json { render json: @user, status: :created, location: @user }
- else
- format.html { render action: "new" }
- format.json { render json: @user.errors, status: :unprocessable_entity }
- end
+ if @user.save
+ redirect_to @user, notice: 'User was successfully created.'
+ else
+ render :new
end
end
- # PUT /users/1
- # PUT /users/1.json
def update
@user = User.find(params[:id])
-
- respond_to do |format|
- if @user.update_attributes(params[:user])
- format.html { redirect_to @user, notice: 'User was successfully updated.' }
- format.json { head :no_content }
- else
- format.html { render action: "edit" }
- format.json { render json: @user.errors, status: :unprocessable_entity }
- end
+ if @user.update_attributes(params[:user])
+ redirect_to @user, notice: 'User was successfully updated.'
+ else
+ render :edit
end
end
- # DELETE /users/1
- # DELETE /users/1.json
def destroy
@user = User.find(params[:id])
@user.destroy
-
- respond_to do |format|
- format.html { redirect_to users_url }
- format.json { head :no_content }
- end
end
end
View
1  spec/dummy/app/models/user.rb
@@ -1,3 +1,4 @@
class User < ActiveRecord::Base
attr_accessible :name
+ has_many :activities, foreign_key: :owner_id, class_name: 'Timber::Activity'
end
View
1  spec/dummy/app/views/layouts/application.html.erb
@@ -11,6 +11,7 @@
<nav>
<%= link_to "Users", users_path %>
<%= link_to "Posts", posts_path %>
+ <%= link_to "Events", events_user_path(current_user) %>
</nav>
<%= yield %>
View
16 spec/dummy/app/views/posts/_form.html.erb
@@ -11,6 +11,22 @@
</div>
<% end %>
+ <div class="field">
+ <%= f.label :title %><br />
+ <%= f.text_field :title %>
+ </div>
+
+ <div class="field">
+ <%= f.label :author %><br />
+ <%= f.text_field :author %>
+ </div>
+
+ <div class="field">
+ <%= f.label :text %><br />
+ <%= f.text_area :text %>
+ </div>
+
+
<div class="actions">
<%= f.submit %>
</div>
View
4 spec/dummy/app/views/posts/index.html.erb
@@ -2,6 +2,8 @@
<table>
<tr>
+ <th>Title</th>
+ <th>Author</th>
<th></th>
<th></th>
<th></th>
@@ -9,6 +11,8 @@
<% @posts.each do |post| %>
<tr>
+ <td><%= post.title %></td>
+ <td><%= post.author %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
View
5 spec/dummy/app/views/users/events.html.erb
@@ -0,0 +1,5 @@
+<ul>
+ <% @activities.each do |activity| %>
+ <li><%= activity.text.html_safe %></li>
+ <% end %>
+</ul>
View
12 spec/dummy/config/initializers/timber.rb
@@ -5,7 +5,17 @@
Timber::Activity.create(
trackable: post,
owner: event.current_user,
- key: "timber.post.create",
+ key: "timber.posts.create",
+ parameters: { user_name: event.current_user.name }
+ )
+ end
+
+ subscribe "posts#update" do |event|
+ post = Post.find(event.params[:id])
+ Timber::Activity.create(
+ trackable: post,
+ owner: event.current_user,
+ key: "timber.posts.update",
parameters: { user_name: event.current_user.name }
)
end
View
3  spec/dummy/config/locales/timber.en.yml
@@ -1,3 +1,4 @@
timber:
- post:
+ posts:
create: "<%= owner.name %> created a post: &ldquo;<%= trackable.title %>&rdquo;"
+ update: "<%= owner.name %> updated a post: &ldquo;<%= trackable.title %>&rdquo;"
View
6 spec/dummy/config/routes.rb
@@ -1,6 +1,10 @@
Dummy::Application.routes.draw do
- resources :users
+
root to: "posts#index"
resources :posts
+ resources :users do
+ get :events, on: :member
+ end
+
end
View
1  spec/spec_helper.rb
@@ -3,6 +3,7 @@
require File.expand_path("../dummy/config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
+require 'pry'
ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
Dir[File.join(ENGINE_RAILS_ROOT, 'spec/support/**/*.rb')].each { |f| require f }
View
26 spec/timber/timber_spec.rb
@@ -25,7 +25,33 @@
it "should set the params hash" do
@activity.parameters[:user_name].should == "Willa Cather"
end
+ it "should set the activity text" do
+ @activity.text.should == "Willa Cather created a post: &ldquo;Neighbour Rosicky&rdquo;"
+ end
end
+ describe "posts#update" do
+ before(:all) do
+ @post = Post.create(title: "My Antonia", text: "Last summer...", author: "Willa Cather")
+ @activity = publish_notification(
+ controller: "posts",
+ action: "update",
+ current_user: @current_user,
+ params: { id: @post.id }
+ )
+ end
+ it "should set the owner association" do
+ @activity.owner.should == @current_user
+ end
+ it "should set the trackable association" do
+ @activity.trackable.should == @post
+ end
+ it "should set the params hash" do
+ @activity.parameters[:user_name].should == "Willa Cather"
+ end
+ it "should set the activity text" do
+ @activity.text.should == "Willa Cather update a post: &ldquo;My Antonia&rdquo;"
+ end
+ end
end
View
1  timber.gemspec
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
s.add_dependency "rails", "~> 3.2.3"
+ s.add_development_dependency "pry"
s.add_development_dependency "sqlite3"
s.add_development_dependency "rspec-rails"
end
Please sign in to comment.
Something went wrong with that request. Please try again.