<commit_before>= DirtyAssociations

A Rails plugin in the early stages of development to add basic change-tracking facility to ActiveRecord associations.

<b>*** GOTCHA:</b> Sorry, DirtyAssociations require edge rails (currently 2.3.0), because it makes use of +default_scope+. I didn't want to reinvent the wheel. +has_dirty_associations+ uses the :+include+ option to preload all of the associations that it's watching. I'd image bad things happen if you try to override this.

	# installing edge rails
	$ rake rails:freeze:edge

== Usage

	# In the model:

	class Gallery < ActiveRecord::Base
		belongs_to :user
		has_many :photos
		has_many :comments
		has_and_belongs_to_many :subscribers
	
		has_dirty_associations :photos, :comments
	
		#...	
	end

=== Class Methods

Setting up:

	Gallery.has_dirty_associations :photos, :comments
	Gallery.watched_associations 
		# => [:photos, :comments]

	Gallery.has_dirty_associations
	Gallery.watched_associations 
		# => [:user, :photos, :comments, :subscribers]
	
	Gallery.has_dirty_associations :all
	Gallery.watched_associations 
		# => [:user, :photos, :comments, :subscribers]

	Gallery.has_dirty_associations :children
	Gallery.watched_associations 
		# => [:comments, :photos, :subscribers]
	
	Gallery.has_dirty_associations :parents
	Gallery.watched_associations 
		# => [:user]

	# Singular versions are available
	Gallery.has_dirty_association :user
	Gallery.watched_association
		# => [:user]

=== Instance Methods

Shows some basic interaction:

	gallery = Gallery.first

	gallery.new_photos? 
		# => false

	gallery.photos.build

	gallery.new_photos? 
		# => true

	gallery.new_photos 
		# => [#<Photo:0x20da67c>]
	
	gallery.comments.first.destroy

	gallery.deleted_comments?
		# => true
	
	gallery.deleted_comments 
		# => [#<Comment:0x20da21b>]

=== Individual Records

You can also find out more about the actual changes:

	gallery.photos.first.inspect
		# => #<Photo id: 4, title: "A boring photo", gallery_id: 1, created_at: "2008-11-29 18:52:47", updated_at: "2008-12-07 20:01:25">
	
	gallery.photos.first.title = "A lovely photo"

	# Also available, without the +any_+ prefix: +gallery.user_changed?+
	gallery.any_photos_changed?
		# => true
	
	gallery.photos_changed
		# => {4 => ["title"]}

	gallery.photos_changes
		# => {4 => { "title" => ["A boring photo", "A lovely photo"] }}

=== Changes for all watched_associations

The #comprehensive_changes method provides structured change data for the record in question as well as all watched associated records.

	gallery.title = "Some other gallery title"
	
	gallery.comments.first.id
	  # => 12
	
	gallery.comments.first.body = "Not such a great set..."
	
	gallery.comprehensive_changes
		# => { :self => { :title => ["Some original title", "Some other gallery title"] },
		 		 	 :associated => { :comments => { 12 => { :body => ["Pretty awful.", "Not such a great set..."] }}} }

=== Caching Changes

I'm not really sure why you'd want to do this, but it might come in handy.

Setup:

	gallery.photos.first.title
		# => 'Some original title'
	
	gallery.photos.first.title = 'A changed title'

Without caching:

	gallery.edited_photos?
		# => true
	
	gallery.save

	gallery.edited_photos?
		# => false

So once you've saved a record, you loose any trace of the changes made...	
With caching:

	gallery.cache_photos!

	gallery.save

	gallery.photos.first.title
		# => 'A changed title'
	
	gallery.photos_from_cache.first.title
		# => 'Some original title'
		
	gallery.clear_cache!
	
	gallery.photos_from_cache
		# => nil
		
Additionally, you can cache all associations at once, and read back all together:

	gallery.description = 'Photos taken on holiday'
	
	gallery.cache_associated!
	
	gallery.comments.destroy_all
	
	gallery.photos.count
		# => 2
	
	gallery.photos.build(:url => 'some_url')
	
	gallery.photos.count
		# => 3
	
	gallery.save
	
	gallery.associations_from_cache
		# => { :photos => [#<Photo:0x10ae23a>, #<Photo:0x14af61c>], 
					 :comments => [#<Comment:0x20da21b>],
					 :user => #<User:0x21fc11a>,
					 :subscribers => [] }
					
	gallery.photos_from_cache.length
		# => 2
	
=== Disclaimer

This is about as rough and raw as it comes, and is my first go at making a plugin, so be kind!

Copyright (c) 2008 <NAME>, released under the MIT license<commit_msg>Format README<commit_after>= DirtyAssociations

A Rails plugin in the early stages of development to add basic change-tracking facility to ActiveRecord associations.

