如何在lib / Module方法中使用Rails更干燥的case语句?

时间:2011-03-02 05:54:13

标签: ruby-on-rails ruby case

以下是我在lib / Module中调用cron_tasks.rb的方法。

这是一个案例陈述:

case quad

when "0"

然后运行这种类型的代码。

79           #upper-left address
 80            pdf.draw_text contact.first_name + " " + contact.last_name,
 81               :at =>[(pdf.bounds.left + postcard_width - in2pt(2.75)), (pdf.bounds.top - in2pt(2.25))],
 82               :size => 14
 83 
 84            pdf.draw_text contact.address.street1,
 85               :at =>[(pdf.bounds.left + postcard_width - in2pt(2.75)), (pdf.bounds.top - in2pt(2.25) - 20)],
 86               :size => 14
 87 
 88            pdf.draw_text contact.address.city + ", " + contact.address.state,
 89               :at =>[(pdf.bounds.left + postcard_width - in2pt(2.75)), (pdf.bounds.top - in2pt(2.25) - 40)],
 90               :size => 14
 91 
 92            pdf.draw_text contact.address.zip,
 93               :at =>[(pdf.bounds.left + postcard_width - in2pt(2.75)), (pdf.bounds.top - in2pt(2.25) - 60)],
 94               :size => 14

对于不同的时间,所有这些代码只有轻微的偏移:

when 1
....(same code)

when 2
....(same code)

when 3
....(same code)

有没有办法让所有的文本定位更干燥(也许这个模块中的self.position?),这样我才能传递偏移量?

我在一张大纸上打印一次四个地址,所以相对位置是相同的,我只需要将它移动到四个象限中的每一个。

重要提示:难以接受的挑战是,当我尝试使用self.print_address时,我必须从main方法中传递这么多变量...实际上,我还没弄清楚如何添加所有这些因为对其他模块有依赖...

2 个答案:

答案 0 :(得分:1)

我会使用Bounding Boxes。您可以绝对定位四个边界框,而不是绝对定位每个地址线。

  pdf.bounding_box([(pdf.bounds.left + postcard_width - in2pt(2.75)), (pdf.bounds.top - in2pt(2.25))], :width=>250, :height=>100) do
     pdf.font_size 14
     pdf.text contact.first_name + " " + contact.last_name
     pdf.text contact.address.street1
     pdf.text contact.address.city + ", " + contact.address.state
     pdf.text contact.address.zip
     #pdf.stroke_bounds #use for testing box size
  end

编辑:与lambda一起使用

将lamba中的边界框包装起来,然后从case语句中调用它。

draw_address = lambda { |contact, x, y| 
  pdf.bounding_box([x, y], :width=>250, :height=>100) do
     pdf.font_size 14
     pdf.text contact.first_name + " " + contact.last_name
     pdf.text contact.address.street1
     pdf.text contact.address.city + ", " + contact.address.state
     pdf.text contact.address.zip
     #pdf.stroke_bounds #use for testing box size
  end
  }

  #use draw_address in your case to populate and position
when 1
  draw_address(contact, 560, 70)
when 2
  draw_address(contact, 240, 70)
when etc...

答案 1 :(得分:0)

你可以将重复的东西包裹在一个lambda中,这会使差异立即明显,你不会重复自己:

draw_it = lambda { |str, offset|
    x = pdf.bounds.left + postcard_width - in2pt(2.75)
    y = pdf.bounds.top  - in2pt(2.25)    - offset
    pdf.draw_text(str, :at =>[ x, y ], :size => 14)
}
#...
draw_it.call(contact.first_name + " " + contact.last_name,         0)
draw_it.call(contact.address.street1,                             20)
draw_it.call(contact.address.city + ", " + contact.address.state, 40)
draw_it.call(contact.address.zip,                                 60)

然后再采取一个简单的步骤来取消offset参数:

offset  = 0
draw_it = lambda { |str|
    x       = pdf.bounds.left + postcard_width - in2pt(2.75)
    y       = pdf.bounds.top  - in2pt(2.25)    - offset
    offset += 20
    pdf.draw_text(str, :at =>[ x, y ], :size => 14)
}
#...
draw_it.call(contact.first_name + " " + contact.last_name)
draw_it.call(contact.address.street1)
draw_it.call(contact.address.city + ", " + contact.address.state)
draw_it.call(contact.address.zip)

你也可以把它变成一个完整的方法,但是你必须正确地跟踪和重置@offset的值,你最终会拖动一个无用的实例变量(@offset周围;对于像这样的情况,一个简单的闭包可能更有意义。