AnnaSm
AnnaSm

Reputation: 2300

Rails, after a record is created, how to automatically create an associated record?

I have a Ratings model where a user can rate an object... After a rating takes place I want to then automatically create a RatingLog record so the user can see a list of all the ratings.

Models: Rating.rb and RatingLog.rb

I see RatingLog including a list of events other than just Ratings, like Badges etc... VERY similar to StackOverflow.

What is the right way with Rails 5, to populate RatingLog.rb after a Rating is created... Should I use after_create in Rating.rb? Should I create some other type of callback? Would love to hear what is the right way to implement the above in Rails 5.

Thank you

Upvotes: 0

Views: 866

Answers (3)

George
George

Reputation: 680

Another option is an after_commit callback which will only run when the Rating object is saved.

after_create will work too, but if you have an error when you try to save your RatingLog then the Rating record you created will also not save (checkout this answer).

So depending on the behavior you want, choose one:

  • after_commit RatingLog errors don't effect Rating saves
  • after_create RatingLog errors rollback Rating saves

Also:

  1. It's not totally clear from your post, but it sounds like Rating and RatingLog are holding very similar data?? or if RatingLog will hold logs of other events, maybe name it something else.
  2. Check out this answer on naming conventions -- the convention for model file naming is rating.rb and rating_log.rb

Upvotes: 0

Thanh
Thanh

Reputation: 8604

I assume that you have models:

class Rating
  has_one :rating_blogs
end

class RatingBlog
  belongs_to :rating
end

so, to create a rating blog afer rating is created, you can do:

@rating = Rating.new
@rating.build_rating_blog(some_message: 'Message')
@rating.save

So when @rating is created, a rating blog will be created and associated with @rating.

Upvotes: 1

David Weber
David Weber

Reputation: 479

I don't know if this is considered okay... But I do this right inside of the create action, in your case I'll guess: RatingController

def create
...
    @ratinglog = RatingLog.create
        @ratinglog.user = current_user
        @ratinglog.rating = @rating.id
        @ratinglog.comment_type = "server generated"
        @ratinglog.comment = "#{current_user.fname} #{current_user.lname} submitted a rating of #{@rating.content}"
        @ratinglog.save!
...
end

Upvotes: 0

Related Questions