繁体   English   中英

Rails Relationship(has_many / belongs_to)已完成

[英]Rails Relationship (has_many/belongs_to) Completed

所以,自从我和人际关系玩起来已经有很长一段时间了,我想确保我做得对。

在我的客户模型中,我有:

class Client < ApplicationRecord
   has_many :projects, dependent: :destroy
end

在我的项目模型中,我有:

class Project < ApplicationRecord
   belongs_to :client
end

所以我知道那是设定的。 然后抓住我放在项目控制器中的项目:

def create
 @client = Client.find(params[:client_id])
 @project = @client.project.new(project_params)
 flash[:notice] = "Project created successfully" if @client.project << @project
 respond with @project, location: admin_project_path
end

我是否需要在我的节目中放一些同样的东西?

关系中我还缺少什么?

我会这样想:

def create
  @client = Client.find(params[:client_id])
  @project = @client.project.new(project_params)
  flash[:notice] = "Project created successfully" if @client.project << @project
  respond with @project, location: admin_project_path
end

看起来更像是:

def create
  @client = Client.find(params[:client_id])
  @project = @client.projects.new(project_params)
  if @project.save
    # do success stuff 
  else
    # do failure stuff
  end
end

注意

@project = @client.project.new(project_params)

应该:

@project = @client.projects.new(project_params)

正如Yechiel K所说,没有必要这样做:

@client.project << @project

以来:

@project = @client.projects.new(project_params)

将自动在新的@project上设置client_id 顺便说一句,如果你想手动将project添加到client ,那么它是:

@client.projects << @project

(注意projectsproject 。)

如果没有client使用params[:client_id] ,那么@client = Client.find(params[:client_id])将抛出错误。 你可能应该包括一个救援区。 或者,我更喜欢:

def create
  if @client = Client.find_by(id: params[:client_id])
    @project = @client.projects.new(project_params)
    if @project.save
      # do success stuff 
    else
      # do failure stuff
    end
  else
    # do something when client not found
  end
end

此外, respond with不是一件事。 respond_with是一件事。 (我相信它已被转移到一个单独的宝石, responders 。)从你的代码中不清楚你是否需要不同的响应,比如, htmljs 如果没有,那么我认为它更像是:

def create
  if @client = Client.find_by(id: params[:client_id])
    @project = @client.projects.new(project_params)
    if @project.save
      flash[:notice] = "Project created successfully"
      redirect_to [@client, @project]
    else
      # do failure stuff
    end
  else
    # do something when client not found
  end
end

这假设你的路线看起来像:

Rails.application.routes.draw do

  resources :clients do 
    resources :projects
  end

end

在这种情况下,rails会将[@client, @project]解析为正确的路由/路径。

正如DaveMongoose所提到的,你可以@client = Client.find_by(id: params[:client_id])before_action 这很常见。 这里有一个关于为什么不这样做的讨论。 就个人而言,我曾经像这样使用before_action ,但是不再这样了。 作为替代方案,您可以:

class ProjectsController < ApplicationController 

  ...

  def create 
    if client 
      @project = client.projects.new(project_params)
      if @project.save
        flash[:notice] = "Project created successfully"
        redirect_to [client, @project]
      else
        # do failure stuff
      end
    else
      # do something when client not found
    end
  end

private

  def client 
    @client ||= Client.find_by(id: params[:client_id])
  end

end

更进一步,你可以这样做:

class ProjectsController < ApplicationController 

  ...

  def create 
    if client 
      if new_project.save
        flash[:notice] = "Project created successfully"
        redirect_to [client, new_project]
      else
        # do failure stuff
      end
    else
      # do something when client not found
    end
  end

private

  def client 
    @client ||= Client.find_by(id: params[:client_id])
  end

  def new_project 
    @new_project ||= client.projects.new(project_params)
  end

end

我会替换这一行:

flash[:notice] = "Project created successfully" if @client.project << @project

有:

flash[:notice] = "Project created successfully" if @project.save

无需手动将@project添加到@client.projects ,当您使用@client.projects.new创建它时会自动添加它,您唯一遗漏的是使用.new创建内容并不会将其保留在DB中,通过调用@project.save完成。

对于你的节目动作,我不确定你是指客户的节目页面还是项目的,但在任何一种情况下,你都会使用params[:id]检索它(除非你使用了一些嵌套路由)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM