Ossie
Ossie

Reputation: 1113

Trouble writing action

UPDATE

I have an action in my Miniatures model called set_gold_and_silver.

I want my Users model to run it when a User is destroyed, so I have before_destroy :set_gold_and_silver in my User model.

A User has many Imagevotes. Before destroy I need to delete those Imagevotes and then run set_gold_and_silver on all the Miniatures that those imagevotes pertained to.

This is what I've got so far and I'm currently getting undefined method 'miniatures'.

It's not clear to me whether I am caching self.imagevotes or whether they are just deleted and then I get the error because they no longer exist?

def set_gold_and_silver
   votes = self.imagevotes
   self.imagevotes.destroy
   votes.miniatures.uniq.each(&:set_gold_and_silver)
end

My models

User

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable
  has_many :collections, dependent: :destroy
  has_many :miniatures, through: :collections

  has_many :imagevotes, foreign_key: "voted_id", dependent: :destroy
  has_many :imagevotes, foreign_key: "voter_id", dependent: :destroy
  before_destroy :set_gold_and_silver

  def set_gold_and_silver
    my_collections = self.collections.each
    their_miniatures = collection.miniature.uniq
    my_collections.their_miniatures.each(&:set_gold_and_silver)
  end


end

Miniature

class Miniature < ActiveRecord::Base
  has_many :collections, dependent: :destroy
  has_many :users, :through => :collections
  has_many :imagevotes, dependent: :destroy

  def set_gold_and_silver
    wipe = self.collections.all
    wipe.each {|s| s.update_attributes :is_gold => false, :is_silver => false}
    top_collections = self.collections.limit(4)
    gold = top_collections.shift 
    gold.update_attribute :is_gold, true if gold
    top_collections.each {|s| s.update_attribute :is_silver, true}
  end
end

Collection

class Collection < ActiveRecord::Base
  default_scope order('imagevotes_count DESC')
  belongs_to :miniature
  belongs_to :user
  has_many :imagevotes, dependent: :destroy

end

Imagevote

class Imagevote < ActiveRecord::Base
    belongs_to :collection, :counter_cache => true
    belongs_to :voter, class_name: "User", :counter_cache => "voted_count"
    belongs_to :voted, class_name: "User", :counter_cache => "vote_count"
    belongs_to :miniature

    after_create :set_gold_and_silver
    after_update :set_gold_and_silver

    def set_gold_and_silver
        self.miniature.set_gold_and_silver
    end

end

Upvotes: 0

Views: 26

Answers (1)

Sergey Moiseev
Sergey Moiseev

Reputation: 2963

You need to make your code simpler:

class Miniature < ActiveRecord::Base
  def set_gold_and_silver
    self.collections.update_all("is_gold = false, is_silver = false")
    top_collections = self.collections.limit(4)
    gold = top_collections.shift 
    gold.update_attribute :is_gold, true if gold
    top_collections.each {|s| s.update_attribute :is_silver, true}
  end
end

class User < ActiveRecord::Base
  def set_gold_and_silver
    self.miniatures.uniq.each(&:set_gold_and_silver)
  end
end

you have has_many :miniatures, through: :collections so you don't need to work with collections to get minuatures.

And for now your code not working because everything still there before destroy. It need to be done after, when everything depended to user removed. And also as it seems for me you need to remove imagevotes in user destroy and set_gold_and_silver only after that. For now it's not done, so gold and silver stays.

Upvotes: 1

Related Questions