开发者

Help with HABTM :through

My current HABTM implementation works so far with :has_and_belongs_to_many. Notification and Privacy both inherit from Preference. Preference is an STI. I want to try using :has_many, :through association instead.

Model files

class User < ActiveRecord::Base
  has_and_belongs_to_many :preferences
end

class Preference < ActiveRecord::Base
  has_and_belongs_to_many :users
end

class Notification < Preference
end

class Privacy < Preference
end

Migration files

class UsersHaveAndBelongToManyPreferences < ActiveRecord::Migration
  def self.up
    create_table :preferences_users, :id => false do |t|
      t.references :preference, :user

      t.timestamps
    end
  end

  def self.down
    drop_table :preferences_users
  end
end

class CreatePreferences < ActiveRecord::Migration
  de开发者_运维问答f self.up
    create_table :preferences do |t|
      t.string :title
      t.text :description
      t.string :type

      t.timestamps
    end
  end

  def self.down
    drop_table :preferences
  end
end

class DeviseCreateUsers < ActiveRecord::Migration
  def self.up
    create_table(:users) do |t|
      t.string :name
      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end

I tried the following

class User < ActiveRecord::Base
  has_many :preferences, :through => :preferences_users
end

class Preference < ActiveRecord::Base
  has_many :users, :through => :preferences_users
end

My form looks like

  <% Preference.where(:type => 'Notification').all.each do |notification| %>
    <li>
      <%= check_box_tag 'user[preference_ids][]', notification.id, @user.preference_ids.blank? ? false : @user.preferences.include?(notification) %>
      <%= label_tag notification.description %>
    </li>
  <% end %>

I get

Could not find the association :preferences_users in model User

What am I doing wrong? Is the problem in my form or in my association?


Ok got it to work. I needed a model PreferencesUser, and was missing has_many :preferences_users on the user and preference models:

class PreferencesUser < ActiveRecord::Base
    belongs_to :user
    belongs_to :preference
end

class User < ActiveRecord::Base
  has_many :preferences_users
  has_many :preferences, :through => :preferences_users
end

class Preference < ActiveRecord::Base
  has_many :preferences_users
  has_many :users, :through => :preferences_users
end

Did not have to change anything in my form. Hope this helps someone


HABTM association is made to create a N to N relationship, which you did well but was not that useful. The has_many association is made to create a 1-N relationship and is a good choice.

You'd have to:

  • add has_many :preferences in your User model (just like you did)
  • add belongs_to :user in your Preference model
  • add user_id to your preference tables

Generally we use the :through to link objects which are not directly linked such as Users connected to Articles because they posted a Comment on some articles.

Another useful usage is for a conditional N-N relationship, 'friendship' class for instance:

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => "User"
end

class User < ActiveRecord::Base
  has_many :friends, :through => :friendships, :conditions => "status = 'accepted'"
  has_many :requested_friends, :through => :friendships, :source => :friend, :conditions => "status = 'requested'", :order => :created_at
  has_many :pending_friends, :through => :friendships, :source => :friend, :conditions => "status = 'pending'", :order => :created_at
end 

To stick to your needs, you could do the following:

#in you User model
has_many :notifications, :source => :preferences
has_many :privacies, :source => :preferences

#in your Preference model
belongs_to :user
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