为什么我的多对多通关会失败?

时间:2012-01-05 20:28:07

标签: ruby-on-rails ruby-on-rails-3 model-associations

我已经设置了类似Twitter的跟随模型。用户都可以互相订阅。在尝试创建关系时,我在用户控制器中收到错误。

user.rb:

has_many :subscriptions
has_many :providers, :through => :subscriptions

has_many :followings, :class_name => "Subscription"
has_many :followers, :through => :followings

subscription.rb

belongs_to :provider, :class_name => 'User', :foreign_key => "provider_id"
belongs_to :follower, :class_name => 'User', :foreign_key => "follower_id"

users_controller.rb

69 def follow
70   logger.debug params.to_yaml
71   @user = User.find(params["user_id"])
72   logger.debug @user.to_yaml
73   if current_user.providers << @user
74     flash[:notice] = "Subscribed"
75   else
76     flash[:error] = "Unable to subscribe."
77   end
78 end

当我致电以下时,这是错误:

ActiveRecord::UnknownAttributeError (unknown attribute: user_id):
  app/controllers/users_controller.rb:73:in `follow'

我已经验证我运行了rake db:migrate - 订阅表有两个字段provider_id和follower_id。任何人都可以帮我解决错误并解释为什么它正在寻找'user_id'属性吗?

更新

show.html.erb:

<%= button_to "Subscribe", user_follow_path(@user), :remote => true %>

routes.rb中:

resources :users do
  resources :locations
  resources :saved_events
  resources :saved_locations
  post "follow"
end

rake routes | grep跟随:

user_follow POST     /users/:user_id/follow(.:format)                    {:action=>"follow", :controller=>"users"}

2 个答案:

答案 0 :(得分:1)

使用Michael Hartl's tutorial作为指导,我提出了这个解决方案,它修复了数据模型,使收集功能正常工作。

使提供者ID可访问并删除订阅模型中的外键。

subscription.rb:

attr_accessible :provider_id
belongs_to :provider, :class_name => 'User'
belongs_to :follower, :class_name => 'User'

在用户模型中为订阅和reverse_subscriptions添加外键。

user.rb:

has_many :subscriptions, :foreign_key => "subscriber_id", :dependent => :destroy
has_many :subscribed_to, :through => :subscriptions, :source => :provider

has_many :reverse_subscriptions, :class_name => "Subscription", :foreign_key => "provider_id", :dependent => :destroy
has_many :followers, :through => :reverse_subscriptions

我还在用户模型中添加了辅助方法。

user.rb:

def following?(provider)
  subscriptions.find_by_provider_id(provider)
end

def follow!(provider)
  subscriptions.create!(:provider_id => provider.id)
end

def unfollow!(provider)
  subscriptions.find_by_provider_id(provider).destroy
end

然后,在控制器中,我们可以打电话跟随!或取消关注!

user_controller.rb:

...
current_user.unfollow!(@user)
...
current_user.follow!(@user)
...

答案 1 :(得分:0)

它给你一个错误的原因是因为当你在provider集合上调用<<时,用户不知道它应该是一个追随者。所以它基本上说,“我是一个用户,把我加入这个提供商集合!”而不是“这个人会跟着我,我现在是一个提供者,他是一个追随者”

最简单的答案可能就是

user.rb:

def follow(other_user)
  Subscription.create(:provider => other_user, :follower => self)
end

users_controller.rb

def follow
  @user = User.find(params["user_id"])
  if current_user.follow(@user)
    flash[:notice] = "Subscribed"
  else
    flash[:error] = "Unable to subscribe."
  end
end