<b>*** GOTCHA:</b> Sorry, DirtyAssociations require edge rails (currently 2.3.0), because it makes use of +default_scope+. I didn't want to reinvent the wheel. +has_dirty_associations+ uses the :+include+ option to preload all of the associations that it's watching. I'd image bad things happen if you try to override this.

  # installing edge rails
  $ rake rails:freeze:edge

== Usage

  # In the model:

  class Gallery < ActiveRecord::Base
    belongs_to :user
    has_many :photos
    has_many :comments
    has_and_belongs_to_many :subscribers
  
    has_dirty_associations :photos, :comments
  
    #...  
  end

=== Class Methods

Setting up:

  Gallery.has_dirty_associations :photos, :comments
  Gallery.watched_associations 
    # => [:photos, :comments]

  Gallery.has_dirty_associations
  Gallery.watched_associations 
    # => [:user, :photos, :comments, :subscribers]
  
  Gallery.has_dirty_associations :all
  Gallery.watched_associations 
    # => [:user, :photos, :comments, :subscribers]

  Gallery.has_dirty_associations :children
  Gallery.watched_associations 
    # => [:comments, :photos, :subscribers]
  
  Gallery.has_dirty_associations :parents
  Gallery.watched_associations 
    # => [:user]

  # Singular versions are available
  Gallery.has_dirty_association :user
  Gallery.watched_association
    # => [:user]

=== Instance Methods

Shows some basic interaction:

  gallery = Gallery.first

  gallery.new_photos? 
    # => false

  gallery.photos.build

  gallery.new_photos? 
    # => true

  gallery.new_photos 
    # => [#<Photo:0x20da67c>]
  
  gallery.comments.first.destroy

  gallery.deleted_comments?
    # => true
  
  gallery.deleted_comments 
    # => [#<Comment:0x20da21b>]

=== Individual Records

You can also find out more about the actual changes:

  gallery.photos.first.inspect
    # => #<Photo id: 4, title: "A boring photo", gallery_id: 1, created_at: "2008-11-29 18:52:47", updated_at: "2008-12-07 20:01:25">
  
  gallery.photos.first.title = "A lovely photo"

  # Also available, without the +any_+ prefix: +gallery.user_changed?+
  gallery.any_photos_changed?
    # => true
  
  gallery.photos_changed
    # => {4 => ["title"]}

  gallery.photos_changes
    # => {4 => { "title" => ["A boring photo", "A lovely photo"] }}

=== Changes for all watched_associations

The #comprehensive_changes method provides structured change data for the record in question as well as all watched associated records.

  gallery.title = "Some other gallery title"
  
  gallery.comments.first.id
    # => 12
  
  gallery.comments.first.body = "Not such a great set..."
  
  gallery.comprehensive_changes
    # => { :self => { :title => ["Some original title", "Some other gallery title"] },
           :associated => { :comments => { 12 => { :body => ["Pretty awful.", "Not such a great set..."] }}} }

=== Caching Changes

I'm not really sure why you'd want to do this, but it might come in handy.

Setup:

  gallery.photos.first.title
    # => 'Some original title'
  
  gallery.photos.first.title = 'A changed title'

Without caching:

  gallery.edited_photos?
    # => true
  
  gallery.save

  gallery.edited_photos?
    # => false

So once you've saved a record, you loose any trace of the changes made... 
With caching:

  gallery.cache_photos!

  gallery.save

  gallery.photos.first.title
    # => 'A changed title'
  
  gallery.photos_from_cache.first.title
    # => 'Some original title'
    
  gallery.clear_cache!
  
  gallery.photos_from_cache
    # => nil
    
Additionally, you can cache all associations at once, and read back all together:

  gallery.description = 'Photos taken on holiday'
  
  gallery.cache_associated!
  
  gallery.comments.destroy_all
  
  gallery.photos.count
    # => 2
  
  gallery.photos.build(:url => 'some_url')
  
  gallery.photos.count
    # => 3
  
  gallery.save
  
  gallery.associations_from_cache
    # => { :photos => [#<Photo:0x10ae23a>, #<Photo:0x14af61c>], 
           :comments => [#<Comment:0x20da21b>],
           :user => #<User:0x21fc11a>,
           :subscribers => [] }
          
  gallery.photos_from_cache.length
    # => 2
  
=== Disclaimer

This is about as rough and raw as it comes, and is my first go at making a plugin, so be kind!

Copyright (c) 2008 <NAME>, released under the MIT license
{'fraction_non_alphanumeric': 0.11410314924691921, 'fraction_numerical': 0.01734367868553172, 'mean_word_length': 3.6424788135593222, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '165947', 'n_tokens_mistral': 3152, 'n_tokens_neox': 2741, 'n_words': 788}