opensoul.org

acts_as_audited

NOTE: This article is out of date. Visit the project on Github or the mailing list for up-to-date information.

acts_as_audited is an Active Record plugin that logs all modifications to your models in an audits table. It uses a polymorphic association to store an audit record for any of the model objects that you wish to have audited. The audit log stores the model that the change was on, the “action” (create, update, destroy), a serialzied hash of the changes, and optionally the user that performed the action.

Auditing in Rails

If you’re using acts_as_audited within Rails, you can simply declare which models should be audited. acts_as_audited can also automatically record the user that made the change if your controller has a current_user method.

class ApplicationController < ActionController::Base
  audit User, List, Item
protected
  def current_user
    @user ||= User.find(session[:user])
  end
end

Caveats

Auditing with user support depends on Rails’ caching mechanisms, therefore auditing isn’t enabled during development mode. To test that auditing is working, start up your app in production mode, or change the following options in config/environments/development.rb:

config.cache_classes = true
config.action_controller.perform_caching = true


This has been fixed.

Customizing

To get auditing outside of Rails, or to customize which fields are audited within Rails, you can explicitly declare acts_as_audited on your models. The :except option allows you to specify one or more attributes that you don’t want to be saved in the audit log.

class User < ActiveRecord::Base
  acts_as_audited :except => [:password, :credit_card_number]
end

Installation

You can grab the plugin by running:

script/plugin install git://github.com/collectiveidea/acts_as_audited.git

Run the migration generator and migrate to add the audits table.

script/generate audited_migration add_audits_table
rake db:migrate

Upgrading

Those upgrading from version 0.2 need to add 2 fields the audits table:

add_column :audits, :user_type, :string
add_column :audits, :username, :string

acts_as_audited, plugin, popular, rails, and ruby July 21, 2006

