1
votes

I have a model named Tweet. The columns of the Tweet model are:

-id  
-content  
-user_id  
-picture  
-group  
-original_tweet_id    

Every tweet can have one or multiple retweets. The relation happens with the help of original_tweet_id. All the tweets have original_tweet_id nil , whilst the retweets contain the id of the Tweet.
When a tweet is deleted the retweets have to be deleted also. I try to do this in the following function:

   def destroy_retweets(tweet)
    retweets = Tweet.where(original_tweet_id: @tweet.id)
    if retweets.any?
      retweets.each do |retweet|
        destroy_retweets(retweet)
        retweet.destroy
      end
    end
  end

If I don't add the line "destroy_retweets(retweet)" then it's all ok and it deletes the retweets of the tweet. The problem is when I have retweets of retweets that's why I have to add that line(so I delete the retweets of all the retweets and so on). Since this doesn't work any ideas how I can make it work or an alternative (except not allowing users to retweet a retweet).

As suggested this is the tweet.rb model:

class Tweet < ActiveRecord::Base
  belongs_to :user
  has_many :hashrelations, dependent: :destroy
  has_many :hashtags, through: :hashrelations
  default_scope -> { order(created_at: :desc) }
  mount_uploader :picture, PictureUploader
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }
  validate  :picture_size


  private

    # Validates the size of an uploaded picture.
    def picture_size
      if picture.size > 5.megabytes
        errors.add(:picture, "o poza nu poate sa aiba o marime mai mare de 5MB")
      end
    end

end

This is the method that first calls destroy_retweets:

  def destroy
    destroy_retweets(@tweet)
    @tweet.destroy
    redirect_to request.referrer || root_url
  end
2
Why use an instance variable? That's going to hose things up since each method call will be overwriting @retweets. It may not be the root cause, but it strikes me as suspicious. - Dave Newton
I changed @retweets to retweets and I still get the stack level too deep :P - Lucian Tarna
I solved the problem I wrote @tweet.id instead of tweet.id in the where clause my god silly me. This was a good question anyway that you very much Dave Newton and Avdept :) I learnt something from you both - Lucian Tarna
@DaveNewton mind posting the answer so I can check it ? :) This question is solved , other questions might need more attention from people. - Lucian Tarna
You can answer your own question and accept it; my comment didn't really help :) - Dave Newton

2 Answers

2
votes

If you express the relation properly, ActiveRecord will do it for you

class Tweet
  belongs_to :original_tweet, class_name: Tweet
  has_many :retweets, class_name: Tweet, dependent: :destroy, inverse_of :original_tweet

end

Tweet.last.destroy  # will now destroy dependents
1
votes

Even if collection emtpy, it returns true anyway. Instead of if @retweets, use if @retrweets.any?

Why? Because where query returns ActiveRecord::Relation object, and you checking if object present, not if any records present.