在 Rails 中连接关联的按钮不起作用。所有权转让

Posted

技术标签:

【中文标题】在 Rails 中连接关联的按钮不起作用。所有权转让【英文标题】:Button to connect an association in Rails is not working. Transfer of ownership 【发布时间】:2021-11-02 01:58:26 【问题描述】:

我正在处理我的第一个 Rails 项目,一个采用应用程序,并试图将关联与 Rails 中的新潜在所有者联系起来。我的控制器操作正在通过我的收养请求方法进行,但没有任何更改被持久保存到我在 ActiveRecord 中的联接表中。有人可以告诉我我在这里缺少什么吗?

应用程序:

所有者注册或登录到他们的帐户。他们可以使用表格添加他们的雪貂。稍后,所有者可能想要创建一个机会列表来收养/重新安置他们的动物。浏览的人应该能够点击他们感兴趣的 Opportunity,这应该在连接表 Opportunity 中建立关联,:adopter_id。

我的模特:

class Owner < ApplicationRecord
  has_secure_password

  has_many :ferrets, dependent: :destroy
  has_many :opportunities, dependent: :destroy
  has_many :ferret_adoptions, through: :opportunities, source: :ferret
  accepts_nested_attributes_for :ferrets, :opportunities
end


class Ferret < ApplicationRecord
  belongs_to :owner
  has_many :opportunities
  has_many :owners, through: :opportunities
end


class Opportunity < ApplicationRecord
  belongs_to :ferret
  belongs_to :owner
end

在 Opportunities Controller 中,我的 admission_request 方法:

def adoption_request
  @owner = Owner.find(session[:owner_id])
  @opportunity = Opportunity.find(params[:id])
  @opportunity.adopter_id = [] << current_user.id
  current_user.req_id = [] << @opportunity.id
          
  flash[:message] = "Adoption request submitted."
  redirect_to questions_path
end

我正在使用一个按钮来执行此操作,但如果有更好的效果,我愿意更改它:

<button><%= link_to 'Adoption Request', adoption_request_path, method: :post %> <i class='fas fa-heart' style='color:crimson'></i></button>

作为所有者,当我单击按钮提出采用请求时,我看到了 byebug 中的所有工作部分,并且我被重定向到带有成功消息的下一页,好像一切正​​常,但没有关联实际上被持久化到数据库中。

感谢您提供的任何反馈。

【问题讨论】:

我认为您需要致电 save 才能使任何分配持续存在。 current_user.req_id = [] &lt;&lt; @opportunity.id这应该做什么? @opportunity.adopter_id = current_user.id。或@opportunity.adopter_id = ([] &lt;&lt; current_user.id)[0] 以获得最大的愚蠢。尽管[] &lt;&lt; 是一种非常奇怪的声明数组的方式,但很严肃。尤其是当您不需要数组时。 我希望将 owner.id 作为机会.adopter_id 保存在连接表中以完成关联。以下是可选的,不过最好将Owner记录中的opportunity.id保存为req_id作为请求的记录。 好的,我想我可能已经解决了这个问题。我确实在考虑数组,并读到铲子方法应该自动保存在 Rails 中。但我根本不需要这样做。我刚刚分配了它 = 新的关联显示在控制台中。 【参考方案1】:

我在这里假设 Opportunity 应该代表类似于列表的东西(它需要一个不那么模糊的名称)。

如果是这样,如果您希望多个用户能够响应机会,则您缺少模型及其表:

class Owner < ApplicationRecord
  has_secure_password
  has_many :ferrets, dependent: :destroy
  has_many :opportunities, dependent: :destroy
  has_many :adoption_requests_as_adopter,
    foreign_key: :adopter_id,
    class_name: 'AdoptionRequest'
  has_many :adoption_requests_as_owner,
    through: :opportunities,
    source: :adoption_requests
  accepts_nested_attributes_for :ferrets, :opportunities
end

class Ferret < ApplicationRecord
  belongs_to :owner
  has_many :opportunities
  has_many :owners, through: :opportunities
  has_many :adoption_requests, through: :opportunities
end

class Opportunity < ApplicationRecord
  belongs_to :ferret
  belongs_to :owner 
  has_many :adoption_requests
end

class AdoptionRequest < ApplicationRecord
  belongs_to :adopter, class_name: 'Owner' # ???
  belongs_to :opportunity
  has_one :ferret, through: :opportunity
  has_one :owner, through: :opportunity
end

如果您的opportunities 表中只有一个adopter_id,则它只能保存一个值。

我只是将路由/控制器设置为嵌套资源的普通 CRUD 控制器:

# routes.rb
resources :opportunities do
  resources :adoption_requests, only: [:create, :index]
end
<%= button_to "Adopt this ferret", opportunity_adoption_requests_path(@opportunity), method: :post %>
class AdoptionRequestsController < ApplicationController
  before_action :set_opportunity

  # @todo authorize so that it can only be viewed by the owner
  # GET /opportunities/1/adoption_requests
  def index
    @adoption_requests = @opportunity.adoption_requests
  end

  # @todo authorize so that a current owner can't create adoption_requests
  #   for their own ferrets
  # POST /opportunities/1/adoption_requests
  def create
    @adoption_request = @opportunity.adoption_requests.new(
      adopter: current_user
    )
    if @adoption_request.save
      redirect_to @opportunity, notice: 'Thank you for your reply! The owner of the ferret will be notified.'
      # @todo send notification to owner
    else
      redirect_to @opportunity, notice: 'Oh noes!'
    end
  end

  private

  def set_opportunity 
    @opportunity = Opportunity.find(params[:opportunity_id])
  end
end

只有在所有者实际接受收养请求时,您才会真正更新机会,这是以后的单独问题。

【讨论】:

在我工作的过程中,我意识到需要一个额外的表,但是这些关系很难让我理解。非常感谢您在这里的反馈。 如果您尝试将其视为域中的实际对象而不是连接表,并且在开始编写域之前使用记事本或 UML 工具勾勒出域,这会有所帮助代码。

以上是关于在 Rails 中连接关联的按钮不起作用。所有权转让的主要内容,如果未能解决你的问题,请参考以下文章

Rails 关联不起作用,user_id 未显示在控制台中

Rails 与自身的关联不起作用

使用dependent: :destroy 在rails 上不起作用

可达性转到“Wi-Fi 设置”按钮不起作用

提交按钮根本不起作用 Simple_Forms Rails 4

Rails best_in_place jQuery 就地编辑:激活器按钮不起作用