Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails控制器中嵌套资源的条件路由#编辑操作,取决于请求来自何处_Ruby On Rails_Redirect_Controller_Routing - Fatal编程技术网

Ruby on rails Rails控制器中嵌套资源的条件路由#编辑操作,取决于请求来自何处

Ruby on rails Rails控制器中嵌套资源的条件路由#编辑操作,取决于请求来自何处,ruby-on-rails,redirect,controller,routing,Ruby On Rails,Redirect,Controller,Routing,我有一个Foo资源有许多条。我将嵌套资源用于有限数量的操作,但在其他情况下,我更喜欢将路由保持为浅条。导航到条形图对象的编辑视图有两种方法-从包含foo的嵌套路径,或从不嵌套在foo中的较浅的Bar路径。例如,用户可以在/foos/[:foo_id]/bar/[:bar_id]的页面上单击编辑按钮;或者从/bar/[:bar\u id]开始 在第一种情况下,我希望控制器在更新记录后将用户重定向回父foo页面:/foos/[:foo\u id]。在第二种情况下,我希望它重定向到条:/bar的索引视

我有一个Foo资源
有许多
条。我将嵌套资源用于有限数量的操作,但在其他情况下,我更喜欢将路由保持为浅条。导航到条形图对象的编辑视图有两种方法-从包含
foo
的嵌套路径,或从不嵌套在
foo
中的较浅的
Bar
路径。例如,用户可以在
/foos/[:foo_id]/bar/[:bar_id]
的页面上单击编辑按钮;或者从
/bar/[:bar\u id]
开始

在第一种情况下,我希望控制器在更新记录后将用户重定向回父foo页面:
/foos/[:foo\u id]
。在第二种情况下,我希望它重定向到
/bar
的索引视图。我相信我需要在
控制器中的
编辑
操作中使用某种条件,它将告诉Rails在执行
#更新
后要去哪里

# config/routes.rb
resources :foos do
  resources :bars, only: [:new, :edit]
end

resources :bars

# bin/rake routes:
foo_bars     POST   /foos/:foo_id/bars(.:format)          bars#create
new_foo_bar  GET    /foos/:foo_id/bars/new(.:format)      bars#new
edit_foo_bar GET    /foos/:foo_id/bars/:id/edit(.:format) bars#edit
        bars GET    /bars(.:format)                       bars#index
             POST   /bars(.:format)                       bars#create
     new_bar GET    /bars/new(.:format)                   bars#new
    edit_bar GET    /bars/:id/edit(.:format)              bars#edit
         bar GET    /bars/:id(.:format)                   bars#show
             PATCH  /bars/:id(.:format)                   bars#update
             PUT    /bars/:id(.:format)                   bars#update
             DELETE /bars/:id(.:format)                   bars#destroy
条的控制器

# app/controllers/bar_controller.rb
def edit
  @bar = bar.find(params[:id])
  @foo = @bar.foo
end

def update
  @bar = bar.find(params[:id])
  @foo = @bar.foo

  respond_to do |format|
    if @bar.update_attributes(bar_params)
      format.html { redirect_to @foo, notice: "bar successfully updated" }
    else
      format.html { render action: "edit" }
    end
  end
end
我正在尝试更改
#update
操作中的
重定向到@foo
行,以便根据
#edit
操作的启动位置,有条件逻辑将
@foo
切换到
@bar
。我尝试了以下方法来测试调用
#edit
操作时是否存在
params[:foo]
,为重定向设置一个实例变量

def edit
  if params[:foo]
    @redirect_page = @foo
  else
    @redirect_page = @bars
  end
  @bar = bar.find(params[:id])
  @foo = @bar.foo
end

def update
  # code omitted...
      format.html { redirect_to @redirect_page, notice: "bar successfully updated" }
  # code omitted...
end
这不管用。Rails状态
无法重定向到nil。我还尝试了一些基于
#edit
操作中的
URI(request.referer).path
的测试,但没有成功


我仍然不完全清楚Rails的魔力是如何在控制器中发生的。我相信
#edit
操作是定义重定向条件的合适位置(或通过
#edit
操作中调用的方法),因为控制器将在那里“看到”传入请求并知道它来自何处。但我不太明白如何捕获这些信息,并将其传递给
#update
。感谢您的指导。

在您的编辑表单中,添加一个
隐藏的\u字段\u标签

<%= hidden_field_tag "route", request.env['PATH_INFO'] %>


然后在您的控制器中,您可以有一个
if
语句,并根据
参数[:route]
是什么,使用一个
重定向到

。使用
request.env['PATH\u INFO]
的params[:route]方法对我不起作用,因为表单中的'PATH\u INFO'变量提供了传递给
bar#update
操作的路径,而不是启动
bar#edit
操作的路径

/foos/[:id]
的父foo页面中单击“编辑”后,参数散列为:

>>  params
=> {"controller"=>"bars", "action"=>"edit", "foo_id"=>"3786", "id"=>"16"}
首次访问表单时,
params[:route]
没有值-只有在编辑表单中单击“更新”后,隐藏字段才会添加到params散列中:

>>  params[:route]
=> "/foos/3786/bars/16/edit"
这可能可行,但需要构建逻辑来解析路由,以便重定向到
/foos/[:foo_id]

事实证明,使用Rails
flash
方法存储重定向回源页面的路径更简单。为此,我在BarsController中调用了一个自定义方法
set\u redirect\u path
,然后在
bars\edit
中调用它。这将为闪存中的源设置一个值,该值可在
栏#update
中找到。也许有更好/更传统的方法来实现这一点,但这似乎是一个干净和简单的方式来做我想要的

# app/controllers/bars_controller.rb
def edit
  set_redirect_path
  @bar = bar.find(params[:id])
  @foo = @bar.foo
end

def update
  @bar = bar.find(params[:id])
  @foo = @bar.foo

  respond_to do |format|
    if @bar.update_attributes(bar_params)
      format.html { redirect_to flash[:source], notice: "bar successfully updated" }
      format.xml { head :ok }
    else
      format.html { render action: "edit" }
      format.xml { render xml: @bar.errors, status: :unprocessable_entity }
    end
  end
end

private
  def set_redirect_path
    flash[:source] = URI(request.referer).path
  end

这种方法的一个优点是,我现在可以摆脱共享部分
app/views/bar/\u list.html.haml
中的条件逻辑,该逻辑用于确定单击“编辑”按钮是否应路由到
Edit\u foo\u bar\u path
Edit\u bar\u path
(即,如果
@foo
存在,则选择前者)。因此,我可以删除嵌套资源
:bar
:edit
。由于闪存捕获请求的传入源并将其存储在
#update
操作中以供参考,因此所有编辑请求都可以使用相同的
编辑条路径
,而不管它们来自何处。更新后,Rails将用户重定向到他们启动编辑操作的点。

您正在定义编辑操作的重定向页面。您需要在更新操作时执行此操作。在编辑表单上,您可以将de
foo\u id
设置为隐藏字段。但我需要捕获调用
\edit
时请求的来源。如果我将逻辑放在
#update
操作中,我就看不到原始请求。例如,在编辑表单的web控制台中,
URI(request.referer).path
返回
/foos/[:foo\u id]
。提交后(在
#update
操作中调用
控制台
),它返回
/bar/[:bar\u id]/edit
。这并没有告诉我在哪里调用了
#edit
。顺便说一句,我意识到,
#edit
是为foo中的嵌套资源公开的;但是,使用共享视图显示
条形图#索引
foo#show
页面上的条形图。试图避免附加的视图逻辑