1

I have an object called a tag which has_many :tweets. The tweet also has a corresponding belongs_to.

If I'm generating a tweet to save in the tag model like so:

        new_tweet = Tweet.new

        new_tweet.favorite_count = tweet.favorite_count 
        new_tweet.filter_level = tweet.filter_level 
        new_tweet.retweet_count = tweet.retweet_count 
        new_tweet.text = tweet.text 
        new_tweet.tweeted_at = tweet.created_at 

        new_tweet.created_at = DateTime.strptime tweet.created_at.to_s, '%Y-%m-%d %H:%M:%S %z' 

        new_tweet.save 

How do I set that tweets parent to be the current tag? Would I do something like this?

new_tweet.tag = self

I tried this and it didn't work, whats a better solution? Thanks for your help.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
NNNNNNNNNNDelicious
  • 933
  • 3
  • 7
  • 19

3 Answers3

1

Try create tweet's new object with association and tag_id will automatically assign in your new tweet object. So change Tweet.new to self.tweets.new and you are done.

new_tweet = self.tweets.new

new_tweet.favorite_count = tweet.favorite_count 
new_tweet.filter_level = tweet.filter_level 
new_tweet.retweet_count = tweet.retweet_count 
new_tweet.text = tweet.text 
new_tweet.tweeted_at = tweet.created_at 

new_tweet.created_at = DateTime.strptime tweet.created_at.to_s, '%Y-%m-%d %H:%M:%S %z' 

new_tweet.save 

As per your comment. You also have database structure issue. You need to resolve that first. You don't have tag_id in your tweets table assuming you take tag name column. To make my code work properly and create a proper parent child relation you must have parent_id in your child table.

So try add tag_id in your tweets table and your error will gone. Also your value will save properly.

Dipak Gupta
  • 7,321
  • 1
  • 20
  • 32
0

I'd say you have two solutions :

1) As suggested by pavan, assign the tag_id of the original tweet to the new tag. This will create the association between new_tweet and the tag :

new_tweet.tag_id = tweet.tag_id

2) Or, if you do create the new_tweet in a tag instance method, you can directly create the tweet through the association as suggested by Dipak :

new_tweet = self.tweets.build
LapinLove404
  • 1,939
  • 1
  • 21
  • 26
  • The first way gives me an error. The second way gives me this error (I originally tried it as `new_tweet.tag = self` but it should be the same as you got on suggestion one, both give me: `ActiveModel::MissingAttributeError: can't write unknown attribute `tag_id``. Way number 2 gives me the same error as I mentioned in a comment below: `ActiveRecord::UnknownAttributeError: unknown attribute 'tag_id' for Tweet` so maybe I have a deeper problem here? – NNNNNNNNNNDelicious Sep 24 '15 at 03:39
  • Do you have a "tag_id" column in your database for the `Tweet` model ? – LapinLove404 Sep 24 '15 at 10:33
0

I think there's a better way to do it.

If you're saving a tag object, why not just use an after_create hook to make another tweet? You're basically copying all the data over anyway...

For example:

#app/models/tag.rb
class Tag < ActiveRecord::Base
    has_many :tweets
    attr_accessor :parent
    #This will allow you to save a tag with attribute "parent" as true. If true, the tweet model will create another tweet. It will need tweaking
end

#app/models/tweet.rb
class Tweet < ActiveRecord::Base
   belongs_to :tag
   after_create :new_tweet, if: Proc.new { |tweet| tweet.tag.parent }

   def new_tweet
      new = self.clone
      new.tweeted_at = self.created_at
      new.created_at = DateTime.strptime self.created_at.to_s, '%Y-%m-%d %H:%M:%S %z' 
      new.save
   end
end

You can read more about Rails' clone method here.

--

Relational

Rails is actually very good with handling relational data.

Pavan in the comments is almost spot-on with his recommendation of using tag_id. This, of course, will load a database attribute, but there's a better way.

As can be seen here, there are a number of methods added with a has_many/belongs_to relationship:

enter image description here

enter image description here

This means you'll be able to use the following:

  • tweet.tag to retrieve the tag object.

  • If tweet had many tag, you'd be able to use the tweet.tag or tweet.tag_id

All of this means you can pass an object to your new_tweet.tag attribute...

Thus, your answer:

new_tweet.tag = tweet.tag
Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147