Ruby on rails Rails-具有两个父级的嵌套资源

Ruby on rails Rails-具有两个父级的嵌套资源,ruby-on-rails,nested-resources,Ruby On Rails,Nested Resources,假设我有一个子模型和两个父模型: Event has_many tickets Person has_many tickets Ticket belongs_to Event Ticket belongs_to Person 路线已映射,因此票证始终嵌套在事件或人员中: resource :people do resources :tickets end resources :events do resources :tickets end 如何根据父资源确定我的票证控制器CR

假设我有一个子模型和两个父模型:

Event has_many tickets

Person has_many tickets

Ticket belongs_to Event
Ticket belongs_to Person
路线已映射,因此票证始终嵌套在事件或人员中:

resource :people do
  resources :tickets
end

resources :events do
  resources :tickets
end
如何根据父资源确定我的票证控制器CRUD操作的范围

现在我正在测试参数并使用条件语句:

class TicketController

  before_filter :get_person
  before_filter :get_event

  def index
    if @person do
      ...
    elsif @event do
      ...
    end
    respond_to
      ...
    end
  end
对于每个动作来说,这样做似乎有点乏味。有没有一种更为简单的方法呢?

您可以这样做:

class TicketController

  before_filter :get_object

  def index

  end

  private

  def get_object
    type = params['event_id'] ? 'event' : 'person'
    value = type.classify.constantize.find(params[:"#{type}_id"])
    name = '@' + type
    instance_variable_set(name , value)
  end

end
有很多方法可以改进上面的代码

您还可以按如下方式编写路由:

resources :people, :has_many => :tickets

resources :events, :has_many => :tickets

最干燥的方法是使用继承的资源:

class TicketsController < InheritedResources::Base
  belongs_to :event, :person, :polymorphic => true
end

编辑:我在上面添加了@template_前缀,以解决您在评论中提到的模板问题。

在第二种方法中,我的模板对于这两种类型的父母来说有很大的不同。有什么聪明的方法可以做到这一点,或者只是把响应语句放在一个条件语句中的两个模板上?谢谢,现在我明白了。我还可以通过在get_parent中使用以下内容来摆脱if语句:@prefix=@parent.class。最后一个问题:我不理解代码中的模板前缀,特别是“people/”和“events/”的存在。索引模板位于“/views/ticket/”中。在render命令中添加了“people/”或“events/”时,Rails对嵌套资源路径的解释是否仍能找到“ticket/index”。“事件/票证/索引”和“人员/票证/索引”都会呈现“票证/索引”模板吗?不,它们不会呈现相同的模板。我之所以这么说,是因为你说你的模板根据你是为一个活动还是为一个人提供门票而明显不同。如果你在任何情况下都能自如地使用相同的模板,那么你可以使用“tickets/index”。但是,如果您想使用不同的模板,您可能希望使用一个变量(即render“events/tickets/index”)来控制它。这有意义吗?顺便问一下,你要用不同的URL显示同一个页面吗?如果是,这对你的搜索引擎优化是一个坏消息。
class TicketsController < ActionController::Base
  before_filter :get_parent

  def get_parent
    if params[:person_id]
      @parent = Person.find(params[:person_id])
      @template_prefix = 'people/tickets/'
    elsif params[:event_id]
      @parent = Event.find(params[:event_id])
      @template_prefix = 'events/tickets/'
    else
      # handle this case however is appropriate to your application...
    end
  end

  # Then you can set up your index to be more generic
  def index
    @tickets = @parent.tickets
    render :template => @template_prefix + 'index'
  end
end