laserlemon / vestal_versions Goto Github PK
View Code? Open in Web Editor NEWKeep a DRY history of your ActiveRecord models' changes
License: MIT License
Keep a DRY history of your ActiveRecord models' changes
License: MIT License
Hi,
I'm using rails3 and vestal_versions for 3 months.
Everything was fine until today.
After a "bundle install" and an update of ActiveRecord, vestal_version crashs.
With rails i got this message :
ActiveRecord::DangerousAttributeError: changes is defined by ActiveRecord
With the console, the message is the next :
ActiveRecord::DangerousAttributeError: changes is defined by ActiveRecord
The probleme is the presence of the changes column into the vestal_versions model.
It could be wisely to rename the column to don't interfer with the behavior of rails3 and ActiveReccord .
Thanks for fixing the issue :)
Hi, I didnt find any info on how to catch versions for my associations (has_many). Is there a way for the same or it is still to be implemented?
Hi,
First of all, thanks for the super useful versioning library.
As some people suggested, I'm using vestal_versions to provide optional versioning in content management solution. When a user feels happy with all the changes, s/he can choose to create a version.
I got the basic workflow working with :if
. Sweet!
However, there's a bit of inconsistency when saving content and then creating a version.
For example, I have a "document" model which has a text "content" field.
versioned :if => :check_version_creation, :only => %w(content)
:check_version_creation
returns true only when the user clicks a button "Create a new versions."
Here's steps to reproduce:
true
so that :check_version_creation
returns true
and calling @document.update_attributes)Expected: A new version is created, and version number is 2 now.
Actual: Version number stays as 1.
My observation is that this happens because vestal_versions compares changes against the latest parent data rather than the previous version's data (which is reasonable). When the user creates a version, since this is a second save, vestal_version doesn't see any changes and does not create a new version.
This causes another issue with versions.changes field. If there are many changes between two revisions, those changes are not captured in versions.changes column because it only captures deltas against the parent table.
I understand that I'm using this library in an unconventional way, but if you could point me to a right direction, your help would be greatly appreciated.
Best regards,
Amie
v1 = Version.new(:number => 1, :versioned_type => "Foo") v2 = Version.new(:number => 1, :versioned_type => "Bar") v1 == v2 # => true
suggest something like the patch at:
http://github.com/davidlee/vestal_versions/commit/9a1318a36bd1ace4a6db1569e933bc61d97fab84
cheers.
DL
I'm trying to install this today and I can't get past the rake db:migrate step.
PGError: ERROR: relation "versioneds" does not exist
: CREATE TABLE "versions" ("id" serial primary key, "versioned_id" integer, "versioned_type" character varying(255), "changes" text, "number" integer, "created_at" timestamp, FOREIGN KEY (versioned_id) REFERENCES versioneds (id))
What's the point of the current version 1 if changes = nil? I propose that versions only get created when a model gets updated.
I'm questioning the usefulness of creating an extra version every time I use revert_to!. I feel that this method should change to a specific version and keep it there, as opposed to changing to the version and then saving the record, which creates a new and duplicated/unnecessary version.
I know that you create a new version every time a record is saved, but I'm wondering if this should be handled differently or overridden when using revert_to!. I just foresee a huge mess of duplicate versions when I should just be able to switch between them.
x = Artikel.find_by_prodid '7394930'
puts x.version
works
x = Artikel.where(:prodid => '7394930')
puts x.version
doesn't (undefined method `version' for #ActiveRecord::Relation:0x914304e)
I suggest to support the options :next and :previous on revert_to. It would be very simple to implement and make the code sweeter! =D
The other day I was using vestal_versions, and I wanted to display a page with all the titles a post had had since its creation. So, I basically needed an array of post objects, each of them belonging to a revision.
I ended up writing this method in my model:
def revisions
versions.collect do |version|
revert_to(version)
self.clone
end
end
Then I thought that it might be interesting to have it inside the plugin. So, in case you (or someone else) is interested, I share the idea.
Regards, and thanks for this very useful gem.
When attempting to use vestal_versions 1.0.1 in a Rails 2.1 app, the following error occurs:
/opt/ruby-enterprise-1.8.6-20080810/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/base.rb:1667:in
method_missing':NoMethodError: undefined method default_scope' for #<Class:0xb0ae758>
It appears that default_scope was added in Rails 2.3. I don't expect a fix to make this work with Rails 2.1 (vestal_versions 0.8.3 is working fine for our needs at the moment), but it would be helpful to update the gemspec to indicate that it requires Rails 2.3.
Thanks for a great gem!
Using Thinking Shpinx, and Formtastic with vestal_versions they bring up some interesting errors... Namely:
"undefined method `reflect_on_association' for VestalVersions::Tagging:Module"
I assume this is because these addons are trying to talk to VestalVersions and its not responding as it expects?
I use,
ActiveRecord::Base.pluralize_table_names = false
the plugin won't work
So, I want to record the user who submits each version change,
But if I try and do this via the vestial_versions :updated_by I can't record the creator (I presume because no version is recorded for the first version... SO any chance to make this recording an option, I I can work around it by just recording a 'created_by' but in that case i might as well record a 'modified_by' and just always use that field on my record rather than vestial versions clever updated_by field... I removing version=1 was probably being too clever with resource usage! maybe make it switchable?
Cheers,
James
The version table currently has columns for user_id and user_type however they don't appear to be supported. Has anyone gotten user_id or user_type to work with this fork?
I have a Company
model as shown below:
class Company < ActiveRecord::Base
versioned
end
c = Company.create(:name => "ABC", :address => "XYZ") # version 1
c.update_attribute(:zip => "3545") # version 2
c.update_attribute(:address => "PQR") # version 3
c.update_attribute(:phone => "546456") # version 4
How do I get the complete Company
object at version 2? I tried to use c.versions.at(2)
. That returns me an VestalVersions
object.
Hi,
I needed to show differences between 2 versions, but not necessarly adjacent.
Let's say I have a Page model, with a title
, a content
, a published
boolean, a published_at
date and a synced_at
date. The synced_at
is relevant because that's my 'from' date.
I've made some changes and I get this :
>> p = Page.first
=> #<Page id: 1, title: "Bonjour tout le monde", content: "Ceci est un super Hello World!", published: true, published_at: "2009-09-12 12:30:56", created_at: "2009-09-11 14:16:08", updated_at: "2009-09-21 15:00:47", synced_at: "2009-09-11 18:16:08">
>> p.versions
=> [#<Version id: 1, versioned_id: 1, versioned_type: "Page", changes: nil, number: 1, created_at: "2009-09-11 14:16:08">, #<Version id: 2, versioned_id: 1, versioned_type: "Page", changes: {"updated_at"=>[Fri Sep 11 14:16:08 UTC 2009, Mon Sep 21 14:17:28 UTC 2009], "published"=>[false, true], "published_at"=>[nil, Sat Sep 12 12:30:56 UTC 2009]}, number: 2, created_at: "2009-09-12 12:30:56">, #<Version id: 3, versioned_id: 1, versioned_type: "Page", changes: {"updated_at"=>[Mon Sep 21 14:17:28 UTC 2009, Mon Sep 21 14:18:26 UTC 2009], "title"=>["Hello World!", "Hello Everyone, including the World"]}, number: 3, created_at: "2009-09-15 10:18:26">, #<Version id: 4, versioned_id: 1, versioned_type: "Page", changes: {"updated_at"=>[Tue Sep 15 10:18:26 UTC 2009, Mon Sep 21 15:00:47 UTC 2009], "title"=>["Hello Everyone, including the World", "Bonjour tout le monde"]}, number: 4, created_at: "2009-09-21 15:00:47">]
I want to know what has been changed since the last sync (hence the synced_at
date).
With just a few minutes playing in the Rails console, I tried this :
>> changes = {}
=> {}
>> p.versions.between(p.synced_at,Time.now).each {|v| v.changes.each{|k,v| changes[k] ? changes[k][1] = v[1] : changes[k] = v } unless v.changes.nil? }
=> (…)
>> changes
=> {"updated_at"=>[Fri Sep 11 14:16:08 UTC 2009, Mon Sep 21 15:00:47 UTC 2009], "title"=>["Hello World!", "Bonjour tout le monde"], "published"=>[false, true], "published_at"=>[nil, Sat Sep 12 12:30:56 UTC 2009]}
There, I can see those changes all, in one hash, just like there has been only one change since the last sync.
I'm sure there is something better to return the hash without using the changes Hash, but I'm not as good as this in Ruby.
I don't know if it might be useful and if it deserves to be included in the plugin, that's up to you.
Could you please implement a #show_version method that could return a specific version of a model?
For example:
>> u = User.create(:first_name => 'Steve', :last_name => 'Richert')
=> #<User first_name: "Steve", last_name: "Richert">
>> u.version
=> 1
>> u.update_attribute(:first_name, 'Stephen')
=> true
>> u.show_version(:first)
=> #<User first_name: "Steve", last_name: "Richert">
>> u.show_version(2).name
=> "Stephen Richert"
This sort of functionality would be especially handy when one needs to compare the differences (if any) between two versions across multiple attributes.
Thanks for a great work. I run into small problem.
I'm not sure is it a feature or issue. For example:
t = Task.find 1
t.name = "new name"
t.save(false) # no validations
t.versions.last.changes
{"name" => [old name , new name]}
Works fine without any problems, but if I do through associations
Project
has_many :tasks
Project.tasks.last.attributes= {:id => 1 , :name = "new old name" }
Project.save(false)
Project.tasks.last.versions.last.changes
{"name" => [old name , new name]}
This wont work, Task model will be updated through associations, but version will remain the same it won't add a new one.
Marek
Is there a way to force a version increment without any changes?
This could be useful in cases when related models' versions are kept in sync even if only one of them has changed. This could be an easy way to track complex associations across versions--just get the related objects with the same version numbers.
if you try using vestal_versions with is_paranoid, the version history gets removed no matter what.
tried is_paranoid before versioned in model and vice versa. the outcome is still the same. i technically still have a record in the master table and yet all of the history is removed.
I saw this in the issue list,
http://github.com/laserlemon/vestal_versions/issues/unreads#issue/17/comment/77697
And I'm wondering if there's changes to get vestal_versions work with removed parent object?
All the best,
Hao
Instead of relying only on numbers for versioning, vestal_versions could identify versions by some optional unique string too. This would speed up a lot of scenarios, when we have to iteratively revert to previous versions in order to test some object property; with labels, we could just make one query to database if that property is uniquely tied to the label.
Hello, can you add option for versioned function to disable callbacks? I don't need to create versions every time i edit my recodrs. I want to trigger versioning when i need. Thanks.
Hi,
I've added your plugin to environment.rb and after attempt to run any rake task or script i see following error:
$ ./script/generate
/opt/local/lib/ruby/gems/1.8/gems/rails-2.3.5/lib/rails/gem_dependency.rb:119:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010. Use #requirement
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/reflection.rb:187:in quoted_table_name': undefined method
quoted_table_name' for VestalVersions::Tagging:Module (NoMethodError)
from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:1416:in configure_dependency_for_has_many' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.5/lib/active_record/associations.rb:824:in
has_many'
from (eval):3:in has_many' from /opt/local/lib/ruby/gems/1.8/gems/mbleigh-acts-as-taggable-on-1.0.5/lib/acts_as_taggable_on/acts_as_taggable_on.rb:25:in
acts_as_taggable_on'
from /opt/local/lib/ruby/gems/1.8/gems/mbleigh-acts-as-taggable-on-1.0.5/lib/acts_as_taggable_on/acts_as_taggable_on.rb:24:in class_eval' from /opt/local/lib/ruby/gems/1.8/gems/mbleigh-acts-as-taggable-on-1.0.5/lib/acts_as_taggable_on/acts_as_taggable_on.rb:24:in
acts_as_taggable_on'
from /opt/local/lib/ruby/gems/1.8/gems/mbleigh-acts-as-taggable-on-1.0.5/lib/acts_as_taggable_on/acts_as_taggable_on.rb:20:in each' from /opt/local/lib/ruby/gems/1.8/gems/mbleigh-acts-as-taggable-on-1.0.5/lib/acts_as_taggable_on/acts_as_taggable_on.rb:20:in
acts_as_taggable_on'
Can you tell me plz - what causes this error and how to solve?
I have attributes such as last_logged_in_at which I don't want to be versioned. Can we get this down the track?
I'm running both acts_as_taggable_on and vestal_versions, and I just installed the fork that fixes the issue with tags. But now when I try to create or update a record that is using versioning, I get an "undefined method `user_name=' for #VestalVersions::Version:0x10319d7b0" error. Was working fine before.
Any thoughts?
This seems to happen after updating a timestamp. Below is the code in the template that creates the TemplateError
<% @model.versions.each do |version| %>
<%= version.changes['last_run'][1] %>
<%end%>
Database entry for "changes" causing the error
--- last_run: - !timestamp 20.10.2010 - !timestamp 14.10.2010
when escaping the the exclamation mark with a forward slash in the DB the error disappears.
As I have just went thru a serious conflict between vestal_versions and acts_as_taggable_on module, I wonder if there is a way to restructure the module locations to avoid such conflict.
Hi!
Just checking out vestal_versions, looks really good.
I'm trying to modify it slightly for my needs, and I was wondering: any reason for all these alias_method_chain?
Have you thought of having a base module with trivial methods, and all the others could simply call super instead of method chaining?
I'd submit a patch if you want.
You should be able to get a specific version of a model (for example to display it) without necessarily revert it.
First off, great work!
Next, I'd like to clarify as to how do I set the user information? I know there is 'updated_by' to do the job, but where do I call it? If I have versioned a model, and my requirement is to set user information automatically when the entry is made into versions table. Right now, I have created my own callback that does the job like -
after_update :set_user_to_version
def set_user_to_version
self.versions.last.user = current_user
end
Is that the right way to do it? Also, when I try to execute 'revert_to!(<version_no>), 'set_user_to_version' is not invoked. So the state now is that user information is set in updates but not in reverts. Please elaborate a bit on this.
The problem link is http://stackoverflow.com/questions/2802310/vestal-versions-question
I would be very happy, if somebody give me an starting point.
I'd like to be sure if vestal_versions does support versioned associations (it seems like it doesn't) before switching out to another versioning gem that can support versioned associations e.g => has_versioning. I haven't looked at the code yet but I couldn't find anything related with versioned associations from the readme file or this issues section. Help would be appreciated!
Hi.
I am using your vestal_versions.
But I miss something like changed_by , where will be saved id of user who commited change to versioned data. I want to track down all chages on differents models by user.
Are you planning similiar feature?
I think more of vestal_versions' users would welcome similiar feature.
With regards Petr Blaho
It would be very nice if we could remove an specific version from database, in order to maintain it lean.
For example, I have a model that is versioned by month. This way, I have one version for 01/2009, 02/2009 and so on. But people can update an old month record, and it duplicates the version for a given month. For example, if I have a 11/2009 version and update the 02/2009 version, it gets duplicated on the database. The solution I found now is remove the 02/2009 version (and shift all previous versions' numbering to maintain the straight sequence), so it stays there only once. This solution could be incorporated to vestal_versions.
Hi,
Good plugin. I already use it. But i want to add a diff method. Its in your roadmap ?
Thank you,
Florian
I tried updating to v1.0.0, but I keep running into this undefined method 'changes' error anytime I try to run a rake task or load the rails environment.
jdutils-macbook-pro:searchburlington jdutil$ script/generate vestal_versions
/Library/Ruby/Gems/1.8/gems/vestal_versions-1.0.0/rails/../lib/vestal_versions/version.rb:16:in undef_method': undefined method
changes' for class VestalVersions::Version' (NameError) from /Library/Ruby/Gems/1.8/gems/vestal_versions-1.0.0/rails/../lib/vestal_versions/version.rb:16 from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in
gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in require' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:156:in
require'
from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:521:in new_constants_in' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:156:in
require'
from /Library/Ruby/Gems/1.8/gems/vestal_versions-1.0.0/rails/../lib/vestal_versions.rb:24
from /Library/Ruby/Gems/1.8/gems/vestal_versions-1.0.0/rails/../lib/vestal_versions.rb:24:in each' from /Library/Ruby/Gems/1.8/gems/vestal_versions-1.0.0/rails/../lib/vestal_versions.rb:24 from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in
gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in require' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:156:in
require'
from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:521:in new_constants_in' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:156:in
require'
from /Library/Ruby/Gems/1.8/gems/vestal_versions-1.0.0/rails/init.rb:1:in evaluate_init_rb' from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/plugin.rb:158:in
evaluate_init_rb'
from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/core_ext/kernel/reporting.rb:11:in silence_warnings' from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/plugin.rb:154:in
evaluate_init_rb'
from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/plugin.rb:48:in load' from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/plugin/loader.rb:38:in
load_plugins'
from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/plugin/loader.rb:37:in each' from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/plugin/loader.rb:37:in
load_plugins'
from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/initializer.rb:369:in load_plugins' from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/initializer.rb:165:in
process'
from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/initializer.rb:113:in send' from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/initializer.rb:113:in
run'
from /Users/jdutil/searchburlington/config/environment.rb:11
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in gem_original_require' from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in
require'
from /Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/commands/generate.rb:1
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in gem_original_require' from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in
require'
from script/generate:3
What I did to get the user to save to my foo model:
Everything else works great, I think if you solved this user issue the gem would be pretty polished :)
First of all, thanks a lot for the great gem, very useful an easy to use...
I've a little problem versioning models which have relations.
When I'm in a view displaying all the history of an istance I write:
<% @design.versions.each do |v| %>
<% @design.revert_to(v.number) %>
<%= render :partial => "state", :locals => {:state => v} %>
<% end %>
This couse my @design fields to have the correct attribute, but @design belogns to client, so the client_id field is correct, but @design.client is the old one. What I had to do is:
<% @design.versions.each do |v| %>
<% @design.revert_to(v.number) %>
<% @design.client.reload %>
<%= render :partial => "state", :locals => {:state => v} %>
<% end %>
Which works well, but I was wondering if it can be done somewhere in the gem itself!
Again. thanks for the great work!
Hi,
First of all, well done for this great gem, really useful.
Any reason why you choosed to don't implement a quick access method updated_at / updated_on to return object.versions.at(version_number).created_at ?
I feel that manually calling object.versions.at(version_number).created_at is pretty over complicate comparing a natural call to object.updated_at / updated_on as follow:
object.updated_at
object.revert_to(version_number)
object.updated_at
Sébastien Grosjean - ZenCocoon
Hello,
I have installed vestal_versions and followed the instructions, the versioning works fine, however when i try to use updated_by such as:
@post.update_attributes(params[:post].merge(:updated_by => User.first))
i get the error/warning "Can't mass-assign these protected attributes: updated_by"
doing a @post.versions.last.user comes back nil as well.
is this a bug or iam missing something?
I am using composed of as below:
composed_of :html,
:class_name => 'HtmlWrapper',
:mapping => ['body', 'html'],
:converter => Proc.new { |str| HtmlWrapper.new(str) }
Reverting a previous version works great for the other fields,
but the fields using composed of simply return the newest value.
Strangely the version changes are saved correctly.
So I suspect this must have something to do with
the accessor method.
Hi,
is there a way with vestal versions to show a nice compare-view or change-view of 2 versions?
I am looking for a wikipedia-style compare-view with highlighting…
This is probably not part of the vestal versions-scope – do you know any good rails plugin for this?
Thanks
Tobias
I notice that the versions table created by the generator includes both a created_at and an updated_at column for the versions. Given that the versions are read only as I understand it, this seems redundant, and maybe only one or the other should be kept?
In general, it would be nice if it were documented whether any columns we don't feel like we'll need, such as user_name, can just be deleted from the migration.
Also, it seems like it would be better if VestalVersions would keep a version 1, so that we could have the timestamps for when the initial item was created without having to add a column that will only be used once to the tracked models.
What about creating a simple script that would add the necessary migration file.
Hi,
Great plugin. I really like the flexibility. Is there any thought to having support for deleted versions as well? (Similar to PaperTrail).
We are going ahead and using this plugin for our versioning and deletion tracking in our site however we are migrating off of ActsAsParanoid and would like to keep similar functionality. I've quickly added an initial pass at deletion tracking and restore here:
http://github.com/adamcooper/vestal_versions
I added a new :dependent option called :tracking which if set will start tracking deletions. It does this by creating a new version on destroy with a complete set of attributes. Ie. not the current diff approach. On a restore, the last version is deleted.
I'm just wondering what the likely hood of something like this getting merged upstream.
Thanks,
Adam
First of all, I love the simplicity and DRY of this plugin, fantastic work!
Most of my models, and specifically the ones I would like to track have associated models.
For instance, a client record has an avatar attachment (paperclip),
Many phone numbers, and many email addresses.
I was thinking that we could possibly store the attributes for these associations in the version database and then use a build command to show them, without creating them while iterating through versions.
Paperclip attachments are harder, as if they get destroyed, the files are gone, even if you DO track the file names.
Anyway, I would be happy to collaborate with you on this feature, as I think it is invaluable to true versioning. If you don't already have something like this in the works.
Thanks!
Dustin
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.