【问题标题】:Rails: passing objects between model and controllerRails:在模型和控制器之间传递对象
【发布时间】:2013-11-12 05:23:50
【问题描述】:

在 Rails 中管理模型和控制器之间的对象是否有最佳实践?我的代码笨拙地将文件从控制器传递到模型并返回,如下所示:

document_controller.rb:

tmp_file = Tempfile.new(Digest::MD5.hexdigest(rand(12).to_s))
pdf = Prawn::Document.generate(tmp_file.path(), :page_size => "A4", :skip_page_creation => true) do |posting|
  @document.process(posting)
  send_data posting.render, :filename => "#{@document.id}", :type => "application/pdf"
end

document.rb:

def process(pdf)
  pdf.start_new_page
  pdf.image self.user.logo.path, :width => pdf.bounds.width
  pdf.fill_color '#444444'
  pdf.image self.component.image_snapshot.path, :width => pdf.bounds.width
  pdf.move_down 20
  pdf.indent 20 do
    pdf.text self.component.name, :size => 24
  end
  box_start = pdf.cursor
  pdf.reflow_column_box([20, box_start-15], :width => pdf.bounds.width-20) do
    format_for_prawn(pdf, self.component.body, self.user.colour1)
  end
end

如何重写这段代码,这样我就不必笨拙地传递pdf/posting 对象?感觉很不像 Rails。

感谢您的意见。

编辑:更糟糕的例子。

再次在控制器中:

tempfile = Magick::Image.read(@document.component.image_newsletter.path).first
overlay = Magick::Image.read(@document.user.logo.path).first.resize_to_fit(tempfile.columns)
rec = Magick::Draw.new
rec.stroke = "##{@document.user.colour1}"
rec.fill = "##{@document.user.colour1}"
rec.rectangle 0, 0, tempfile.columns, 5
lank = tempfile.extent(tempfile.columns, tempfile.rows+overlay.rows, 0 ,0)
final = lank.composite(overlay, Magick::SouthGravity, 0, 0, Magick::OverCompositeOp)
rec.draw(final)
send_data final.to_blob, :filename => "#{@document.user.name}-#{@document.id}.jpg", :type => "image/jpg"

这是在控制器中,否则send_data 无法访问final。有什么帮助吗?

再次感谢。

【问题讨论】:

  • 只是我的意见,但我认为这很好。但是 send_data 应该在块之外吗?
  • 我需要访问posting 来渲染和发送它。不好?
  • 重新你的代码,我认为它很好;如果你想调整你的渲染函数以拥有process,我想你可以这样做,但老实说,我认为这会使过程更加不透明。我唯一会做的不同的事情是使用与process 不同的名称,例如generate_report 或更具有描述性的名称(并且不太可能在另一个类中重复)。
  • 重新成为障碍,从另一种语言来到 ruby​​,这样的事情看起来很笨拙: File.open('my-file.txt', 'w') {|f| f.write("here is a string) } 但实际上它们很好。这似乎增加了不必要的复杂性。
  • 这很公平。我会用一个更糟糕的例子来更新我的问题,看看你的想法。而进程只是一个代理/幽灵方法。

标签: ruby-on-rails ruby ruby-on-rails-3 model-view-controller


【解决方案1】:

编辑

您可以通过

为内置类创建扩展方法
#lib/ext/prawn/document.rb

class Prawn::Document
def process(pdf)
  pdf = self if pdf.blank?
  pdf.start_new_page
  pdf.image self.user.logo.path, :width => pdf.bounds.width
  pdf.fill_color '#444444'
  pdf.image self.component.image_snapshot.path, :width => pdf.bounds.width
  pdf.move_down 20
  pdf.indent 20 do
    pdf.text self.component.name, :size => 24
  end
  box_start = pdf.cursor
  pdf.reflow_column_box([20, box_start-15], :width => pdf.bounds.width-20) do
    format_for_prawn(pdf, self.component.body, self.user.colour1)
  end
end
end

在你的控制器中

tmp_file = Tempfile.new(Digest::MD5.hexdigest(rand(12).to_s))
pdf = Prawn::Document.generate(tmp_file.path(), :page_size => "A4", :skip_page_creation => true) do |posting|
  posting.process
  send_data posting.render, :filename => "#{@document.id}", :type => "application/pdf"
end

要加载此类,您需要在 config/application.rb 文件或初始化程序中使用它。

require 'ext/prawn/document'

【讨论】:

  • 这与将该方法放入模型中并没有什么不同。
【解决方案2】:

为了将凌乱的控制器代码放入模型中,我这样做了:

def process_media
  temp = "#{::Rails.root}/public/temporary/#{temp_file_name}"
  tempfile = Magick::Image.read(self.component.image_newsletter.path).first
  overlay = Magick::Image.read(self.user.logo.path).first.resize_to_fit(tempfile.columns)
  rec = Magick::Draw.new
  rec.stroke = "##{self.user.colour1}"
  rec.fill = "##{self.user.colour1}"
  rec.rectangle 0, 0, tempfile.columns, 5
  lank = tempfile.extent(tempfile.columns, tempfile.rows+overlay.rows, 0 ,0)
  final = lank.composite(overlay, Magick::SouthGravity, 0, 0, Magick::OverCompositeOp)
  rec.draw(final)
  final.to_blob
  final.write("#{temp}.jpg")
end

我正在从控制器发送带有send_file 的实际文件。希望对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 2010-12-31
    • 2018-06-22
    • 2016-10-13
    • 1970-01-01
    • 2012-11-16
    • 1970-01-01
    相关资源
    最近更新 更多