多个嵌套路由到同一个控制器。没有ID,找不到XYZ

时间:2013-03-01 19:35:56

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2 routes nested-routes

我正在重构我的应用程序,以便在任何地方使用1级深层嵌套资源,它是一个仅限JSON的API。这是我routes.rb的修剪版本:

resources :measurements, only: [:index, :show] do
  resource :tag_node, controller: :physical_nodes, only: [:show]
  resource :anchor_node, controller: :physical_nodes, only: [:show]
  resource :experiment, only: [:show]
end

resources :physical_nodes, only: [:index, :show] do
  resources :tag_nodes, controller: :measurements, only: [:index]
  resources :anchor_nodes, controller: :measurements, only: [:index]
end

resources :experiments, only: [:index, :show] do
  resources :measurements, only: [:index]
end

我缩减models

class Measurement < ActiveRecord::Base
  self.table_name = 'measurement'
  self.primary_key = 'id'

  belongs_to :physical_node, foreign_key: :tag_node_id
  belongs_to :physical_node, foreign_key: :anchor_node_id
  belongs_to :experiment, foreign_key: :experiment_id
end

class PhysicalNode < ActiveRecord::Base
  self.table_name = 'physical_node'
  self.primary_key = 'id'

  has_many :measurements, foreign_key: :tag_node_id
  has_many :measurements, foreign_key: :anchor_node_id
end

class Experiment < ActiveRecord::Base
  self.table_name = 'experiment'
  self.primary_key = 'id'

  has_many :measurements, foreign_key: :experiment_id
end

1:

什么有效:

  • GET /experiments/4/measurements.json工作正常

什么行不通:(其他一切;))

  • GET /measurements/2/experiment.json

错误讯息:

Processing by ExperimentsController#show as HTML
Parameters: {"measurement_id"=>"2"}

ActiveRecord::RecordNotFound (Couldn't find Experiment without an ID)

这应该很容易修复。更重要的是:

2:

GET "/measurements/2/tag_node"

Processing by PhysicalNodesController#show as HTML
Parameters: {"measurement_id"=>"2"}

如何让我调用它来tag_node_id而不是measurement_id

解决方案:

经过与'dmoss18'的长时间聊天后,很明显将tag_nodesanchor_nodes作为physical_nodes的子元素放在一起是没有意义的,因为它们只存在于测量表。

所以现在我的routes.rb看起来像这样:

resources :measurements, only: [:index, :show, :create]

resources :physical_nodes, only: [:index, :show]

resources :tag_nodes, only: [] do
  resources :measurements, only: [:index]
end

resources :anchor_nodes, only: [] do
  resources :measurements, only: [:index]
end

resources :experiments, only: [:index, :show] do
  resources :measurements, only: [:index]
end

我还删除了所有only childs,因为这不是数据库的设计方式。

1 个答案:

答案 0 :(得分:1)

1:您的ExperimentsController #show action可能会寻找params [:id]来查找rails在测量ID中传递的实验。您需要执行以下操作:

@experiment = Experiment.find(params[:measurement_id])

但是,由于您的实验表没有measurement_id列,因此无法使用。我不建议将实验嵌套作为测量资源。这不是您的数据库的布局方式。如果你仍然希望嵌套它,这就是你需要做的:

@experiment = Measurement.find(measurement.experiment_id).experiment

您的“has_many”和“belongs_to”不需要“foreign_key”属性。 Rails会自己解决这个问题。

2:由于此路由的父资源是Measurement,因此rails将假定调用id参数:measurement_id。像这样更新您的关联:

class Measurement < ActiveRecord::Base
  self.table_name = 'measurement'
  self.primary_key = 'id'

  belongs_to :tag_node, :class_name => 'PhysicalNode', :foreign_key => :tag_node_id
  belongs_to :anchor_node, :class_name => 'PhysicalNode', :foreign_key => :anchor_node_id
  belongs_to :experiment
end

class PhysicalNode < ActiveRecord::Base
  self.table_name = 'physical_node'
  self.primary_key = 'id'

  has_many :tag_node, :class_name => 'Measurement', :foreign_key => :tag_node_id
  has_many :anchor_node, :class_name => 'Measurement', :foreign_key => :anchor_node_id
end

class Experiment < ActiveRecord::Base
  self.table_name = 'experiment'
  self.primary_key = 'id'

  has_many :measurements
end

我不会在测量资源下嵌套任何内容,因为它是子资源,而不是父资源。由于您的/ measurements / 1 / [anythingelse]是测量路由,因此rails假定id为:measurement_id。 您在ID为1的测量资源/对象下嵌套。换句话说,您说测量x HAS tag_nodes和HAS anchor_nodes,这不是真的。

如果您仍然想要,可以在控制器中为每个资源创建单独的操作,如下所示:

resources :measurements, only: [:index, :show] do
  resource :tag_node, controller: :physical_nodes, only: [:show_tag]
  resource :anchor_node, controller: :physical_nodes, only: [:show_anchor]
  resource :experiment, only: [:show]
end

在physical_nodes控制器中创建show_tag和show_anchor操作。然后,这些操作将查找params [:measurement_id)