Rails 命名空间与嵌套资源

发布于 2024-10-19 23:10:48 字数 1418 浏览 2 评论 0原文

假设我的应用程序有两个模型:Foo 和 Bar。

Foo 可选地属于 Bar。

现在我可以查看单个 Foo,或者搜索特定的 Foo,FoosController 会处理所有这些。我的网址是这样的: foos/1foos/new

有时我想看看一个 Bar。 BarsController 处理这个问题,我的处理方式如下: bars/1bars/1/edit

如果我正在查看一个 Bar,我可能想浏览属于该 Bar 的所有 Foos。因此,我想使用 bars/1/foos/ 来查看这些 Foos。

对于嵌套资源来说,这非常简单,看起来像这样:

resources :foo
resources :bar do
  resources :foo
end

但是,作为 Bar 一部分的 Foo 有点特殊,与常规 Foo 不同。因此,例如,如果我加载 foos/1bars/1/foos/1,我会看到相同的 Foo,但我关注的是不同的信息在每种情况下。

因此,我一直在考虑使用 BarFoos 控制器来处理位于 Bar 上下文中的 Foos。但是,如果我将 BarFoos 嵌套在 Bar 下,那么我的助手将类似于 bar_bar_foos_pathnew_bar_bar_foo_path。这似乎是多余的。

所以,现在我正在考虑命名空间,这是我以前从未研究过的东西。我在 Rails 指南中看到我可以定义:

namespace "bar" do
  resources :foos
end

如果我这样做,我可以在 app/bar/ 下创建第二个 FoosController,并且 FoosController 可以在Bar 带有很好的帮助器,例如 bar_foo_path(:id) 而不是 bar_bar_foo_path(:id)

但如果我这样做,我的 BarsController 会发生什么?如果我有命名空间“bar”而不是resources :bars,请求如何路由到BarsController

最后,我需要在辅助 FoosController 中做一些特殊的事情,以确保与顶级 FoosController 不存在名称冲突吗?我意识到路由说的是“命名空间”,但是 ruby​​ 代码的其余部分如何知道 app/bar/foos_controllerapp/foos_controller 不是同一个类?

谢谢!

Let's say my app has two models, Foo and Bar.

Foo optionally belongs_to Bar.

Right now I can look at a single Foo, or search for a particular Foo, and the FoosController handles all that. My URLS are like:
foos/1 and foos/new

Sometimes I want to look at a Bar. The BarsController handles that, and I get to it like:
bars/1 or bars/1/edit.

If I'm looking at a Bar I might want to browse all the Foos that are part of that Bar. So, I'd like to use bars/1/foos/ to look at those Foos.

This is pretty straightforward with nested resources, and it looks like this:

resources :foo
resources :bar do
  resources :foo
end

However, Foos that are part of a Bar are kind of special, set apart from regular Foos. So, for instance, if I load foos/1 or bars/1/foos/1, I would be looking at the same Foo, but I am focused on different information in each case.

So I've been thinking about having a BarFoos Controller to handle Foos when they're in the context of a Bar. However, if I nest BarFoos under Bar, then my helpers are going to be like bar_bar_foos_path and new_bar_bar_foo_path. That seems redundant.

So, now I'm thinking about namespaces, which is something I've never looked into before. I see in the rails guide that I could define:

namespace "bar" do
  resources :foos
end

If I do that I can make a second FoosController under app/bar/, and that FoosController can handle Foos inside of a Bar with nice helpers like bar_foo_path(:id) instead of bar_bar_foo_path(:id).

But if I do that, what happens to my BarsController? How do requests get routed to BarsController if instead of resources :bars I have namespace "bar"?

And, lastly, is there anything special I need to do inside my secondary FoosController to make sure there's not a name conflict with the top-level FoosController? I realize the routing says "namespace", but how does the rest of the ruby code know that the app/bar/foos_controller and app/foos_controller are not the same class?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼波传意 2024-10-26 23:10:48

