4

I have a database that contains users and groups with a has_and_belongs_to_many relationship. When a new group is added, it gets created but the user's membership to the group doesn't seem to propagate until I clear the cache or login with an incognito window. I know it's getting saved correctly, it just doesn't seem to be loading until the cache is cleared. This only recently started happening and I can't figure out why! Any help would be greatly appreciated.

From the models:

class User < ActiveRecord::Base
    has_many :services
    has_many :recipes
    has_and_belongs_to_many :groups
    attr_accessible :recipes, :groups
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
  has_many :recipes
  attr_accessible :description, :title, :recipe, :picture, :featured, :user_id
end

The create group method:

def create
    @user = User.find(current_user.id)
    @group = Group.new(params[:group])
    @group.user_id = @user.id   
    @user.groups << @group

    redirect_to group_path(@group)
  end

Displaying the group memberships of a user -- this won't update until the cache is cleared:

<% @user.groups.each do |group| %>
<% if group %>
    <p class="group-title"><a href="<%=  group_path(group) %>"><%= group.title %></p>
        <% @latestpic = Recipe.where("group_id = ?", group).limit(1).order("created_at DESC") %>
        <% if @latestpic.exists? %>
            <% @latestpic.each do |pic| %>
                <%= image_tag(pic.picture.url(:medium)) %>  
            <% end %></a>
        <% else %>
            <%= image_tag "http://placehold.it/300x300" %>
        <% end %>
        <br></br>

<% end %>
<% end %>
Kim
  • 161
  • 7
  • @AdamEberlin -- I'm a rails noob. How would I check? – Kim Sep 29 '12 at 18:10
  • Are you using the RAILS standalone server or another service to serve your RAILS application? And what operating system? – Adam Eberlin Sep 29 '12 at 18:31
  • @AdamEberlin - I'm using Thin web server (v1.4.1 codename Chromeo). I'm on Mac OS. This issue is happening locally and when hosted on Heroku. – Kim Sep 29 '12 at 18:35

3 Answers3

0

In your models you have a "has and belongs to many" relationship, which means your users can be in n groups and your groups contains n users.

@group.user_id

If you have created a user_id column in your "groups" table, you can drop it, because a group contains n users. You have to use a table between users and groups like this :

create_table :group_users, :id => false do |t|
  t.references :group, :null => false
  t.references :user, :null => false
end

Then refactor your controller as I did below :

def create
  @group = current_user.groups.build(params[:group])

  if @group.save
    redirect_to @group, notice: 'Group was successfully created.'
  else
    render action: "new"
  end
end

This will create a group with your current user in it. In your method, you forgot to save your modifications. Because the operator = and << does not update the database. Then I refactored a little bit, but it is the same logic.

You can also refactor a lot of things in your view, but it's not the question, we'll leave it as is.

Does it work now?

basgys
  • 4,320
  • 28
  • 39
0

May be this answer is outdated, but might be useful for googlers who ends-up here:

When Rails(4.2 for me) updates Has-And-Belongs-To-Many association, it does not change an updated_at value for the root record. Example:

# This does not change @user.updated_at value 
@user.update_attributes(group_ids: [1, 2, 3])

Every ActiveRecord objects has a special cache_key that usually built using value of updated_at and invalidation of cache is based on that. So, if we change only HABT it does not invalidates cache.

Possible solution here - manually call @user.touch if HABTM was changed.

Semjon
  • 983
  • 6
  • 17
0

If someone came here because data won't show after create or delete, here is what you need to do to update the cache after those actions:

  # in your model file
  after_save    :expire_model_all_cache
  after_destroy :expire_model_all_cache

  def expire_model_all_cache
    Rails.cache.delete("your cache name")
  end
tronerta
  • 432
  • 6
  • 12