Ruby on Rails ||以下会议

时间:2017-04-30 14:57:58

标签: ruby-on-rails ruby relationship

我试图在Ruby on Rails中创建一个应用程序,我可以:

  • 创建会议(工作)

  • 查看会议列表(工作)

  • 关注并取消关注会议(不工作)

  • 查看以下会议(不工作)

我在12月份开始使用Ruby on Rails并使用Micheal Hartl的教程开始。在第14章(https://www.railstutorial.org/book/following_users)中,迈克尔通过关系介绍了跟随和取消关注的用户。

我尝试应用他的技术,但将其调整到一个模型和一个控制器之间的关系,到两个模型和两个控制器的位置。

一个控制器& model是User_controller和User Model,另一个是控制器& model是Conference_controller和Conference Model。

我首先将活跃的关系添加到用户模型中,因为它是参加会议的一方

user.rb

  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  has_many :following, through: :active_relationships, source: :followed

我在会议模式中做了相反的事情,因为我关注的是被关注的一方

Conference.rb

has_many :passive_relationships, class_name:  "Relationship",
                                   foreign_key: "followed_id",
                                   dependent:   :destroy
  has_many :followers, through: :passive_relationships, source: :follower

为了清除结构,我已将以下代码行添加到关系模型

Relationship.rb

  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "Conference"
  validates :follower_id, presence: true
  validates :followed_id, presence: true

当试图查看用户是否实际关注会议时,用户模型中出现错误:

ActiveRecord::RecordNotUnique in RelationshipsController#create

SQLite3::ConstraintException: UNIQUE constraint failed: relationships.follower_id, relationships.followed_id: INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)

问题的根源在于:

app/models/user.rb:116:in `follow'
app/controllers/relationships_controller.rb:6:in `create'

我理解当无法插入记录时会出现问题,因为它会违反唯一性约束,但我不知道违反了什么唯一性约束。

现在第一个问题出现在 user.rb 中,当在用户和会议之间创建active_relationship时。

  # Returns true if the current user is following the other user.
  def following?(other_conference)
    following.include?(other_user)
  end

  # Follows a conference.
  def follow(other_conference)
    active_relationships.create(followed_id: other_conference.id)
  end

  # Unfollows a conference.
  def unfollow(other_conference)
    active_relationships.find_by(followed_id: other_conference.id).destroy
  end

第二个问题出在Relationships_controller中,current_user应该跟随会议。

def create
    @conference = Conference.find(params[:followed_id])
    current_user.follow(@conference)
    respond_to do |format|
      format.html { redirect_to @conference }
      format.js
    end
  end

现在我不确定问题的原因是什么以及如何解决。我希望我能清楚地解决问题以及我想要实现的目标。如果不是,我很乐意提供有关我的问题的更多信息。

1 个答案:

答案 0 :(得分:1)

您正在关注一个处理更复杂案例的示例(您将两次加入同一个表格)并且您的解决方案比它需要的更复杂:

class User
  has_many :subscriptions
  has_many :conferances, though: :subscriptions

  def subscribed_to?(conference)
    conferances.include?(conference)
  end

  def find_subscription(conference)
    subscriptions.find_by(conference: conference)
  end
end

class Conferance
  has_many :subscriptions
  has_many :users, though: :subscriptions
end

# Its better to name join models after an actual thing
class Subscription
  belongs_to :user
  belongs_to :conference
end
resources :conferences, shallow: true do
  resource :subscriptions, only: [:create, :destroy]
end
class SubscriptionsController
  before_action :set_conferance, only: :create

  def create
    if current_user.subsciptions.create(conferance: @conferance)
      flash[:success] = "You are now subscribed to { @conferance.name }"
    else
      flash[:error] = "Could not create subscription."
    end
    redirect_to @conferance
  end

  def destroy
    @subscription = current_user.subsciptions.find(params[:id])
    if @subscription.destroy
      flash[:success] = "You are no longer subscribed to { @conferance.name }"
    else
      flash[:error] = "Oh noes"
    end

    redirect_to @subscription.conferance 
  end

  def set_conferance
    @conferance = Conferance.find(params[:conferance_id])
  end
end
<% if current_user.subscribed_to?(@conferance) %>
  <%= button_to "Subscribe", conferance_subsciptions_path(@conferance), method: :post %>
<% else %>
  <%= button_to "Unsubscribe", subscription_path(current_user.find_subscription(@conferance)), method: :delete %>
<% end %>