将多个变量传递给Rails中的Haml文件?

时间:2011-03-08 02:46:53

标签: ruby-on-rails haml

我正在尝试使用rails将目录的内容推送到Haml(作为字符串数组)并将它们作为链接呈现为链接文本,但无法弄清楚如何传递多个实例变量到我的Haml文件。 这是我的控制器代码:

    class FilesController < ApplicationController
    def index
     @dir = Dir.new('/Users/userName/Code/RailsTest/public/');
     @files = Dir::entries('/Users/userName/Code/RailsTest/public/');
     @fileNames = @files;
     for file in @files
       file = @dir.path + '/' + file
     end
     respond_to do |format|
        format.html # index.html.haml
        #format.xml  { render :locals {:files => @files, :fileNames: @fileNames} }
        format.xml  { render :xml => @files }
     end
  end
end

和我的Haml文件:

%h1 Files
%p This will eventually list the files in our upload directory

- @files.each do |file|
    %a(href=file) file

感谢您提供任何帮助!

编辑: 我的控制器方法现在包含

@dir = Dir.new('/Users/chronon/DEsktop/RailsNexus/public');
     @files = Dir::entries('/Users/chronon/DEsktop/RailsNexus/public');
     @fileNames = @files;
     @files.map! do |file|
       {:path => "#{@dir.path}/#{file}", :filename => file}
     end
     respond_to do |format|
        format.htm
     end

index.html.haml和_file_link.html.haml都是nzifnab建议的。 但是,我现在在我的_file_link文件中得到“无法将符号转换为整数”错误。

两个haml文件的内容都是

%h1 Files
%p This will eventually list the files in our upload directory

= render :partial => 'files/file_link', :collection => @files, :as => :file

= link_to(:file[:path], :file[:filename])

(我必须将'file'更改为':file'才能使渲染正常工作。基于Rails指南)

2 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点:将其渲染为局部或渲染普通输出模板。如果将其渲染为部分,则可以传递:locals选项哈希,您可以使用它来获取变量。如果您渲染一个普通的haml文件,那么您将需要为数据使用实例变量。

我会将控制器中的for循环更改为:

@files.map! do |file|
  {:path => "#{@dir.path}/#{file}", :filename => file}
end

编辑:刚刚意识到你可能已经习惯了.map!方法。它将遍历@files中的每个条目,并将其值更改为块中最后一行的内容。如果你使用.map而不是.map!然后该方法返回一个由这些值组成的新数组。

这只是一个类似ruby的东西,而且我不能100%确定你正在使用的for循环是否像你想要的那样通过引用来改变值。也许你的很好......但是我喜欢类似ruby的方法,比如Array.map,Array.each等而不是for语法,这样就可以获得你在一个漂亮的哈希中每个对象所需的所有数据。

您的haml文件可以更改如下:

index.html.haml

%h1 Files
%p Something exciting

= render :partial => 'files/file_link', :collection => @files, :as => :file

这将为files/file_link.html.haml数组中找到的每个对象呈现文件@files一次,并将该对象保存在file选项指定的局部变量:as =>

然后你可以拥有这个文件:

_file_link.html.haml

= link_to(file[:path], file[:filename])

您在控制器中定义的任何实例变量都将自动在视图中可用。如果出于某种原因,你想让视图中的对象改为局部变量,我相信你必须将视图渲染为局部视图而不是完整视图。虽然它可能会这样做,但我不是百分百肯定。:

format.html{ render :action => 'index', :locals => {:files => files} }

然而,这不是一个好的做法。通常在视图中直接使用控制器中的实例变量。希望我在这里的某处回答你的问题:)(你没有选项或参数的format.html就足够了我上面发布的视图代码。)

编辑:

你改变render :partial to, :as => :file是正确的(这里的符号,我在上面更新了)。但是,它所做的是将@files数组中的每个项目作为名为file的新局部变量发送到partial。所以你的部分仍然应该说:

= link_to(file[:path], file[:filename])

另请注意,您不再需要@fileNames实例变量。 .map!和哈希为您解决了这个问题。

为了澄清,在您致电@files.map! do ...等之后,您的数据结构应如下所示:

@files = [
  {:path => "my/path/1/filenamex", :filename => "filenamex"},
  {:path => "my/path/2/filenamey", :filename => "filenamey"},
  {:path => "my/path/3/filenamez", :filename => "filenamez"}
]

因此,当您将变量发送到render :partial =>时,它将为每个哈希值渲染一次。第一个渲染,它会将_file_link.html.haml中的file变量设置为:

{:path => "my/path/1/filenamex", :filename => "filenamex"}

对于每个哈希值,它将经历三次。

我希望你明白发生了什么:)

答案 1 :(得分:0)

认为这就是你想要的

   @myfiles = [];
     for file in @files
           @myfiles << { :file => @dir.path + '/' + file, :filename => file}
     end

     respond_to do |format|
       format.html
     end