Alfred
Alfred

Reputation: 7091

How to update a join model with a has_many :through association?

I have a question regarding many-to-many relationships, specifically has_many :through associations.

All the tutorials I found just set you up with the models and migrations but leave you hanging when it comes to controllers.

What I want to do is to update the timestamps of the join table when an article that is already present is added again, so that it moves to the top of the "list". How do I do that?

This is what my create action looks like:

def create
  @article = Article.find_or_create_by_url(params[:article])
  if current_user.articles.find(@article)

      # update the timestamps on the join table 
      # ie moved the old article to the top

      flash[:notice] = "Successfully added article (again)."
      redirect_to @article
  else
    @article.users << current_user
    if @article.save
      flash[:notice] = "Successfully added article."
      redirect_to @article
    else
      render :action => 'new'
    end
  end
end

Thanks in advance!

Update:

@Ben Lee

Thanks for your answer, as I have a has_many through association my article model looks like this:

has_many :readinglist_items, :dependent => :destroy
has_many :users, :through => :readinglist_items

So I don't know if I can add a :touch => true to has_many as I just want to specific entry in the join table.

The point of the update in the create action is to move the article to the top (instead of adding it again) if a user adds an article it have already added in the past.

Upvotes: 2

Views: 2645

Answers (2)

Alfred
Alfred

Reputation: 7091

I solved it! (readinglist_item is the name of the join table):

def create
  @article = Article.find_or_create_by_url(params[:article])
  if current_user.articles.find(@article)

      @article.readinglist_items.find_by_user_id(current_user.id).touch

      flash[:notice] = "Successfully added article (again)."
      redirect_to @article
  else
    @article.users << current_user
    if @article.save
      flash[:notice] = "Successfully added article."
      redirect_to @article
    else
      render :action => 'new'
    end
  end
end

Upvotes: 1

Ben Lee
Ben Lee

Reputation: 53349

If I'm understanding you correctly, this isn't a controller issue, but a model issue. You can specify :touch => true on a belongs_to relationship. This will make it so that whenever the child is updated, the association's update_at is updated well.

So put something like this in your Article model:

belongs_to :whatever, :touch => true

Also, tangentially related: it's not clear from the code exactly what your code is doing, but it seems like maybe you are putting create and update functionality both in in the create method instead of splitting them up appropriately.

Upvotes: 3

Related Questions