165 Comments

  1. Navjeet Navjeet July 21, 2006

    In the audit table, what is the significance of auditable_id and auditable type? In example above does auditable_type User reflect the model being audited?

  2. Brandon Brandon July 21, 2006

    Yeah, sorry, I should have explained that.

    The plugin adds a polymorphic join from the audited models to the Audit model, so you can retrieve all the audits for a model by calling:

      User.find(:first).audits
    

    If you have an instance of Audit, you can also call audit.auditable to get the model that the audit record is for.

  3. bryanl bryanl July 21, 2006

    So, can we version and audit a model?

  4. Brandon Brandon July 21, 2006

    Well, there shouldn’t be anything that stops you from using the acts_as_versioned in combination with acts_as_audited.

    But on that note, I’m toying with the idea of building in the ability to revert individual fields using the audit record. I’d love to hear poeple’s thoughts on that.

  5. Matt Morton Matt Morton July 26, 2006

    Wow, way cool plugin. Somehow Rails just keeps drawing me in. :)

  6. Eric Anderson Eric Anderson August 1, 2006

    The plugin looks good but I am trying to understand why I would use this instead of the “acts_as_versioned” plugin? It seems that the “acts_as_versioned” plugin can provide the same information but in a more usuable form. With the acts_as_versioned plugin I can instantionate the object at the time it was versioned.

    The only big advantages I see for this plugin over acts_as_versioned are:

    • It should use less space since it is only recording what changed and not the entire record.
    • Since the audit trail is stored in one table you could easily get a list of changes across all models in one query. With the acts_as_versioned plugin it seems that it would be more difficult to get all the changes made by user X in the last 5 days.

    This comment is not meant to critisize. I am just trying to understand the proper time to use this and the proper time to use acts_as_versioned.

  7. Brandon Brandon August 1, 2006

    Eric,

    Thanks for your feedback. I think you’re exactly right. I wrote acts_as_audited for a specific purpose: an audit trail. I want to be able to answer questions like, “show me all of the changes made by Sally”, or “show me all of the changes for July 31”. I could have done this all with acts_as_versioned, but not as easily, and I didn’t want to double the number of tables in my database.

    Now, I have been thinking about adding versioning to acts_as_audited (but not for the project I working on now). It would basically be a polymorphic version of acts_as_versioned. We’ll see, versioning isn’t something that I have a need for right now.

    I’m open to any suggestions you may have.

  8. Kevin Marsh Kevin Marsh August 4, 2006

    Wouldn’t you know it… I just implemented something like this using callbacks. Wrangling with Observer proved to be too much of a hassle for the time being but this is much cleaner!

  9. Michael Schuerig Michael Schuerig August 11, 2006

    IMHO, you should use the serialization feature of ActiveRecord::Base. It as easy as

    class Audit

  10. Michael Schuerig Michael Schuerig August 11, 2006

    Sigh, your blog can’t handle the less-than sign.

    class Audit; serialize :changes; end

  11. Brandon Brandon August 12, 2006

    Michael,

    Thanks for the suggestion. I had thought about doing that and for some talked myself out of it (don’t remember why). I will probably switch to that.

  12. Michael Schuerig Michael Schuerig August 13, 2006

    Here’s another change, I hope you can decipher it after the blog has mangled the formatting. This version of write_attribute ensures that the comparison of attributes is done with old and new values properly typecast. Also, it writes the new value every time it is called, not just the first time.

    def write_attribute(attr_name, attr_value)
    attr_name = attr_name.to_s
    if audited_attributes.include?(attr_name)
    @changed_attributes ||= {}
    if old_entry = @changed_attributes[attr_name]
    old_value = old_entry.first
    else
    old_value = self[attr_name]
    end
    super(attr_name, attr_value)
    new_value = self[attr_name]
    if new_value != old_value
    @changed_attributes[attr_name] = [old_value, new_value]
    end
    else
    super(attr_name, attr_value)
    end
    end

  13. Brandon Brandon August 14, 2006

    Michael,

    Thanks! I’ve committed that along with serializing the changes.

  14. Michael Schuerig Michael Schuerig August 15, 2006

    One more thing… I think

    has_many :audits, :as => :auditable

    should not nullify the referring foreign keys on destruction of the audited object. The auditable_id doesn’t serve any purpose in the DB after the object is destroyed, but it is the only thing that ties together the events that happened to an object during its lifetime — even after it is gone.

  15. Brandon Brandon August 15, 2006

    Yeah, you’re right. It’s committed. Thanks!

  16. Aníbal Rojas Aníbal Rojas August 21, 2006

    Thanks a lot for such great plugin, and I must agree wth you that sometimes there is no need for versions, but for a simple audit trail.

    Off Topic: This is just a quick note to invite you to register at RubyCorner.com, a meeting place for people interested in the Ruby Programming Language or any of the related technologies.

  17. Dewet Dewet August 28, 2006

    Great plugin; ever thought of hooking it into the login_engine?

  18. namxam namxam August 29, 2006

    I am not 100% sure about this one, but isn’t it a bad idea to access the user id by calling User.current. I thought models shouldn’t have access to such data. Or at least I always put such a call in the application controller / helper.

  19. Brandon Brandon August 29, 2006

    Dewet,

    No, I haven’t really used engines much. I tried using login_engine and found that it was going to take more work to get it working how I wanted than to just use one of the generator plugins.

    namxam,

    You’re right, it is poor design. And it would be even poorer if Rails ran in a threaded environment. Ideally there should be some type of security system injected between the controller and the model that would audit what users did. Unfortunately that would be a lot more complicated than this simple plugin. Putting a class method on User that keeps track of the current user is the cleanest solution I can think of. I’m interested if you have any ideas.

  20. GregH GregH August 30, 2006

    Hi,

    Does the serialization approach introduce a possible issue for existing data if Ruby itself is upgraded? (I come from java where one has to be quite careful here)

    Tks
    Greg

  21. GregH GregH August 30, 2006

    PS Does “auditable_id” provide a unique identify for all data rows that changed for a particular user HTTP request into a controller does it? (i.e. if one action, e.g. user commits a multi-page form, the same auditable_id is used for all the database changes?).

    If this is the case could potentially it be a good idea to have an auditable_id type table which has a controller focused summary of the event (from the user perspective). If the user was then going to review audit they could see the overall summary of actions they have performed, and then click on one to then bring up the detailed data changes associated with this event? Comments?

  22. Brandon Brandon August 31, 2006

    GregH,

    No, serialization is not an issue for different versions of ruby. The serialized verson is actually just a YAML dump of the attributes.

    auditable_id is the primary key of the originial record, auditable_type is the model of that record. acts_as_audited doesn’t actually know anything about the HTTP reqeust or controller. It works the same way inside of an HTTP request as it does from the command line.

    What I’ve done on the frontend is use naming conventions to link to the original record. If my model name is “User”, then I assume the controller name is “users”. So, if I have an audit record with auditable_id => 10 and auditable_type => User, then I create a link by doing:

    &amp;lt;% link_to 'record', :controller =&gt; audit.autidable_type.downcase.pluralize, :action =&gt; 'show', :id =&gt; audit.auditable_id %&amp;gt;
    

    Which creates a link to “/users/show/10”.

  23. GregH GregH August 31, 2006

    Brandon – understood. Sounds good.

    I was actually thinking of a slightly different user case however. The concept I have is that there is a (a) user interaction audit/event type log and (b) the actual database data change audit trail [i.e. acts_as_audited].

    For (a) the concept would be an audit entry (one record) for each user action carried out. This could often be a simple action that changes one data in one table, but at times could be more complex and make changes to numerous tables (e.g. 5/4/06 7.23am, GregH, Submitted request for purchase all cart items). This could be just one table that contained this.

    What would then be cool is to link this user level event audit to the underlying database tables/rows which were changed (i.e. the acts_as_audited table rows). So this might involve acts_as_audited code picking up a user action audit row ID.

    What do you think? Is there a better way to do this? Do you think acts_as_audited could be easily modified to do what I was suggesting?

    Cheers

  24. Greg Hauptmann Greg Hauptmann September 5, 2006

    PSS. Can anyone help? Still can’t work out how to get the userid column to log.

    I use ActiveRBAC for user authentication (just for background) and have acts_as_audited working for everything but for logging the userid. I’m not exactly sure how to setup the required class/objects with the appropriate method for acts_as_audited that it needs to get the username. Can anyone help out with:

    a) how to setup the appropriate class
    b) probably more to the point, how to make sure it’s in the required context for acts_as_audited to get (i.e. I guess it needs to be visible from the .rb even though it would no doubt get created in the controller which has access to the session no?

    For background, with ActiveRBAC I can issue the following to get the userid “current_user.login” which is based on use of an ActiveRBAC helper (I think helpers are available in views). Extract from the rbac_helper.rb:
    =====
    def current_user
    return @active_rbac_user unless @active_rbac_user.nil?

    @active_rbac_user =
    if session[:rbac_user_id].nil? then
    ::AnonymousUser.instance
    else
    ::User.find(session[:rbac_user_id])
    end
    return @active_rbac_user
    end

    =


    Tks in advance

  25. Brian Hogan Brian Hogan September 5, 2006

    @Brandon:

    I think this is awesome. However, there’s one thing I don’t like and that’s the use of cattr_accessor for the user id.

    I have a plugin that stores the user id on the table in the created_by field. It was based on a similar plugin which uses the same method as you. My approach was to overload the save and update_attributes methods of ActiveRecord to take an optional parameter.. the user id.

    If you’re interested in refactoring your plugin to do something similar, hit me up at my email and we could discuss some more. I want to use your plugin and may modify it myself but I wanted to talk to you first.

    I love the plugin… great job!!!!

  26. Brandon Brandon September 5, 2006

    Greg,

    I don’t use ActiveRBAC, but what I did with acts_as_authenticated is replace the use of an instance variable with User.current_user. So in your code, replace all instances of @active_rbac_user with User.curent_user.

  27. Brandon Brandon September 5, 2006

    Brian,

    I agree, I don’t like it either. However, it is the most unobtrusive way I can think of. I want to stay way from modifying the API so that it can be added and removed from apps without breaking or having to change all your code. With the current implementation, you only have to change a few lines in your login code.

    What would be ideal is if Rails’ around filter didn’t force you to have separate before_filter and after_filter methods so you could just use a block for auditing. Something like:

    Audit.as_user(current_user) do
      // continue processing filter chain &amp; actions
    end
    

    That being said, I am interested in seeing your implementation. Feel free to email me a patch.

  28. Brian Hogan Brian Hogan September 5, 2006

    The way I do it is by allowing the save method to take an optional parameter. This way nothing breaks. If the developer doesn’t pass the id through the save or update_attributes, then the record does not get stamped. I’ll send you a link to my code (it’s tiny) and you can see if it would work for you.

  29. Greg Hauptmann Greg Hauptmann September 5, 2006

    Brandon – do you mind if I could ask for a quick explanation of how the userid passing and contexts work here. I’m just a little confused (still new to Ruby). For example:

    • in your controller set User.curent_user to @active_rbac_user (i.e the userid). So is this mean I’m effectively creating a class User with an attribute “current_user” on the fly?
    • In the Model class one does “acts_as_audited :user_class_name => ‘User’, :user_method => ‘current’”, and cattr_accessor :current_user
      - can the model context “see” the User object created in the controller? How does this work?
      - how does the “cattr_accessor” help here?

    Thats the main thing for me, just trying to understand how the userid is passed through. I also have several other questions if you’ve got time, posted at: http://www.ruby-forum.com/topic/79999#new

    Thanks again

  30. […] Thanks to Michael Schuerig for pointing out that malicious users could unassociate your audit records due to the use of has_many in acts_as_audited. has_many :audits creates an attribute accessor called audit_ids on the model objects that you declare acts_as_audited, which could allow users to pass an array of ids that would overwrite the actual audit records. […]

  31. Greg Hauptmann Greg Hauptmann October 10, 2006

    Hi,

    Does anyone have the code to read in the changes (stored in yaml) and display them in a view they could post? For a given record in the audits table for example, and the yaml that is stored in the changes column. I have read in the yaml from the changes column for a given audit table entry, but just now wondering how to consume this and display it (my first time with YAML)

    Thanks
    Greg

  32. Brandon Brandon October 10, 2006

    Greg,

    ActiveRecord handles that for you, so you should just be able to treat the changes as a hash.

    @user.autits.first.changes[:username]
    
  33. Tim Tim October 12, 2006

    Hello

    This is a fantastic plugin! Previously I was using my own solution to create an audit trail, but that involved adding code into every update method – messy and certainly not DRY. This acts_as_audited is really neat.

    There’s only one downside compared with the manual approach I used to use – I need to record the reason /why/ a change was made. Is there any way the plugin could be modified so that it could take an optional parameter and record a reason for the change? I think this would be very useful for most people who need to keep an aufit trail.

    Many thanks for a brilliant plugin.

    Tim

  34. NeilS NeilS October 20, 2006

    Hi.

    This plugin is great; exactly what I wanted – although it took me quite a while to get the user_id correctly logging my acts_as_authenticated user; and in a horribly hacky way. Is there a recommended technique to achieve this?

    On a second note, I have two classes of people updating my records; Administrators update records at the back end, and Clients can update their own records at the front end.

    At the moment, my audit table contains my user_id, but I don’t know if that refers to an Administrator or a Client. Is there a way I can record which model that user_id refers to? (Or can this be a feature request if there’s no way to do it! :-)

    Thanks for this great plugin – and any advice will be warmly received.
    NeilS.

  35. Brandon Brandon October 20, 2006

    NeilS,

    The user_id is a big hack that I’m not very happy with. The way I suggest to do it above doesn’t actually work, it causes concurrency issues. Someone actually suggested overwriting the ActiveRecord save method to accept the user as an argument. I’m hesitant to do that because I don’t want to change the API, but that may be the best solution.

    As to your second question, yes, I think you could use a polymorphic association between the Audit model and your Administrator and Client models. I’ll look into it.

    Thanks,
    Brandon

  36. Chaz Chaz November 7, 2006

    Have you considered using Sweepers to figure out the current user? I stole the idea from the Rails recepies book to add auditing to one of my projects, and it’s worked well thus far.

  37. vasudeva vasudeva November 14, 2006

    Any thought on how this plugin could use Apache’s REMOTE_USER variable to integrate with users that have authenticated against LDAP but have no associated model/table?

  38. Brandon Brandon November 14, 2006

    Chaz: no, I hadn’t, but that’s a great idea! Thanks for pointing that out. I’ll try to incorporate that in the next couple weeks.

    vasudeva: at the moment, there isn’t really a way to do that. But I’m going to be working on some changes in the next couple weeks. I’ll take that into account.

  39. vasudeva vasudeva November 14, 2006

    Great. So far the plugin works beautifully otherwise; it’s exactly what I needed. Can’t show it to the boss until we can successfully track changes by user. I’ll probably be reloading this page twice daily to see if you find a way to work that in. ;)

  40. Brandon Brandon November 19, 2006

    vasudeva: I’ve made some updates to the plugin that will allow you to set the user in the audit record to a string in addition to an ActiveRecord model. Just add a method to your controller called current_user that returns the username. Let me know how it works out for you.

  41. Peer Allan Peer Allan November 29, 2006

    Hi Brandon, I saw you plugin and thought it would work perfectly for my needs. However I am having small problem when I try to run the migration “script/generate audited_model add_audits_table” I just get this error “Couldn’t find ‘audited_model’ generator” I assume I am doing something wrong, but I can’t figure out what it is?

  42. Brandon Brandon November 29, 2006

    Peer Allen:

    Sounds like it’s not picking up the generators in the plugins directory. What happens when you run script/generate without any arguments? Here’s what I see for installed generators:

    Installed Generators
      Plugins: audited_migration
      Builtin: controller, integration_test, mailer, migration, model, plugin, scaffold, session_migration, web_service
    
  43. Brandon Brandon November 29, 2006

    Peer Allen:

    Ah, I didn’t notice it when I first glanced at your comment, but it should be audited_migration, not audited_model.

  44. Peer Allan Peer Allan November 29, 2006

    Whoops, I guess I should get a little more sleep before attempting to tackle blatantly obvious tasks. Thanks Brandon.

  45. Craig White Craig White December 28, 2006

    There is something wrong and I can’t lay my finger on it. In a view that lists found entries from the audits table, these work…
    <%= audit.auditable_type >
    <
    = audit.username >
    <
    = audit.action >
    <
    for change in audit.changes ><= change >
    <
    end >
    <
    = audit.created_at >
    <
    = audit.auditable_id %>

    but no matter what, this will toss an syntax error…

    <%= (audit.auditable_type == ‘Placement’ ? (link_to ‘Show Placement’, { :controller => ‘placements’, :action => ‘show’, :id => audit.auditable_id } )) %>

    so I cannot make conditional links to the actual records which is something I would really like to do

    Craig

  46. Chris Chris January 5, 2007

    Hi,

    A newbie here.. I thought that this plugin is the best suited for my need. I am able to install it, but I cannot move on after executing

    ruby script/generate audited_migration add_audits_table

    I get some error. It says:

    script/../config/../vendor/rails/activerecord/lib/../../activesupport/lib/act
    ive_support/dependencies.rb:123:in `const_missing’: uninitialized constant ActionController (NameError) from script/../config/../vendor/plugins/acts_as_audited/init.rb:8:in
    `load_plugin’ from script/../config/../vendor/rails/railties/lib/initializer.rb:348
    :in `load_plugin’ from …

    Can you please help me? Many thanks!

  47. Brandon Brandon January 9, 2007

    Chris,

    Not sure what is causing that error. What version of Rails are you using? This plugin was developed using 1.1.x, but I’m using it in a 1.2 project now, so I know it works.

  48. Chris Chris January 19, 2007

    Thanks Brandon.

    I am now into 1.2.1. Tried it again, but i’m still getting the same error.

    What do you think could be wrong? Any insight on this?

    Many thanks!

  49. Camila Camila January 25, 2007

    I’m reading about the plugin and I knows is what I nees because I need to ansewer the same kind of questions than Brandon. The problem is that is my first time with ruby, and with plugin, and eventhough I understand english, I ``m not really sure how can i use this wonderful act_as_audited… I`m working on that. so if anybody has something that explains it in spanish, or step by step in english, I’ll be thankful, happy, and closer to get this think working.
    thanks!

  50. Camila Camila January 25, 2007

    Ok I finally got it. I didn`t know where to make the changes; now I understand that in every model you want to audit you have to put: act_as_audited
    Now here is my new question: I have a table “people” that is related wuith the table “area” through the table “peoplearea”, meaning that each person may have many areas. The “peoplearea” and the “people” models are being audited, and it works. The problem is that if I’m editing a person info, and I add or delete a new area, the “audits” table show this changes as destroying or creating the table “peoplearea” and I need to be saved as a change made over the person. Is this possible with this plugin?

  51. Brandon Brandon January 25, 2007

    Camilia:

    Nope. It doesn’t record changes to associations. That’s not a feature that I need, but patches are welcome.

  52. Chris Chris February 10, 2007

    I’ve finally got the plugin to work!!! It’s really great. It’s what I actually need.

    But, I need more help. Does the user object need to have exactly the same field names as the audits table (user_id, user_type, and username) for it to actually work? I tried to turn on caching for the dev environment, and to put the current_user method in the application controller, but it still doesn’t log anything under the 3 user columns.

    What must I do? Am I missing anything at all? Thanks!

  53. Brandon Brandon February 10, 2007

    Chris,

    Does the user object need to have exactly the same field names as the audits table (user_id, user_type, and username) for it to actually work?

    Nope.

    Did you declare the models to audit in the controller?

    class ApplicationController &lt; ActionController::Base
      audit User, List, Item
    end
    

    If you did, and it is auditing changes and not the user, then I would check to make sure that your current_user method on your controllers returns an ActiveRecord object or a string.

  54. Skiz Skiz February 14, 2007

    I’ve been trying to interface this with the existing acts_as_authenticated for current_user support, but I cannot for the life of me update the username or associated user. Someone above has had this previously but did not provide any information.

  55. Brandon Brandon February 14, 2007

    Skiz,

    I use it with acts_as_authenticated, it should “Just Work”™. Have you tried it in production mode? It wasn’t working for me in development the one time I tried (even with caching enabled), but I know it works in production.

  56. josh josh February 22, 2007

    First off, thanks Brandon for an outstanding plugin. I am curious though, if it is possible to return(/display) all audits in total and chronologically as opposed to on a per user basis? I am a bit new to ror in general but I was thinking maybe I could make an additional model that also refers to the audits table. Would that work? Poor form? Is there another way? Thanks for any insight.

  57. Brandon Brandon February 22, 2007

    josh,

    There already is a model for it:

    Audit.find(:all, :order =&gt; "created_at")
    
  58. Deepak Kumar Deepak Kumar March 13, 2007

    Thanks for a simple, to the point plugin, works exactly as expected. Saved a lot of time. Is it listed in Rails Wiki, I could not find it there, had to rely on Google. Anyway great work.

  59. Adam Adam March 18, 2007

    Thanks for the great plugin. I was wondering whether you could add a feature to selectively audit on action.

    acts_as_audited :on => [:update, :destroy]

    Its just that I dont usually audit the creation of a record, as this stands as the record itself until the first change which is audited.

  60. Brandon Brandon March 19, 2007

    Adam,

    That’s a great suggestion. I probably won’t have time to add features to this plugin for a month or so, but I’m open to taking patches.

  61. Erik Erik March 31, 2007

    I like this plugin, but I’ve run into a weird problem and I’m wondering if you have any advice on solving it.

    In my application I have an Address model, with a :coords attribute, implemented with GeoRuby’s Point class.

    I installed acts_as_audited and told it to audit Address. It works fine in production mode, and in development mode with caching enabled.

    However, when I run my unit tests, I get lots of errors about undefined methods on Point. If I take the audit statement out, the errors go away.

    Running a unit test in the debugger, I find that at the point when I try to call, say, Point.from_lon_lat (a class method), Point is a subclass of Object with no geometry-related methods, rather than the subclass of Geometry it should be.

    Obviously I’m not asking you to study up on GeoRuby or debug my problem for me, but I thought you might have some thoughts on why the presence of an audit statement somehow makes Point refer to a different class.

  62. Erik Erik March 31, 2007

    Well, that didn’t take so long. The answer is that referring to the classes in application.rb changed the order in which they were loaded, revealing a previously hidden bug in my code.

    (In case anyone’s curious: I had a local extension to the Point class. When my extension was loaded after GeoRuby, it altered GeoRuby’s Point. But when the extension was loaded first, or without GeoRuby, it created its own Point class. The solution was to require GeoRuby and explicitly identify the Point class to be extended.)

    Anyway, uh… yeah! Cool plugin! Sorry for the interruption! Carry on!

  63. Meng Kuan Meng Kuan April 5, 2007

    Brandon, thanks for the cool plugin! Just installed it and works like a charm.

    I am thinking of using the audits table as the source of input for a dashboard interface for my app. I am able to pull out several arrays of the relevant Audit records off the table and flatten them as one big array. E.g. latest list of messages, todo items, comments, etc. all in one array. However, before displaying them, Next I want to sort them according to created_at. I can update the audit.rb class directly and add the “def <=>(o)” method there but am wondering if there is a cleaner way of doing this?

  64. Brandon Brandon April 5, 2007

    Meng,

    audits = Audit.find(:all, :order =&gt; 'created_at')
    
    #or
    audits.sorty_by(&amp;:created_at)
    
  65. Nicholas Nicholas April 6, 2007

    Brandon, This seems to be a great plugin. I have been trying to get it to work, but rails 1.2 doesn’t seem to like it when you use your models in the initialization of the ApplicationController. Has anyone else had this issue?


    class ApplicationController < ActionController::Base



    1. Auditing – initalize autditing sweepers
      audit User, Account

    protected
    include AuthenticatedSystem


    end


    class Account < ActiveRecord::Base
    acts_as_audited
    end


    class User < ActiveRecord::Base
    acts_as_audited :except => [:password]
    end


    The error:


    Expected C:/…/app/models/account.rb to define Account
    C:/…/vendor/rails/activesupport/lib/active_support/dependencies.rb:
    249:in `load_missing_constant’
    C:/…/vendor/rails/activesupport/lib/active_support/dependencies.rb:
    452:in `const_missing’
    C:/…/vendor/rails/activesupport/lib/active_support/dependencies.rb:
    464:in `const_missing’
    C:/…/vendor/rails/activesupport/lib/active_support/dependencies.rb:
    470:in `send’
    C:/…/vendor/rails/activesupport/lib/active_support/dependencies.rb:
    470:in `const_missing’
    C:/…/app/controllers/application.rb:19
    c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_re
    quire’


    I am running rails 1.2.3. What I found weird is that it fails on the second model and not the first. If I comment out the Account model in the audit statement in Application Controller, it works. Any suggestions?


    - Nicholas

  66. Steve Steve April 12, 2007

    I cant even install this on Rails 1.2.3. The command line spits out the following errors…

    /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/depende
    ncies.rb:266:in `load_missing_constant': uninitialized constant CollectiveIdea::
    ActionController (NameError)
            from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_su
    pport/dependencies.rb:452:in `const_missing'
            from script/../config/../vendor/plugins/acts_as_audited/init.rb:8:in `lo
    ad_plugin'
            from /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/initializer.rb:40
    1:in `load_plugin'
            from /usr/local/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_su
    pport/core_ext/kernel/reporting.rb:11:in `silence_warnings'
            from /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/initializer.rb:40
    1:in `load_plugin'
            from /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/initializer.rb:18
    5:in `load_plugins'
            from /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/initializer.rb:18
    5:in `each'
            from /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/initializer.rb:18
    5:in `load_plugins'
             ... 6 levels...
            from /usr/local/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/commands/generate
    .rb:1
            from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in
    `gem_original_require'
            from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in
    `require'
            from script/generate:3
  67. Brandon Brandon April 12, 2007

    Steve,

    $ rails --version
    Rails 1.2.3
    $ rails test
    &lt;truncated&gt;
    $ cd test
    $ script/plugin install http://source.collectiveidea.com/public/rails/plugins/acts_as_audited
    + ./acts_as_audited/CHANGELOG
    + ./acts_as_audited/README
    + ./acts_as_audited/Rakefile
    + ./acts_as_audited/generators/audited_migration/USAGE
    + ./acts_as_audited/generators/audited_migration/audited_migration_generator.rb
    + ./acts_as_audited/generators/audited_migration/templates/migration.rb
    + ./acts_as_audited/init.rb
    + ./acts_as_audited/install.rb
    + ./acts_as_audited/lib/acts_as_audited.rb
    + ./acts_as_audited/lib/audit.rb
    + ./acts_as_audited/lib/audit_sweeper.rb
    + ./acts_as_audited/tasks/acts_as_audited_tasks.rake
    + ./acts_as_audited/test/acts_as_audited_test.rb
    + ./acts_as_audited/test/audit_test.rb
    + ./acts_as_audited/test/database.yml
    + ./acts_as_audited/test/fixtures/user.rb
    + ./acts_as_audited/test/schema.rb
    + ./acts_as_audited/test/test_helper.rb
    

    It “works for me™” on a fresh rails 1.2.3 project. Feel free to email or IM me with more details.

  68. Tom Tom April 26, 2007

    hey Brandon, thanks for the plugin…
    The username column is not being filled in in the audit table. I think its because my user model uses login instead of username as the human readable string that identifies the user.
    so in the audit.rb I changed the line self.username = user
    to self.username = user.login. But it still doesn’t work.
    Also current_user is already defined “we use the acts_as_auth..” plugin. Iam a little new to ruby but I can’t figure out how to get the username column to be filled in correctly.

  69. Sheldon Hearn Sheldon Hearn May 1, 2007

    Great stuff, thanks.

    If I don’t specify audit in ApplicationController, then the sweepers aren’t registered and so audits aren’t created with user information.

    But if I specify audit on the controller, then the :except option to acts_as_audited is ignored on the observed models.

    Would be nice to have my cake and eat it too. :-)

  70. Brandon Brandon May 1, 2007

    Sheldon,

    You should be able to have your cake and eat it too. Specifying audit in the controller simply calls acts_as_audited on the models IF it hasn’t already been called.

  71. Tom Healey Tom Healey May 4, 2007

    Ok lets see if I can ‘splain this.
    I am using the beast forum software in my app
    In the post and topic model it specifies that body and title are attr_accessible respectively. (these are the only places in our app we do this)
    So I excepted all the other fields but I get this error
    NoMethodError (You have a nil object when you didn’t expect it!
    You might have expected an instance of Array.
    The error occurred while evaluating nil.each):
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1671:in `attributes=’
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1505:in `initialize_without_callbacks’
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/callbacks.rb:225:in `initialize’
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/has_many_association.rb:13:in `new’
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/has_many_association.rb:13:in `build’
    .//app/controllers/topics_controller.rb:25:in `create’
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/database_statements.rb:59:in `transaction’
    /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/transactions.rb:95:in `transaction’
    .//app/controllers/topics_controller.rb:24:in `create’

    I tried removing the attr_accessible on those filds but I got other errors. So I guess my question is why doesn’t it work even when I exclude all the fields except the attr_accessible fields.

    Thanks in advance,
    Tom

  72. Tom Healey Tom Healey May 4, 2007

    Brandon,
    In addition to my previous post I was wondering why when I disabled the cache the acts_as_audited plugin was still “in effect”.

  73. Brandon Brandon May 5, 2007

    Tom,

    There’s actually a Rails bug that prevents you from using attr_protected and attr_accessible on the same model, and acts_as_audited uses attr_protected :audit_ids to prevent malicious users from messing with the audit associations.

    I’m not sure what you mean by your second question.

  74. ANR ANR May 16, 2007

    Hello,

    Has anyone used this plugin with Goldberg (link below)? I am currently getting an error within Goldberg only when I have auditing enabled for a particular model. If I disable auditing by commenting out of the application controller, I no longer get any errors. This error only ocurrs when using Goldberg related functionality but the rest of the application works fine.

    Below is a bit more details of the issue. Dave from Goldberg Forums is currently assisting me with this but if anyone has used Goldberg and has a workaround, any guidance will be greatly appreciated. Thanks.

    Goldberg
    http://goldberg.240gl.org/home
    “Goldberg is a Ruby on Rails generator that enables you to set up fully-featured websites within minutes”

    Steps to Reproduce:
    Administration > Setup > Controllers / Actions
    Choose Application and then a controller.
    Then click on ‘Add New Action’ and error occurs immediately.
    It will also occur if you try clicking on other parts of interface or reaching other pages.

    Environment:
    Rails v1.2.3
    Goldberg v0.2.0
    MySQL 5.0.26-community-nt
    WEBrick
    Plugins: userstamp and acts_as_audited.

    Sincerely,

    ANR

    Error 1:
    NoMethodError in Goldberg/controller actionsController#new_for

    You have a nil object when you didn’t expect it!
    The error occurred while evaluating nil.controller_name

    Error 2:
    NoMethodError in Goldberg/controller actionsController#show

    undefined method `controller_name’ for nil:NilClass

  75. John John May 29, 2007

    I’m using acts_as_authenticated and userstamp with acts_as_audited. Has there been a resolution on how to get the current_user in your controller without interfering with these plugins?

    Doesn’t including AuthenticatedSystem in my ApplicationController bring the current_user method to all controllers?

    For userstamp I’m also setting User.current_user (as a cattr_accessor) so if this solution is better, I could use this as well.

    I’ve read through many of the comments but haven’t reached a conclusion. I’m running out of ideas. Anyone?

  76. Brandon Brandon May 30, 2007

    John,

    I’m not familiar with userstamp, but acts_as_audited should “Just Work™” with acts_as_authenticated if you’re declaring audit MyModel in your controller.

    The comments on this post about User.current_user are no longer relevant. acts_as_audited was updated and that has been removed.

  77. John John May 30, 2007

    Thanks for the info Brandon (and sorry for the multiple posts. I got a proxy error and my post timed out several times. It must have posted anyway).

    I’ve tried using the “audit MyModel” within my App controller and the controller in question. The only method I’ve been able to get the auditable plugin working is by adding acts_as_auditable to the model. In this case it adds a record, but doesn’t put any data in the user fields.

    I’m going to do some more debugging to figure out what I’m missing. Do you have any other ideas?

  78. Brandon Brandon May 30, 2007

    John,

    Sounds like you’re running in development mode. Check out the caveats section in the post or the plugin’s README.

  79. John John May 30, 2007

    Right on! I had the cache vars set to true but rails reset one of them to false at a later spot in the dev environment config.

    Everything seems to be working great. Thanks for the plugin! I remember implementing something like this in PHP about a year ago without a framework and it was a hassle.

  80. carlivar carlivar June 11, 2007

    The topic seems to have been dropped, but way back in the early comments you mention possibly adding versioning (allow individual fields to be reverted). I definitely vote for this!

    I just took out acts_as_versioned from my app because it is simply too much hassle. Requires two database tables for every model which I got sick of maintaining. I also think acts_as_versioned gave me a big speed hit but I’m still testing that.

    Anyway, the “log the diffs” model is much better for versioning IMHO. Thanks!

  81. Brandon Brandon June 18, 2007

    carlivar,

    Just for you, I’ve updated acts_as_audited to include some sort of revisioning. Check out my latest post for more info. I’d love to get your feedback.

  82. John Devine John Devine July 12, 2007

    This works:
    =====
    class PatientDetail < ActiveRecord::Base

    acts_as_audited

    end
    ===
    if I add the following it ceases to work
    ===
    class ApplicationController < ActionController::Base



    1. Pick a unique cookie name to distinguish our session data from others’
      session :session_key => ‘_ClinicCare_session_id’

    audit PatientDetail
    protected
    def current_user
    @user = Goldberg.user ? Goldberg.user.name : ‘(not logged in)’
    end

    end
    ===


    if I comment out “audit PatientDetail” it will work again but does not pass the user through to the log. I have checked to see if there is a value for @user and there is one.


    I have run the tests and they pass.


    Any help is good help:)

  83. Brandon Brandon July 12, 2007

    John,

    Please read the caveats section in the post and the plethora of other comments about the same issue. audit Model in the controller depends on Rails caching, and is therefore is disabled by default in development mode.

  84. hans reiser hans reiser July 17, 2007

    would be cool to have the possibility to completely disable the saving of a delete-action, since this makes trouble, the referring objects are not existing anymore…

  85. Kris Kris August 5, 2007

    Hi Brandon,

    Thanks for this plugin, I just have one quick question though.. I can’t seem to get the user columns filled in.

    If I have done this in my dev environment:

    config.cache_classes = true
    config.action_controller.perform_caching = true
    

    and this

    class MyModel &lt; ActiveRecord::Base
      acts_as_audited
    end
    

    where should I put the

    protected
      def current_user
        @user ||= User.find(session[:user])
      end
    

    such that I may have the three user columns filled up? Sorry if this is a very lame question. I’m not too good with RoR. :)

    Thanks so much in advance!

  86. Brandon Brandon August 5, 2007

    Kris,

    See the “Auditing in Rails” section above. It shows that you need to declare “audit MyModel” and define current_user in ApplicationController.

  87. Bugbuster Bugbuster August 7, 2007

    Hi, I have one problem, I’m auditing an “Article” model wich has “Title” and “Text” fields.
    The problem is, when I create an article, the event is logged correctly, but in the “changes” column I have something like this:


    title:
    -
    - a title
    text:
    -
    - some text

    So when I access the Article in this way:
    article.audits.first.changes
    I get
    {"text"=>[nil, “a title”], “title”=>[nil, “some text”]}

    so that
    article.audits.first.changes[:title] returns NIL

    What’s wrong?
    The problem is the same with every model and field, I always have a NIL object first.

    Thanks, and I hope that this will be useful for others with the same problem

  88. Brandon Brandon August 7, 2007

    Bugbuster,

    For each modification, acts_as_audited stores an array with the old attribute and the new attribute. On create, the old attribute obviously didn’t exist, so it will always be nil. So to get to the new attribute, you could do article.audits.first.changes[:title].last

    Brandon

  89. Bill Pratt Bill Pratt August 9, 2007

    There was a comment made about the ability to ignore delete / destroy actions altogether. I agree, but I found an option that I liked better for my situation, acts_as_paranoid. This plugin overrides destroy by setting the deleted_at timestamp column to the current time. It also overrides find and count to ignore “deleted” items. This still effectively deletes them, but allows this plugin to resurrect them. Hope this helps someone, and Brandon, thanks for the great plugin.

  90. Bill Pratt Bill Pratt August 9, 2007

    I also noticed that this will create an audit trail even if no attributes are changed. This may be necessary for some instances, but I don’t care if nothing is actually modified. Changing line 167 in lib/acts_as_audited.rb to:

    self.audits.create(:changes => changed_attributes, :action =&gt; action.to_s, :user =&gt; user) if !changed_attributes.empty?

    will stop this.

  91. Peter Peter August 11, 2007

    Regarding acts_as_paranoid, it seems that Rick does no longer endorse it.

    Still being a Ruby newbie, I managed to write a revive method that will revive destroyed records. In order to get this to work, I added a before_destroy callback that will add every attribute’s value to the @changed_attributes hash so that the full state of the model is audited. I’ve posted a diff here. If there’s a better way to do this, I’m all ears.

    Using acts_as_audited, is there a way to have the user attributes in the audits table be populated also when using script/console or are the sweepers depending on being used through a running app?

  92. Brandon Brandon August 17, 2007

    Peter,

    There is a #revision method on Audit that will reconstruct the model for that revision using the audits.

    At this time, there isn’t a way to populate the user field from the console. It would probably be a nice addition though.

  93. Bhushan Ahire Bhushan Ahire August 23, 2007

    Hi Brandon,
    I seems to gr8 plug in over acts_as_versioned in space saving.
    I have one problem that,
    If some change are made in the table and I dont know on what column changes are made, then how would I fetch this changes.
    Or rather display the changes in well manner.
    Because if I chack for any column with name then it give nil method error if for that column no changes are made.
    Please reply if anyone has the solution.

    Thanks

  94. Bilson Bilson August 23, 2007

    If I am understanding this correctly, reverting to a specific version number actually reverts to the number preceding that number? (i.e. to revert to the first version I need to select revision 2, to revert to version 3 I select and save version 4)

    Or am I doing something incorrectly?

    task.revision(4)
    task.save
    This will give me version 3.

    BTW – This plugin is amazing.

  95. CH Chee CH Chee August 25, 2007

    Hi Brandon

    I am using acts_as_audited for audit trail in production environment.

    In order to view the audits table within my apps, I had set up a
    controller with a ActiveScaffold config block.

    AS displays fine in List but when I click next or any of the pages in
    the pagination, I get the following message

    TypeError in Audits#update_table
    Showing vendor/plugins/active_scaffold/frontends/default/views/
    _list_record.rhtml where line #7 raised:

    BigDecimal can’t be coerced into BigDecimal

    How can I workaround this BgDecimals issue.
    BTW, I have absolutely no issue in using Active Scaffold to display the other 200 _ tables in my apps . Only in the audits atble am I having the BifDecimnal issue.

  96. Brandon Brandon August 25, 2007

    Ch Chee,

    If you would leave a real email address, you would have gotten my email the last time you posted explaining that I’m pretty sure the issue you’re running into is not an acts_as_audited issue. I’ve never used ActiveScaffold, so I can’t help you out.

  97. CH Chee CH Chee August 25, 2007

    Hi Brandon

    TQ for responding !

    I have found the solution to the Big Decimal issue as it is actually an unfixed rails issue and Michael Raiden has a temporary solution which actually works !

    BTW, the email adress is my working email address and recently the spam filter had been tightened up. Were you getting the BW filter rejection ?

  98. Sal Scotto Sal Scotto August 31, 2007

    nice to see this plug-in, I had created something very similar to this for my rails environment, with the exception of making it standalone gem usable at the model level, and not polymorphicly associating it with the audited class.

  99. Sal Scotto Sal Scotto August 31, 2007

    you should add these to your exception filter
    ‘changed_on’, ‘updated_at’, ‘created_at’, ‘created_on’, ‘updated_on’, ‘type’, ‘position’, ‘lock_version’, ‘parent_id’, ‘lft’, ‘rgt’, ‘quote’, ‘template’]

  100. Brandon Brandon August 31, 2007

    Sal Scotto,

    id, type, lock_version, updated_at and created_at are already ignored. I could see situations where people would actually want to audit the other fields, so I don’t think that ignoring them in the plugin is a good idea. You can add those for your specific model.

  101. Daniel Daniel September 4, 2007

    Hello,
    first of all nice plugin. i have a problem like a few people here.
    i can’t get the plugin to log user data. caching settings are done-
    the plugin isn’t logging any user data on a linux production box, though.

    For authentication i’m using the latest active_rbac version.
    active_rbac provides a current_user function that is mixed in from active_rbac. current_user gives me a User record. does the plugin need the @user variable, or is a valid AR object from current_user enough? any hints to get it work ith the latest active_rbac version?

    the latest active_rbac demo version can be found at:
    svn://rubyforge.org/var/svn/active-rbac/active-rbac/trunk/demo

    would be great if could have look why it isn’t working as axpected.

    tia

    Daniel

  102. Szymon Szymon September 14, 2007

    Hi,

    I’m trying to use this plugin with restful_authentication (should be the same as acts_as_authenticated).

    At first I was setting my config incorrectly (in my main environment.rb file instead of development.rb), but after fixing this mistake I get correctly logged user_id and user_type. However, I don’t get username logged.

    I don’t have username field in my User model – I’ve got custom full_name method that uses 2 fields – first_name and last_name.

    Is there any easy step by step guide how to make username work with custom field/method in User model?

    Thank you in advance

  103. Brandon Brandon September 14, 2007

    Szymon,

    The username field is just for those that don’t have a user model and just want to store the user as a string (e.g. using HTTP basic auth). If you have a user model, it will set the user_id and user_type, which should be all you need.

  104. Brennan Dunn Brennan Dunn September 16, 2007

    I modified the plugin a bit to do some things I need it to do in my application.

    Find all audits of an audited class
    acts_as_audited.rb


    def audits(*args)
    options = {:conditions => {:auditable_type => class_name}, :order => ‘audits.version desc’}.merge(args))
    Audit.find(:all, options)
    end

    Supply either one or an array of audited classes, along with optional arguments, and have audit records returned
    audit.rb


    def self.pool(classes, *args)
    classes = classes.is_a?(Array) ? classes : [classes]
    options = extract_options_from_args({:conditions => [“audits.auditable_type in (?)”, classes.map{|x| x.class_name}]})
    find(:all, options)
    end

  105. Rustam Rustam October 9, 2007

    wow I make it work with acts_as_rateable and hmp =)

  106. skwasha skwasha October 14, 2007

    So, since Restful Authentication defines login, password, and password as attr_accessible. Does that mean I can’t define my User model as auditable?

    thanx!

  107. Sachin Sachin November 15, 2007

    Howdy Brandon?

    First off, great plugin, it is what I have been looking for and it fits my needs for the most part. However, I wonder if I could audit on association columns as well. I mean, I have a Requirement model class that “habtm” Projects model class. So, anytime, a user makes a change only to associate/disassociate which projects are affected/not affected, system essentially made a change in the associated column (Projects model) which means that “audit” did not pick any change. This is a dilemma, even though, I understand that the change occurred in the Projects model yet from the user standpoint, the change occurred on the Requirements.

    Please help! Any ideas to go about resolving this problem will greatly help.

    Thank you very much for considering.
    —Sachin

  108. ynw ynw November 25, 2007

    Nice plugin =)

  109. Brandon Brandon November 26, 2007

    Sachin,

    As I mentioned in a comment above, auditing associations is not a feature I needed, but I’d gladly accept a patch that implements it.

    To solve your problem, you could change the habtm to a has_many :through and audit the join a model.

  110. Eric Pugh Eric Pugh November 28, 2007

    Does acts_as_audited work with Rails 2.0? I tried running the migration and get a missing acts_as_list method error, I assume because that is now a plugin in Rails 2….

    /opt/local/lib/ruby/gems/1.8/gems/activerecord-1.99.0.8178/lib/active_record/base.rb:1334:in `method_missing’: undefined method `acts_as_list’ for # (NoMethodError)
    from /Users/epugh/Documents/code/hightechcville/trunk/vendor/plugins/acts_as_audited/lib/audit.rb:14

  111. Alex Alex November 28, 2007

    acts_as_audited does work with Rails 2.0.

    However, you have to go through a little bit of pain with acts_as_list – you might have to rename the plugin folder in vendor/plugins to ‘01_acts_as_list’ or similar in order for it to load before acts_as_audited requires it.

  112. Wolfgang Wolfgang December 3, 2007

    @Rails 2.0

    Instead of messing with directory names,
    simply set

    config.plugins = %W( acts_as_list acts_as_audited )

    in config/environment.rb

  113. Aaron Aaron December 5, 2007

    I’m using acts_as_audited with ActiveScaffold. When auditing is enabled and I try to open a nested scaffold, I get an exception. Apparently, this happens because acts_as_audited is not designed to handle callbacks for nested actions (due to components).

    For example, the Clients scaffold shows a list of clients. If I click on the meeting registrations for a client, a nested scaffold showing the registrations should open. The sweeper tries to execute before_clients_nested, then before_meeting_registrations_table, then after_meeting_registrations_table, and then — an error, because the sweeper’s controller was set to nil the first time it executed an after callback, and then it tries to execute what should be the after callback for the clients controller. How difficult is it to modify acts_as_audited to work with components?

  114. Patrick Crosby Patrick Crosby December 11, 2007

    I wrote a blog post about how to get acts_as_audited to work in Rails 2 for anyone who has been having trouble with it.

  115. Brandon Brandon December 11, 2007

    Thanks Patrick.

    I’m going to be using acts_as_audited in another project soon, so there should be a slew of updates, including removing the dependence on acts_as_list.

  116. Aaron Aaron December 13, 2007

    It turns out that acts_as_audited can be used with ActiveScaffold simply by modifying a line in audit_sweeper.rb:

    http://groups.google.com/group/activescaffold/browse_thread/thread/a717fa3c8b7433a6

    Also, I modified the write_audit method in acts_as_audited.rb so that dates/times would be serialized in a YAML-compatible format. (I had changed the default date and time formats for my application, and the plugin was using those formats to serialize changes.)

  117. mickey mickey December 17, 2007

    i can’t get this plugin to work with rails 1.2.6: undefined method `extract_options!’

    Research revealed that this function was added with rails 2.0.1 recently. Probably the plugin was updated too but that update broke backwards compatibility?

  118. Brandon Brandon December 17, 2007

    micky: thanks, I recently made some updates and didn’t test them against rails 1.2. It should be fixed now.

  119. cal cal January 2, 2008

    Newbie questions for this great plugin:

    In the app/models/*.rb files I want audited, I’ve included an “acts_as_audited” line. Do I need to specify the audited classes in the app/controllers/application_controller.rb as well?

    On a possibly-related note, I’m having problems getting the Model.revision_at(date) working. Revisions 0 and 1 seem to be duds. Is this proper behavior?

    &gt;&gt; Comment.find(1421).revisions.size
    =&gt; 2
    &gt;&gt; Comment.find(1421).revision(0).text
    =&gt; ""
    &gt;&gt; Comment.find(1421).revision(1).text
    =&gt; ""
    &gt;&gt; Comment.find(1421).revision(2).text
    =&gt; "original text"
    &gt;&gt; Comment.find(1421).revision(3).text
    =&gt; "changed text"
    &gt;&gt; Comment.find(1421).revision(4).text
    =&gt; "changed text"
    
  120. Pefmeister Pefmeister January 3, 2008

    Hi Brandon,

    Very nice plugin, just what I was looking for. Besides the BigDecimal problem, is there any chance to get hbtm relations audited? I’ve got a few structures that have m:n dependencies and would like to record changes to that relationship.

    Thanks,
    Pefmeister

  121. Brad Midgley Brad Midgley January 18, 2008

    Thanks for the contribution to the community.

    fwiw, I’m unable to get user logging to work with restful_authentication with any amount of current_user wrangling. I can see that write_audit is only called with one parameter so the user value always is set to nul. Have I configured it wrong? Is the execution not supposed to go from eg audit_create→write_audit this way?

  122. Ron B Ron B November 19, 2008

    I am noticing a lot of rows in the audits table where the value in changes is ==={}. Why is it logging updates that have no changed data. I’m guessing it is because I take the params for the form and do an update_attributes on the object (even if the user did not actually change and form data)

  123. Brandon Brandon November 19, 2008

    Ron B,

    I’ve been noticing this too. It appears that the “dirty tracking” code in Rails sees an attribute as changed, even if you set it to the same value.

    I don’t think it used to be like that, but I’m not sure at what point it changed. I’ll try to come up with a workaround and post here when I have something.

  124. Andrew Andrew December 8, 2008

    Great plugin! I couldn’t find how to do this: I’m trying to use a current_user.audits to find all audits from a user. I created the proper associations along with the Audit model, but the current_user.audits doesn’t work. Is there a proper way to do it?

  125. Brandon Brandon December 8, 2008

    Andrew,

    You should be able to define an association on your user model:

    class User &lt; ActiveRecord::Base
      has_many :audits, :as =&gt; :user
    end
    
  126. Trevor Trevor December 11, 2008

    Is this plugin compatible with Rails 2.2? When I create or update, the value in the changes field is always ---.

  127. Brandon Brandon December 12, 2008

    Yep, it works with 2.2. I’m guessing you’re viewing the a gui. The changes are a text field that store a serialized hash of the changes, and the gui is probably truncating it.

  128. Chris Chris January 2, 2009

    I’d like to display both the new and prior value. How can I retrieve the prior attribute value for each audit change since only the changed value is stored?

  129. Brandon Brandon January 4, 2009

    Chris: This used to be a feature, but it got removed when I updated the plugin to make it Rails 2 compatible. I will plan to add it back soon.

  130. Chris Chris January 5, 2009

    Excellent, looking forward to the addition. Thanks Brandon!

  131. Josh Josh January 8, 2009

    Great plug-in, easy to use and configure. I did run into one problem when running in production. Any audited action results in the error:

    undefined method `controller_name' for nil:NilClass .../ruby/1.8/gems/actionpack-2.2.2/lib/action_controller/caching/sweeping.rb:83:in `callback' .../ruby/1.8/gems/actionpack-2.2.2/lib/action_controller/caching/sweeping.rb:65:in `after' .../ruby/1.8/gems/actionpack-2.2.2/lib/action_controller/filters.rb:208:in `around_proc' ...

    This only appears to be a problem when I call audit MyModel in the ApplicationControler; when I put the audit call in the controllers themselves, everything works perfectly. I am using namedspaced controllers (e.g. Admin::UsersController), but have not been able to figure out how caching in production mode would created this problem in the sweeper. Any thoughts.

    Thanks.

  132. Josh Josh January 8, 2009

    Sorry, I jumped the gun on my issue a little. After working with the issue more, I’ve found that the real issue is that I was trying to call audit twice:

    audit Album, User audit Photo, :only =&gt; [ :created, :destroy ]

    Instead, I used acts_as_audited in my Photo model, although because I handle multiple models in one form (Album, Photo), current_user is not set for the Photo.

  133. Janine Janine January 16, 2009

    Thanks for a great plugin.

    I’m experiencing a problem with the revision feature and getting incorrect results. It occurs for attributes that are changed, but didn’t change in the previous revision(s). Because changes are gathered from latest to desired, attributes maintain their latest value. Instead, the unchanged attributes need to be set to their value farther back in time. For example, if I have a model with the following audit changes:

    version=3, name='C', address='123 Main St'
    version=2, name='B'
    version=1, name='A', address='555 Abc Ln'
    

    Running model.revision, I get…


    revision(3) => name=‘C’, address=‘123 Main St’
    revision(2) => name=‘B’, address=‘123 Main St’ << ERROR
    revision(1) => name=‘A’, address=‘555 Abc Ln’

  134. Brandon Brandon January 16, 2009

    Janine,

    You’re right, that is definitely broken. I don’t have time to fix it this moment, but I created a failing spec for it and added a ticket to lighhouse.

    If you have time to investigate it, I’d happily accept a patch. Otherwise I’ll try to get to it soon.

  135. Harish Harish January 22, 2009

    Hi,
    I am still using my rails version as 1.2.3. I installed this plugin, but when I use this, I am getting the error,
    undefined method `extract_options!’ for [User]:Array,
    Do you have the older version to work out with this?
    Thanks,
    Harish

  136. Brandon Brandon January 22, 2009

    Harish,

    I’ve added a tag in git for a version that should be compatible with Rails 1.2.

  137. Craig Knox Craig Knox January 27, 2009

    Hi Brandon,

    Great plugin but I notice that it always logs float fields as changed, even if the value was originally NULL in the database, and the user enters nothing in the input tag for the field. Is this how it is supposed to work or is it a bug?

    Thanks,
    Craig

  138. Brandon Brandon January 28, 2009

    Janine: The issue with accessing revisions is now fixed.

    Craig: This is actually a bug in Active Record’s dirty tracking with integer columns. My guess is that you have an integer column that is nil. When you set a nil integer to an empty string (such as, when you submit a form), Active Record sees that field as changed. It’s fixed in edge-rails. I’m open to suggestions for working around it in the interim.

  139. JDutil JDutil January 28, 2009

    I am experiencing an issue that it seems many others are as well with the user data not being saved. I had thought it was because I used a model admin_user rather than user at first, but I found that it does work in the production environment though. What steps do I need to take in order to have users tracked in my development environment?

  140. sock sock February 5, 2009

    Hi, I was wondering how I could force an audit to be created on a parent object when any child object gets changed?

  141. Swards Swards February 6, 2009

    Hi – I’m trying to use AuthLogic with Acts_as_audited and I’m seeing a problem. First – AuthLogic recommends the ‘current_user’ method be declared private, and it’s not available to the Session class in Acts as audited – resulting in a nil user id.

    If I move the mothod so it is protected not private, there is an endless loop – Authlogic calls current_user in the beginning of the request which causes an update to the record (last_request_at) which triggers the Acts as Audited observer to create an audit, which needs to reference current_user, etc. – stack overflow follows.

    Is there a way to get these two to work well together?

  142. Gert Thiel Gert Thiel February 22, 2009

    I can’t find any licensing information.

  143. Brandon Brandon February 23, 2009

    Gert: http://github.com/collectiveidea/acts_as_audited/commit/a044c5cf028fef2ef99d29416d56428a449d80f6

    Swards: I’ve never used authlogic, so I’m not too familiar with how it works, but it sounds like you’re trying to audit the last_request_at. If you exclude that field from being audited, the overflow should go away, right?

     class User &lt; ActiveRecord::Base
      acts_as_audited :except =&gt; :last_request_at
    end
  144. boblin boblin March 3, 2009

    I am trying to use together acts_as_audited and acts-as-taggable-on

    I have this in ApplicationController:

    class ApplicationController < ActionController::Base
    audit Tagging

    end

    When I change some tag i don’t get one but many records in Audit table:


    Tagging Create (0.3ms) INSERT INTO `taggings` (`tagger_id`, `created_at`, `tag_id`, `taggable_id`, `context`, `taggable_type`, `tagger_type`) VALUES
    SQL (0.4ms) SELECT max(`audits`.version) AS max_version FROM `audits` WHERE (`audits`.`auditable_id` = 3289 AND `audits`.`auditable_type` = ‘Tagging’ )
    Audit Create (0.3ms) INSERT INTO `audits` (`created_at`, `username`, `action`, `user_type`, `auditable_type`, `user_id`, `version`, `auditable_id`, `changes`) VALUES
    SQL (0.4ms) SELECT max(`audits`.version) AS max_version FROM `audits` WHERE (`audits`.`auditable_id` = 3289 AND `audits`.`auditable_type` = ‘Tagging’ )
    …………………….
    SQL (0.6ms) SELECT max(`audits`.version) AS max_version FROM `audits` WHERE (`audits`.`auditable_id` = 3289 AND `audits`.`auditable_type` = ‘Tagging’ )
    Audit Create (0.4ms) INSERT INTO `audits` (`created_at`, `username`, `action`, `user_type`, `auditable_type`, `user_id`, `version`, `auditable_id`, `changes`) VALUES
    SQL (10.1ms) COMMIT

    What is wrong?

    Thanks
    Bo.

  145. Brandon Brandon March 3, 2009

    boblin: Strang. I’m not sure what’s going on. Could you open a lighthouse ticket (URL in README) with more information?

  146. boblin boblin March 5, 2009

    Thanks Brandon for reply. I’m trying investigate where is the problem. I found another problem with act_as_taggable_on and act_as_audited. I’ve created new ticket.

  147. David David May 7, 2009

    Great plugin. Exactly what I needed. Many thanks.

  148. Moo Moo May 7, 2009

    First, thanks for the great plugin. saved me lots of time!

    I am having issues with limiting the audits, however. I would like to control what action gets audited. For example, for my Post model, i don’t want “create” to be audited, but only “update” and “destroy” to be audited. I tried the following in my controller:

    audit Post, :only => [:update, :destroy]

    but it still logs the “create” action. Looks like it should be able to do this right? I am using Rails 2.3.

    Thank you!

  149. Jamie Jamie June 10, 2009

    Hey there, I saw earlier that you mentioned auditing a join table for a has_many :through relationship. I’m doing that and the creates are audited just fine, unfortunately destroys don’t get audited. Is there something I can do to get destroys audited for has_many :through relationships?

    Thanks,
    Jamie

  150. Jamie Jamie June 10, 2009

    After some digging I found that when using HM:T relationships, the delete_all method is used rather than destroy on the join model. This is unfortunate because it means that the acts_as_audited hooks don’t have a way of knowing about deletes.

    Any way to somehow hook acts_as_audited into delete and delete_all actions? It’s very much needed as far as I can tell if one wants to audit when a HM:T relationship instance is removed.

    Jamie

  151. Jamie Jamie June 15, 2009

    Just as a follow-up…for the join models that I want to audit destroys, I just overrode the delete_all method…something like this works:

    # Had to override the default behavior of delete_all for CategoriesMembers since HM:T relationships
    # just call delete_all rather than destroy, thereby bypassing auditing.
    def self.delete_all(conditions = nil)
    cm = Category.find(:first, :conditions =&gt; { :member_id =&gt; conditions['member_id'], :category_type_id =&gt; conditions['category_type_id'] }) destroy(cm.id)
    end

  152. Mark Mark June 30, 2009

    Hey Brandon, great tool here… you should be proud! I am going through your invention one file at a time to fully appreciate its capabilities.

    Question: Is there a way to exclude a field from being audited, without excluding the whole table? Such as a users table which stores a hashed password or salt, when the action is create?

    Thanks again… great job!

  153. Brandon Brandon June 30, 2009

    See the :except option in the example in the post.

  154. Ryan Ryan August 5, 2009

    I’m having the same issue with Authlogic: `:except => :last_requested_at` in the model didn’t help; nor did specifying `:only => :create, :update, :destroy` in the ApplicationController.

    However, even when I disabled auditing on the User model, while it didn’t crash, it still didn’t record the username in the audit records.

  155. Ryan Ryan August 5, 2009

    As a point of clarification:

    If I hide the current_user method in `private`, the `:except ` attribute works. In that the field isn’t audited.

  156. Ryan Ryan August 5, 2009

    The only way I can get Authlogic and Acts_as_authentic to work together is to NOT audit the User table.

  157. Marlon Marlon August 12, 2009

    Is there a google group or somesuch for this plugin?

  158. Brandon Brandon August 12, 2009

    No, but given the number of comments on this post, I probably should. :) I’ll set one up soon.

  159. Marlon Marlon August 13, 2009

    FYI, acts_as_audited doesn’t like ResourceController or the other way around….but it doesn’t have an issue with InheritedResources.

    Thanks for the plugin, it is more inline with what I needed than acts_as_versioned….plus it’s a lot easier to implement!

  160. Dharmdip Dharmdip October 26, 2009

    Hi , Brandon

    You made good plugin easy to implement and easy to use , i am facing problem while editing and plugin cause this exception but while adding it works good . Is that rails cause ?

    NameError (undefined local variable or method `changed_attributes’ for #):
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/attribute_methods.rb:205:in `method_missing’
    /vendor/plugins/acts_as_audited/lib/acts_as_audited.rb:167:in `audited_changes’
    /vendor/plugins/acts_as_audited/lib/acts_as_audited.rb:191:in `audit_update’
    /vendor/plugins/acts_as_audited/lib/acts_as_audited/audit_sweeper.rb:72:in `send’
    /vendor/plugins/acts_as_audited/lib/acts_as_audited/audit_sweeper.rb:72:in `before_update’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:157:in `send’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/observer.rb:157:in `update’
    C:/I2/ruby/lib/ruby/1.8/observer.rb:185:in `notify_observers’
    C:/I2/ruby/lib/ruby/1.8/observer.rb:184:in `each’
    C:/I2/ruby/lib/ruby/1.8/observer.rb:184:in `notify_observers’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:338:in `notify’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:302:in `callback’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:239:in `update_without_timestamps’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/timestamp.rb:38:in `update_without_user’
    /lib/usermonitor.rb:38:in `update’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:2238:in `create_or_update_without_callbacks’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:213:in `create_or_update’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1972:in `save_without_validation’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/validations.rb:934:in `save_without_transactions’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:108:in `save’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:66:in `transaction’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:80:in `transaction’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:100:in `transaction’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:108:in `save’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:120:in `rollback_active_record_state!’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/transactions.rb:108:in `save’
    /app/controllers/item_controller.rb:282:in `update_dme_item’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `send’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1158:in `perform_action_without_filters’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:697:in `call_filters’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:725:in `run_before_filters’
    /app/controllers/application.rb:151:in `set_timezone’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:469:in `send!’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:469:in `call’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:722:in `run_before_filters’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:695:in `call_filters’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:689:in `perform_action_without_benchmark’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue’
    C:/I2/ruby/lib/ruby/1.8/benchmark.rb:293:in `measure’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/rescue.rb:199:in `perform_action_without_caching’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:678:in `perform_action’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/query_cache.rb:8:in `cache’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/caching.rb:677:in `perform_action’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `send’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:524:in `process_without_filters’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/filters.rb:685:in `process_without_session_management_support’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/session_management.rb:123:in `process’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:388:in `process’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:171:in `handle_request’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:115:in `dispatch’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:126:in `dispatch_cgi’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/dispatcher.rb:9:in `dispatch’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/bin/../lib/mongrel/rails.rb:76:in `process’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/bin/../lib/mongrel/rails.rb:74:in `synchronize’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/bin/../lib/mongrel/rails.rb:74:in `process’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:159:in `process_client’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:158:in `each’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:158:in `process_client’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:285:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:285:in `initialize’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:285:in `new’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:285:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:268:in `initialize’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:268:in `new’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel.rb:268:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel/configurator.rb:282:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel/configurator.rb:281:in `each’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel/configurator.rb:281:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/bin/mongrel_rails:128:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/lib/mongrel/command.rb:212:in `run’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/mongrel-1.1.2-x86-mswin32/bin/mongrel_rails:281
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:489:in `load’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/servers/mongrel.rb:64
    C:/I2/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require’
    C:/I2/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’
    C:/I2/ruby/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
    C:/I2/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require’
    C:/I2/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require’
    script/server:3

    Thnaks ,
    Dharmdip

  161. Dharmdip Dharmdip October 27, 2009

    OK , i have solved issue !
    enjoy !

  162. Jonathan Jonathan October 29, 2009

    Brandon,

    This is a great gem, really helping me a lot. Question, I have a requirement to associate a optional comment to each Audit record. I wondered if you had an idea on the best way to implement this.

    Thanks!

  163. lyaya lyaya November 1, 2009

    Hi there,

    I’ve been using acts_as_audited for a long time now.
    I’m trying to use it with ActiveLdap, I blindly added the class to be audited and the acts_as_audited statement in the model, but it seems it doesn’t work.

    This is what i get :
    undefined local variable or method `acts_as_audited’ for # if the acts_as_audited statement is after the ldap_mapping
    NameError: undefined local variable or method `acts_as_audited’ for User(objectClass:, must:, may:<>):Class
    if i don’t use the acts_as_audited i get :
    ./vendor/plugins/acts_as_audited/lib/acts_as_audited/audit_sweeper.rb:41:in `send’:NoMethodError: undefined method `acts_as_audited’ for #

    has anybody every tried to use it with activeldap ?
    any idea on how to make it to work ?

  164. Brandon Brandon November 1, 2009

    Try including CollectiveIdea::Acts::Audited into your model. If ActiveLdap acts just like Active Record, it may work (but I doubt it).

  165. Brandon Brandon November 1, 2009

    Comments are closed. Check out the mailing list if you have questions or issues.

Post a Comment

Comments use textile. Anonymous comments will be deleted.

My name is Brandon Keepers. I like to build things, usually in Ruby or JavaScript. I work at GitHub and live in Holland, MI.

Popular Posts