如何根据条件在rails部分中设置不同的变量?

时间:2014-02-14 22:24:28

标签: ruby-on-rails ruby-on-rails-3

我需要能够根据从数据库评估同一个表的条件从数据库中提取不同的值,即为几个条件渲染一个部分?例如,在我的索引视图中,我有:

- @places.each do |place|
    - if place.level == 1
      = render 'place', one: palce 
    - elsif place.level == 2
      = render 'place', two: place
     - else
      = render 'place', none: place

这是我的部分内容:

%table.table
  %caption
    %h2= place.name
  %thead
  %tbody
    %tr
      %td
        Name:
      %td
        = place.place_name
    %tr
      %td
        Total rooms:
      %td
        = place.places_rooms
    %tr
      %td
        Total places:
      %td
        = place.places_count 

我的索引页面代码部分应该是什么样的?

非常感谢!

2 个答案:

答案 0 :(得分:0)

您尝试以不同方式渲染的条件是什么?

我问,因为你传递place作为你的本地人,但你指定一个,两个,没有作为本地人,但他们在你的部分中不存在。如果没有更多信息,我唯一的猜测就是你应该做= render 'place', place: place

编辑随着要求的变化而变化:

-@places.each do |place|
  = render 'place, place: place

部分

%table.table
  %caption
    %h2= place.name
  %thead
  %tbody
    %tr
      %td
        Name:
      %td
        = place.try(:"level_#{place.level}_place") || place.place_name
    %tr
      %td
        Total rooms:
      %td
        = place.places_rooms
    %tr
      %td
        Total places:
      %td
        = place.places_count 

所以我认为这样做是可行的。但也许这应该暗示你的表可能会占用很多不必要的字段。也许最好创建一个级别表,然后在它们之间创建一个关系。

答案 1 :(得分:0)

视图层中的逻辑是一种反模式,因为它使视图的可读性更低/更少与域语言相关联。

您是否考虑将@places包裹在自己创作的decorator object中?假设我正确理解了这个问题(免责声明:我不是100%确定),这就是我可能做的事情:

假设您的控制器是PlacesController ...

# app/controllers/places_controller.rb

class PlacesController < ApplicationController
  def index
    @places = PlaceWithLevels.decorate(places)
  end

  private

  def places
    Place.all
  end
end

现在我们定义装饰器对象PlaceWithLevels(根据您的域名,您可能会提出更好的名称):

# app/models/place_with_levels.rb

class PlaceWithLevels < SimpleDelegator
  def self.decorate(places)
    places.map do |place|
      self.new(place)
    end
  end

  # not sure what to name this since I'm not sure what you're
  # trying to accomplish, but note that this is the method we'll
  # be calling in the partial
  def foo
    case levels
    when 0; 'Text you want to show up when there are 0 levels'
    when 1; 'Text you want to show up when there is 1 level'
    when 2; 'Text you want to show up when there are 2 levels'
  end
end

然后,在视图中:

# app/views/places/index.html.haml
= render @places

请注意,我们不需要调用@places.each,因为render会在集合的每个成员上调用#to_partial_path,以便找出要呈现的部分。 最后,在部分(方法调用places_rooms等等,因为我们在上面使用了SimpleDelegator,所以会在这里工作:

# app/views/places/_place.html.haml
%table.table
  %caption
    %h2= place.name
  %thead
  %tbody
    %tr
      %td
        Name:
      %td
        = place.foo
    %tr
      %td
        Total rooms:
      %td
        = place.places_rooms
    %tr
      %td
        Total places:
      %td
        = place.places_count

请注意,我们不再需要特殊的逻辑...只需在我们的装饰器对象上调用name方法(或任何适当的方法),但从视图的角度看,视图不会我需要知道它正在使用除place以外的任何其他内容。

如果您需要根据level属性呈现完全不同的部分,此技术也非常有用 - 只需在装饰器对象上定义您自己的to_partial_path方法,例如:

def to_partial_path
  case level
  when 0; 'zero_level_place'
  when 1; 'single_level_place'
  when 2; 'two_level_place'
end

希望这有助于!!!!

PS:我还鼓励你除去places_places_roomsplaces_count前缀......更好的信噪比。