我认为您想要实现的是:

  1. Bar​​ 有许多 Foos
  2. 查看属于 Bar 的 Foos
  3. 查看所有 Foos,无论父级如何。

您可以通过以下方式实现这一目标:
routes.rb:

resources :foos
resources :bars do
  resources :foos, :controller => 'bars/foos'
end

您最终得到的路线助手是:

  • bars_path
  • foos_path
  • Bars_foos_path
  • 等,等等,其余的为“rake 路线”
    =)

本质上,你最终得到:

  • app/BarsController (rails gcontrollerbars)
  • app/FoosController(railsgcontrollerfoos)
  • app/bars/FoosController(railsgcontrollerbars/foos)

在 FoosController 中,你可以像往常一样访问 foos with:

@foos = Foos.all

在bars/FoosController 中,您可以通过以下方式访问bar 的foos:

@foos = @bar.foos

其中bar 可以在bars/foos 控制器中通过以下方式预先检索:

before_filter :get_client

private
def get_client
  @bar = Bar.find(params[:bar_id])
end

希望这会有所帮助。 =)

编辑
至于命名空间路由,当我从子路径检索一些资源时,我亲自使用了它们。例如,如果我的网站有一个管理部分,那么我可能有以下内容:

routes.rb:

namespace :admin do
  resources :foos
end

并且我使用以下内容创建控制器:

rails g controller admin/foos

这会设置我的 foos 资源,以便我可以通过“我的网站 url”访问它/admin/foos,还可以获取诸如 admin_foos_path 之类的帮助程序。

I think what you're trying to achieve is:

  1. Bar has many Foos
  2. View Foos belonging to Bar
  3. View all Foos regardless of parent.

You can achieve that with:
routes.rb:

resources :foos
resources :bars do
  resources :foos, :controller => 'bars/foos'
end

The route helpers you end up with are:

  • bars_path
  • foos_path
  • bars_foos_path
  • etc, etc, 'rake routes' for the rest
    =)

In essence, you end up with:

  • app/BarsController (rails g controller bars)
  • app/FoosController (rails g controller foos)
  • app/bars/FoosController (rails g controller bars/foos)

In FoosController, you would access foos as usual with:

@foos = Foos.all

and in bars/FoosController, you would access bar's foos with:

@foos = @bar.foos

where bar can be pre-retrieved in the bars/foos controller with:

before_filter :get_client

private
def get_client
  @bar = Bar.find(params[:bar_id])
end

Hope this helps. =)

Edit:
As for namespaced routes, I've personally used them when I some of my resources retrieved from a sub-path. For example, if I have an admin section of my site, then I might have the following:

routes.rb:

namespace :admin do
  resources :foos
end

and I create my controller with:

rails g controller admin/foos

This sets up my foos resource, such that I can access it at "my site url"/admin/foos, and also get helpers such as admin_foos_path.

终陌 2024-10-26 23:10:48

这种方法也有缺点。

如果你声明一个常量,例如。 CONST_NAME,在嵌套资源 foos 中,rails 由于其作用域算法,会抛出“未初始化常量 ::Foo::CONST_NAME”异常。

为了避免这种行为,请使用:

resources :foos
resources :bars do
  scope :module => "bar" do
    resources :foos #, :controller => 'bar/foos' no need to use this now because route will be searched there by default
  end
end

现在,在使用时不会出现异常:

Foo::CONST_NAME

Bar::Foo::CONST_NAME

There are cons to this approach.

If you declare a constant, eg. CONST_NAME, in nested resource foos, rails will throw "uninitialized constant ::Foo::CONST_NAME" exception because of its scope algorithm.

To avoid such behaviour, use:

resources :foos
resources :bars do
  scope :module => "bar" do
    resources :foos #, :controller => 'bar/foos' no need to use this now because route will be searched there by default
  end
end

Now you will not get an exception while using:

Foo::CONST_NAME

or

Bar::Foo::CONST_NAME
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文