0

Below is my create function for my reviews controller. Basically the issue I have is that if a venue is left blank, and the artist isn't, an artist object is still created and a concert object is not. How do I prevent the artist from being created if the concert fails to create? If this isn't possible, how do I delete the artist immediately after the concert fails to create?

def create

    date_string = "#{review_params['date(1i)']}-#{review_params['date(2i)']}-#{review_params['date(3i)']}"
    artist_string = review_params[:artist].titleize
    venue_string = review_params[:venue].titleize

    @concert = Concert.find_or_create_by!(artist: Artist.find_or_create_by!(name: artist_string), venue: venue_string, date: date_string)
    @review = @concert.reviews.create(review_params)
    @review.user_id = session[:user_id]

end

artist has_many :concerts

concerts belongs_to artist

concert has_many reviews

I need to force an artist to have at least 1 concert.

tshepang
  • 12,111
  • 21
  • 91
  • 136
parameter
  • 894
  • 2
  • 18
  • 35

3 Answers3

2

I think KNaito means that you can wrap your code for creating records within a transaction. If any ActiveRecord operation within the transaction fails all changes will be rollbacked. Example:

transaction do
  <ActiveRecord operations>
end

P.s. This should be done in a method within a model. You can call this method from your controller action.

rails4guides.com
  • 1,441
  • 2
  • 11
  • 8
  • this is in my controller and I get the error undefined method `transaction' for Reviews controller if I try this – parameter Apr 23 '14 at 05:54
  • This is because a transaction is used within the model. So you should move the code to a model to make it work. Anyway, your approach is also fine, although it could use a bit of refactoring. – rails4guides.com Apr 23 '14 at 06:06
0

So I ended up doing this to fix the problem. if anyone has a cleaner or smarter way of doing it please let me know.

def create

date_string = "#{review_params['date(1i)']}-#{review_params['date(2i)']}-#{review_params['date(3i)']}"

artist_string = review_params[:artist].titleize
venue_string = review_params[:venue].titleize

@review = Review.create(review_params)

if @review.save
  @artist = Artist.find_or_create_by(name: artist_string)
  @concert = Concert.find_or_create_by(artist: @artist, venue: venue_string, date: date_string)
  @review.concert_id = @concert.id
  @review.user_id = session[:user_id]
  @review.save
end
parameter
  • 894
  • 2
  • 18
  • 35
0

My answer is same as rails4guides.com's. The codes is following.

def create
    date_string = "#{review_params['date(1i)']}-#{review_params['date(2i)']}-#{review_params['date(3i)']}"
    artist_string = review_params[:artist].titleize
    venue_string = review_params[:venue].titleize

    ActiveRecord::Base.transaction do
        @concert = Concert.find_or_create_by!(artist: Artist.find_or_create_by!(name: artist_string), venue: venue_string, date: date_string)
        raise "no concert" unless @concert
        @review = @concert.reviews.create(review_params)
        @review.user_id = session[:user_id]
    end

    rescue => e

    # rollback

end
KNaito
  • 3,930
  • 2
  • 19
  • 21