public_activity 0.3.4 → 0.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,12 +2,4 @@ source :rubygems
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'rails'
6
- gem 'yard'
7
- gem 'pusher'
8
-
9
- group :development, :test do
10
- gem 'rspec'
11
- gem 'sqlite3'
12
- gem 'rspec-rails'
13
- end
5
+ gem 'yard'
data/README.md CHANGED
@@ -5,53 +5,52 @@ Simply put: it records what has been changed or edited and gives you the ability
5
5
 
6
6
  ## Example
7
7
 
8
- A picture is worth a thousand words, so here is a visual representation of what this gem is about:
8
+ Here is a simple example showing what this gem is about:
9
9
 
10
10
  ![Example usage](http://i.imgur.com/uGPSm.png)
11
11
 
12
- ## Installation
12
+ ## Upgrading to 0.4
13
+
14
+ If you are using versions earlier than 0.4.0 please click [here](#upgrading) or scroll to the "Upgrading" section at the bottom of this README.
15
+
16
+ ## First time setup
17
+
18
+ ### Gem installation
19
+
20
+ You can install `public_activity` as you would any other gem:
13
21
 
14
- You can install this gem as you would any other gem:
15
22
  gem install public_activity
23
+
16
24
  or in your Gemfile:
25
+
17
26
  gem 'public_activity'
18
27
 
19
- ## Usage
28
+ ### Database setup
20
29
 
21
- Create migration for activities (in your Rails project):
30
+ Create migration for activities and migrate the database (in your Rails project):
22
31
 
23
32
  rails g public_activity:migration
24
33
  rake db:migrate
25
34
 
26
- Add 'tracked' to the model you want to keep track of:
35
+ ### Model configuration
36
+
37
+ Include `PublicActivity::Model` and add `tracked` to the model you want to keep track of:
27
38
 
28
39
  ```ruby
29
40
  class Article < ActiveRecord::Base
41
+ include PublicActivity::Model
30
42
  tracked
31
43
  end
32
44
  ```
33
45
 
34
- To default the owner to the current user (optional)
46
+ And now, by default create/update/destroy activities are recorded in activities table. This is all you need to start recording activities for basic CRUD actions.
35
47
 
36
- ```ruby
37
- #Aplication Controller
38
- before_filter :define_current_user
48
+ ### Displaying activities
39
49
 
40
- def define_current_user
41
- User.current_user = current_user
42
- end
43
-
44
- #User.rb (model)
45
- class User < ActiveRecord::Base
46
- cattr_accessor :current_user
47
- end
48
- ```
49
-
50
- And now, by default create/update/destroy activities are recorded in activities table.
51
- To display them you can do a simple query:
50
+ To display them you simply query the `PublicActivity::Activity` ActiveRecord model:
52
51
 
53
52
  ```ruby
54
- # some_controller.rb
53
+ # notifications_controller.rb
55
54
  def index
56
55
  @activities = PublicActivity::Activity.all
57
56
  end
@@ -60,12 +59,39 @@ end
60
59
  And in your views:
61
60
 
62
61
  ```erb
63
- <% for activity in @activities %>
64
- <%= activity.text %><br/>
62
+ <%= for activity in @activities %>
63
+ <%= render_activity(activity) %>
64
+ <% end %>
65
+ ```
66
+
67
+ *Note*: `render_activity` is a helper for use in view templates. `render_activity(activity)` can be written as `activity.render(self)` and it will have the same meaning.
68
+
69
+ You can also pass options to both `activity#render` and `#render_activity` methods, which are passed deeper to the `render_partial` method.
70
+ A useful example would be to render activities wrapped in layout, which shares common elements of an activity, like a timestamp, owner's avatar etc.
71
+
72
+ ```erb
73
+ <%= for activity in @activities %>
74
+ <%= render_activity(activity, :layout => :activity) %>
65
75
  <% end %>
66
76
  ```
67
77
 
68
- The only thing left is to add templates (config/pba.yml), for example:
78
+ The activity will be wrapped with the `app/views/layouts/activity` layout, in the above example.
79
+
80
+ ### Activity views
81
+
82
+ Since version `0.4.0` you can use views to render activities. `public_activity` looks for views in `app/views/public_activity`, and this is now the *default* behaviour.
83
+
84
+ For example, if you have an activity with `:key` set to `"activity.user.changed_avatar"`, the gem will look for a partial in `app/views/public_activity/user/_changed_avatar.(erb|haml|slim|something_else)`.
85
+
86
+ *Hint*: the `"activity."` prefix in `:key` is completely optional and kept for backwards compatibility, you can skip it in new projects.
87
+
88
+ If a view file does not exist, then p_a falls back to the old behaviour and tries to translate the activity `:key` using `I18n#translate` method (see the section below).
89
+
90
+ ### i18n
91
+
92
+ Translations are used by the `#text` method, to which you can pass additional options in form of a hash. `#render` method uses translations when view templates have not been provided.
93
+
94
+ Translations should be put in your locale `.yml` files. To render pure strings from I18n Example structure:
69
95
 
70
96
  ```yaml
71
97
  activity:
@@ -74,16 +100,37 @@ activity:
74
100
  update: 'Someone has edited the article'
75
101
  destroy: 'Some user removed an article!'
76
102
  ```
77
- Place this in a file and reference it in a Rails initializer.
78
103
 
79
- ```ruby
80
- PublicActivity::Activity.template = YAML.load_file("#{Rails.root}/config/pba.yml")
81
- ```
104
+ This structure is valid for activities with keys `"activity.article.create"` or `"article.create"`. As mentioned before, `"activity."` part of the key is optional.
105
+
106
+ ## Upgrading
107
+
108
+ There are a couple of major differences between 0.3 and 0.4 version. To upgrade, follow these steps:
109
+
110
+ 1. Add `include PublicActivity::Model` above `tracked` method call in your tracked models, like this:
111
+
112
+ ```ruby
113
+ class Article < ActiveRecord::Base
114
+ include PublicActivity::Model
115
+ tracked
116
+ end
117
+ ```
118
+
119
+ 2. public_activity's config YAML file is no longer used (by default in `config/pba.yml`). Move your YAML contents to your `config/locales/*.yml` files.
120
+
121
+ <br/>**IMPORTANT**: Locales are no longer rendered with ERB, this has been removed in favor of real view partials like in actual Rails apps.
122
+ Read [Activity views](#activity-views) section above to learn how to use those templates.<br/>
123
+
124
+ 3. Generate and run migration which adds new column to `activities` table:
125
+
126
+ ```bash
127
+ rails g public_activity:migration_upgrade
128
+ rake db:migrate
129
+ ```
82
130
 
83
- This is only a basic example, refer to documentation for more options and customization!
84
131
  ## Documentation
85
132
 
86
- You can find documentation [here](http://rubydoc.info/gems/public_activity/)
133
+ For more customization go [here](http://rubydoc.info/gems/public_activity/index)
87
134
 
88
135
  ## License
89
- Copyright (c) 2012 Piotrek Okoński, released under the MIT license
136
+ Copyright (c) 2012 Piotrek Okoński, released under the MIT license
data/Rakefile CHANGED
@@ -2,15 +2,17 @@ require "bundler/gem_tasks"
2
2
  require 'rake'
3
3
  require 'yard'
4
4
  require 'yard/rake/yardoc_task'
5
- require 'rspec/core/rake_task'
5
+ require 'rake/testtask'
6
6
 
7
- task :default => :spec
8
-
9
- RSpec::Core::RakeTask.new(:spec) do |t|
10
- t.pattern = "./spec/*_spec.rb"
11
- end
7
+ task :default => :test
12
8
 
13
9
  desc 'Generate documentation for the public_activity plugin.'
14
10
  YARD::Rake::YardocTask.new do |doc|
15
11
  doc.files = ['lib/**/*.rb']
16
12
  end
13
+
14
+ Rake::TestTask.new do |t|
15
+ t.libs << "test"
16
+ t.test_files = FileList['test/test*.rb']
17
+ end
18
+
@@ -0,0 +1,17 @@
1
+ require 'generators/public_activity'
2
+ require 'rails/generators/active_record'
3
+
4
+ module PublicActivity
5
+ module Generators
6
+ # Activity generator that creates activity model file from template
7
+ class ActivityGenerator < ActiveRecord::Generators::Base
8
+ extend Base
9
+
10
+ argument :name, :type => :string, :default => 'activity'
11
+ # Create model in project's folder
12
+ def generate_files
13
+ copy_file 'activity.rb', "app/models/#{name}.rb"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ # Activity model for customisation & custom methods
2
+ class Activity < PublicActivity::Activity
3
+ end
@@ -7,6 +7,7 @@ class CreateActivities < ActiveRecord::Migration
7
7
  t.belongs_to :owner, :polymorphic => true
8
8
  t.string :key
9
9
  t.text :parameters
10
+ t.belongs_to :recipient, :polymorphic => true
10
11
 
11
12
  t.timestamps
12
13
  end
@@ -0,0 +1,17 @@
1
+ require 'generators/public_activity'
2
+ require 'rails/generators/active_record'
3
+
4
+ module PublicActivity
5
+ module Generators
6
+ # Migration generator that creates migration file from template
7
+ class MigrationUpgradeGenerator < ActiveRecord::Generators::Base
8
+ extend Base
9
+
10
+ argument :name, :type => :string, :default => 'upgrade_activities'
11
+ # Create migration in project's folder
12
+ def generate_files
13
+ migration_template 'upgrade.rb', "db/migrate/#{name}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # Migration responsible for creating a table with activities
2
+ class UpgradeActivities < ActiveRecord::Migration
3
+ # Create table
4
+ def self.change
5
+ change_table :activities do |t|
6
+ t.belongs_to :recipient, :polymorphic => true
7
+ end
8
+ end
9
+ end
@@ -2,25 +2,35 @@ module PublicActivity
2
2
  # Module extending classes that serve as owners
3
3
  module Activist
4
4
  extend ActiveSupport::Concern
5
+
6
+ # Association of activities as their owner.
7
+ # @!method activities
8
+ # @return [Array<Activity>] Activities which self is the owner of.
9
+
10
+ # Association of activities as their recipient.
11
+ # @!method private_activities
12
+ # @return [Array<Activity>] Activities which self is the recipient of.
13
+
5
14
  # Module extending classes that serve as owners
6
15
  module ClassMethods
7
16
  # Adds has_many :activities association to model
8
17
  # so you can list activities performed by the owner.
9
18
  # It is completely optional, but simplifies your work.
10
- #
19
+ #
11
20
  # == Usage:
12
21
  # In model:
13
22
  #
14
23
  # class User < ActiveRecord::Base
15
24
  # activist
16
- # end
25
+ # end
17
26
  #
18
27
  # In controller:
19
28
  # User.first.activities
20
29
  #
21
30
  def activist
22
31
  has_many :activities, :class_name => "PublicActivity::Activity", :as => :owner
23
- end
32
+ has_many :private_activities, :class_name => "PublicActivity::Activity", :as => :recipient
33
+ end
24
34
  end
25
35
  end
26
36
  end
@@ -1,19 +1,20 @@
1
- require 'active_record'
2
-
3
1
  module PublicActivity
4
- # The ActiveRecord model containing
2
+ # The ActiveRecord model containing
5
3
  # details about recorded activity.
6
4
  class Activity < ActiveRecord::Base
7
5
  # Define polymorphic association to the parent
8
6
  belongs_to :trackable, :polymorphic => true
9
7
  # Define ownership to a resource responsible for this activity
10
8
  belongs_to :owner, :polymorphic => true
9
+ # Define ownership to a resource targeted by this activity
10
+ belongs_to :recipient, :polymorphic => true
11
11
  # Serialize parameters Hash
12
12
  serialize :parameters, Hash
13
-
13
+
14
14
  class_attribute :template
15
15
 
16
- attr_accessible :key, :owner, :parameters
16
+ # should recipient and owner be accessible?
17
+ attr_accessible :key, :owner, :parameters, :recipient
17
18
  # Virtual attribute returning text description of the activity
18
19
  # using basic ERB templating
19
20
  #
@@ -22,11 +23,11 @@ module PublicActivity
22
23
  # Let's say you want to show article's title inside Activity message.
23
24
  #
24
25
  # #config/pba.yml
25
- # activity:
26
- # article:
27
- # create: "New <%= trackable.name %> article has been created"
28
- # update: 'Someone modified the article'
29
- # destroy: 'Someone deleted the article!'
26
+ # activity:
27
+ # article:
28
+ # create: "New <%= trackable.name %> article has been created"
29
+ # update: 'Someone modified the article'
30
+ # destroy: 'Someone deleted the article!'
30
31
  #
31
32
  # And in controller:
32
33
  #
@@ -39,30 +40,91 @@ module PublicActivity
39
40
  #
40
41
  # Now when you list articles, you should see:
41
42
  # @article.activities.last.text #=> "Someone has created an article 'Rails 3.0.5 released!'"
43
+ # @see #render Advanced rendering
42
44
  def text(params = {})
45
+ # TODO: some helper for key transformation for two supported formats
46
+ k = key.split('.')
47
+ k.unshift('activity') if k.first != 'activity'
48
+ k = k.join('.')
49
+
50
+ I18n.t(k, parameters.merge(params) || {})
51
+ end
52
+
53
+ # Renders activity from views.
54
+ #
55
+ # @param [ActionView::Base] context
56
+ # @return [nil] nil
57
+ #
58
+ # Renders activity to the given ActionView context with included
59
+ # AV::Helpers::RenderingHelper (most commonly just ActionView::Base)
60
+ #
61
+ # The *preferred* *way* of rendering activities is
62
+ # to provide a template specifying how the rendering should be happening.
63
+ # However, one may choose using _I18n_ based approach when developing
64
+ # an application that supports plenty of languages.
65
+ #
66
+ # If partial view exists that matches the *key* attribute
67
+ # renders that partial with local variables set to contain both
68
+ # Activity and activity_parameters (hash with indifferent access)
69
+ #
70
+ # Otherwise, it outputs the I18n translation to the context
71
+ # @example Render a list of all activities from a view (erb)
72
+ # <ul>
73
+ # <% for activity in PublicActivity::Activity.all %>
74
+ # <li><%= render_activity(activity) %></li>
75
+ # <% end %>
76
+ # </ul>
77
+ #
78
+ # = Creating a template
79
+ # To use templates for formatting how the activity should render,
80
+ # create a template based on activity key, for example:
81
+ #
82
+ # Given a key _activity.article.create_, create directory tree
83
+ # _app/views/public_activity/article/_ and create the _create_ partial there
84
+ #
85
+ # Note that if a key consists of more than three parts splitted by commas, your
86
+ # directory structure will have to be deeper, for example:
87
+ # activity.article.comments.destroy => /app/views/public_activity/articles/comments/_destroy.html.erb
88
+ #
89
+ # == Variables in templates
90
+ # From within a template there are two variables at your disposal:
91
+ # * activity (aliased as *a* for a shortcut)
92
+ # * params (aliased as *p*) [converted into a {HashWithIndifferentAccess}]
93
+ #
94
+ # @example Template for key: _activity.article.create_ (erb)
95
+ # <p>
96
+ # Article <strong><%= p[:name] %></strong>
97
+ # was written by <em><%= p["author"] %></em>
98
+ # <%= distance_of_time_in_words_to_now(a.created_at) %>
99
+ # </p>
100
+ def render(context, params = {})
43
101
  begin
44
- erb_template = resolveTemplate(key)
45
- if erb_template
46
- parameters.merge! params
47
- renderer = ERB.new(erb_template)
48
- renderer.result(binding)
49
- else
50
- "Template not defined"
51
- end
52
- rescue
53
- "Template not defined"
102
+ params_indifferent = self.parameters.with_indifferent_access
103
+ params_indifferent.merge!(params)
104
+ controller = PublicActivity.get_controller
105
+ context.render :partial => self.template_path(self.key),
106
+ :layout => params_indifferent.delete(:layout),
107
+ :locals =>
108
+ {:a => self, :activity => self,
109
+ :controller => controller,
110
+ :current_user => controller.respond_to?(:current_user) ?
111
+ controller.current_user : nil ,
112
+ :p => params_indifferent, :params => params_indifferent}
113
+ rescue ActionView::MissingTemplate
114
+ context.render :text => self.text(params)
54
115
  end
55
116
  end
56
-
57
- private
58
- def resolveTemplate(key)
59
- res = nil
60
- if self.template
61
- key.split(".").each do |k|
62
- res = (res ? res[k] : self.template[k])
63
- end
64
- end
65
- res
117
+
118
+ protected
119
+ # Builds the path to template based on activity key
120
+ # TODO: verify that attribute `key` is splitted by commas
121
+ # and that the word before first comma is equal to
122
+ # "activity"
123
+ def template_path(key)
124
+ path = key.split(".")
125
+ path.delete_at(0) if path[0] == "activity"
126
+ path.unshift "public_activity"
127
+ path.join("/")
66
128
  end
67
- end
129
+ end
68
130
  end
@@ -1,56 +1,143 @@
1
1
  module PublicActivity
2
+ # Happens when creating custom activities without either action or a key.
3
+ class NoKeyProvided < Exception; end
4
+
5
+ # Used to smartly transform value from metadata to data.
6
+ # Accepts Symbols, which it will send against context.
7
+ # Accepts Procs, which it will execute with controller and context.
8
+ # @since 0.4.0
9
+ def self.resolve_value(context, thing)
10
+ case thing
11
+ when Symbol
12
+ context.__send__(thing)
13
+ when Proc
14
+ thing.call(PublicActivity.get_controller, context)
15
+ else
16
+ thing
17
+ end
18
+ end
19
+
2
20
  # Common methods shared across the gem.
3
21
  module Common
4
22
  extend ActiveSupport::Concern
5
- # Directly creates activity record in the database, based on supplied arguments.
6
- # Only first argument - key - is required.
23
+ # Directly creates activity record in the database, based on supplied options.
7
24
  #
8
- # == Usage:
25
+ # It's meant for creating custom activities while *preserving* *all*
26
+ # *configuration* defined before. If you fire up the simplest of options:
9
27
  #
10
- # current_user.create_activity("activity.user.avatar_changed") if @user.avatar_file_name_changed?
28
+ # current_user.create_activity(:avatar_changed)
11
29
  #
12
- # == Parameters:
13
- # [key]
14
- # Custom key that will be used as a i18n translation key - *required*
15
- # [owner]
16
- # Polymorphic relation specifying the owner of this activity (for example, a User who performed this task) - *optional*
17
- # [params]
18
- # Hash with parameters passed directly into i18n.translate method - *optional*
30
+ # It will still gather data from any procs or symbols you passed as params
31
+ # to {Tracked::ClassMethods#tracked}. It will ask the hooks you defined
32
+ # whether to really save this activity.
19
33
  #
20
- def create_activity(key, owner = nil, params = {})
21
-
22
- if owner.nil? && ((defined? User) != nil) && User.respond_to?(:current_user)
23
- owner = User.current_user
24
- end
34
+ # But you can also overwrite instance and global settings with your options:
35
+ #
36
+ # @article.activity :owner => proc {|controller| controller.current_user }
37
+ # @article.create_activity(:commented_on, :owner => @user)
38
+ #
39
+ # And it's smart! It won't execute your proc, since you've chosen to
40
+ # overwrite instance parameter _:owner_ with @user.
41
+ #
42
+ # [:key]
43
+ # The key will be generated from either:
44
+ # * the first parameter you pass that is not a hash (*action*)
45
+ # * the _:action_ option in the options hash (*action*)
46
+ # * the _:key_ option in the options hash (it has to be a full key,
47
+ # including model name)
48
+ # When you pass an *action* (first two options above), they will be
49
+ # added to parameterized model name:
50
+ #
51
+ # Given Article model and instance: @article,
52
+ #
53
+ # @article.create_activity :commented_on
54
+ # @article.activities.last.key # => "article.commented_on"
55
+ #
56
+ # For other parameters, see {Tracked#activity}, and "Instance options"
57
+ # accessors at {Tracked}, information on hooks is available at
58
+ # {Tracked::ClassMethods#tracked}.
59
+ # @see #prepare_settings
60
+ # @return [Model, nil] If created successfully, new activity
61
+ # @since 0.4.0
62
+ # @api public
63
+ # @overload create_activity(action, options = {})
64
+ # @param [Symbol,String] action Name of the action
65
+ # @param [Hash] options Options with quality higher than instance options
66
+ # set in {Tracked#activity}
67
+ # @option options [Activist] :owner Owner
68
+ # @option options [Activist] :recipient Recipient
69
+ # @option options [Hash] :params Parameters, see
70
+ # {PublicActivity.resolve_value}
71
+ # @overload create_activity(options = {})
72
+ # @param [Hash] options Options with quality higher than instance options
73
+ # set in {Tracked#activity}
74
+ # @option options [Symbol,String] :action Name of the action
75
+ # @option options [String] :key Full key
76
+ # @option options [Activist] :owner Owner
77
+ # @option options [Activist] :recipient Recipient
78
+ # @option options [Hash] :params Parameters, see
79
+ # {PublicActivity.resolve_value}
80
+ def create_activity(*args)
81
+ options = prepare_settings(*args)
25
82
 
26
- activity = self.activities.create(:key => key, :owner => owner, :parameters => params)
27
- if !Pusher.app_id.nil? && !Pusher.key.nil? && !Pusher.secret.nil?
28
- Pusher['activity-channel'].trigger('activity-create', {:key => key, :owner => owner, :parameters => params, :text => activity.text, :object => self})
83
+ if call_hook_safe(options[:key].split('.').last)
84
+ self.activities.create(
85
+ :key => options[:key],
86
+ :owner => options[:owner],
87
+ :recipient => options[:recipient],
88
+ :parameters => options[:params]
89
+ )
29
90
  end
30
91
  end
31
92
 
32
- private
33
- # Prepares settings used during creation of Activity record.
34
- # params passed directly to tracked model have priority over
35
- # settings specified in tracked() method
36
- def prepare_settings
37
- # user responsible for the activity
38
- if self.activity_owner
39
- owner = self.activity_owner
40
- else
41
- owner = self.class.activity_owner_global
42
- end
43
-
44
- case owner
45
- when Symbol
46
- owner = self.__send__(owner)
47
- when Proc
48
- owner = owner.call(self)
49
- end
50
- #customizable parameters
51
- parameters = self.class.activity_params_global
52
- parameters.merge! self.activity_params if self.activity_params
53
- return {:key => self.activity_key,:owner => owner, :parameters => parameters}
93
+ # Prepares settings used during creation of Activity record.
94
+ # params passed directly to tracked model have priority over
95
+ # settings specified in tracked() method
96
+ #
97
+ # @see #create_activity
98
+ # @return [Hash] Settings with preserved options that were passed
99
+ # @api private
100
+ # @overload prepare_settings(action, options = {})
101
+ # @see #create_activity
102
+ # @overload prepare_settings(options = {})
103
+ # @see #create_activity
104
+ def prepare_settings(*args)
105
+ # key
106
+ options = args.extract_options!
107
+ action = (args.first || options[:action]).try(:to_s)
108
+ if action.nil? and !options.has_key?(:key)
109
+ raise NoKeyProvided, "No key provided for #{self.class.name}"
54
110
  end
111
+ key = (options[:key] ||
112
+ self.activity_key ||
113
+ (self.class.name.parameterize('_') + "." + action.to_s)).to_s
114
+
115
+ # user responsible for the activity
116
+ owner = PublicActivity.resolve_value(self,
117
+ options[:owner] ||
118
+ self.activity_owner ||
119
+ self.class.activity_owner_global
120
+ )
121
+
122
+ # recipient of the activity
123
+ recipient = PublicActivity.resolve_value(self,
124
+ options[:recipient] ||
125
+ self.activity_recipient ||
126
+ self.class.activity_recipient_global
127
+ )
128
+
129
+ #customizable parameters
130
+ params = options[:params] || {}
131
+ params.merge!(self.class.activity_params_global)
132
+ params.merge!(self.activity_params) if self.activity_params
133
+ params.each { |k, v| params[k] = PublicActivity.resolve_value(self, v) }
134
+
135
+ {
136
+ :key => key,
137
+ :owner => owner,
138
+ :recipient => recipient,
139
+ :params => params
140
+ }
141
+ end
55
142
  end
56
143
  end
@@ -5,12 +5,11 @@ module PublicActivity
5
5
 
6
6
  included do
7
7
  after_create :activity_on_create
8
- end
8
+ end
9
9
  private
10
10
  # Creates activity upon creation of the tracked model
11
11
  def activity_on_create
12
- settings = prepare_settings
13
- create_activity(settings[:key] || "activity."+self.class.name.parameterize('_')+".create", settings[:owner], settings[:parameters])
12
+ create_activity(:create)
14
13
  end
15
14
  end
16
- end
15
+ end