1

我的 Rails 应用程序中有两个模型(帖子、图片),它们的关联如下:

#Post model
has_many :pictures, :dependent => :destroy 
accepts_nested_attributes_for :pictures, :allow_destroy => true 

#Picture model
belongs_to :post

在我的帖子编辑视图中,我有两个表单,因此我可以编辑帖子内容以及将图片添加到帖子中。我使用 jquery 文件上传插件和carrierwave 来处理上传过程。这看起来与这里的设置非常相似http://tinyurl.com/aun7bl5

当我进入后期编辑视图时,jquery 文件上传总是向我显示所有图片,因为它使用图片控制器的索引操作来获取所有图像并将它们呈现为 json,因此 jquery 文件上传可以处理它们。索引操作看起来像这样。

def index
  @pictures = Picture.all 
  render :json => @pictures.collect { |p| p.to_jq_upload }.to_json
end

当我编辑帖子时,帖子控制器可以使用帖子参数(:id)。我可以用记录器看到它。但它不适用于嵌套在帖子编辑表单中的索引操作。

现在我的问题是,如何在 post 控制器中为 index 操作提供我喜欢编辑的帖子的 id,以便我可以在那里执行类似的操作来过滤它获得的图片:

def index
  @pictures = Picture.where(:post_id => params[:id])
  render :json => @pictures.collect { |p| p.to_jq_upload }.to_json
end

编辑:

#Post#edit view
<div class=post-well>
  <div class="page-header">
    <h1>Reisebericht editieren</h2>
  </div>

  <%= simple_form_for @post do |f| %>
    <%= f.error_notification %>
    <div class="form-inputs">
      <%= f.input :title, :label => "Titel", :input_html => { :class => 'new-post-inputfields' } %>
      <%= f.input :body, :label => "Artikel", :input_html => { :class => 'new-post-inputfields' } %>
      <%= f.hidden_field :picture_ids, :input_html => { :id => 'post_picture_ids' } %> 
      <%= f.button :submit, :label => "Speichern" %>
    </div> 
  <% end %>

  <h4>Bilder verwalten</h4>
  <%= simple_form_for Picture.new, :html => { :multipart => true, :id => "fileupload"  } do |f| %>
    <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
    <div class="row fileupload-buttonbar">
      <div class="span7">
        <!-- The fileinput-button span is used to style the file input field as button -->
        <span class="btn btn-success fileinput-button">
          <i class="icon-plus icon-white"></i>
          <span>Hinzufügen</span>
          <%= f.file_field :path, multiple: true, name: "picture[path]" %>
        </span>
        <button type="submit" class="btn btn-primary start">
          <i class="icon-upload icon-white"></i>
          <span>Upload</span>
        </button>
        <button type="reset" class="btn btn-warning cancel">
          <i class="icon-ban-circle icon-white"></i>
          <span>Abbrechen</span>
        </button>
        <button type="button" class="btn btn-danger delete">
          <i class="icon-trash icon-white"></i>
          <span>Delete</span>
        </button>
        <input type="checkbox" class="toggle">
      </div>
      <div class="span5">
        <!-- The global progress bar -->
        <div class="progress progress-success progress-striped active fade">
          <div class="bar" style="width:0%;"></div>
        </div>
      </div>
    </div>
    <!-- The loading indicator is shown during image processing -->
    <div class="fileupload-loading"></div>
    <br>
    <!-- The table listing the files available for upload/download -->
    <table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody>
    </table>
  <% end %>
</div> 

<script>
  var fileUploadErrors = {
    maxFileSize: 'File is too big',
    minFileSize: 'File is too small',
    acceptFileTypes: 'Filetype not allowed',
    maxNumberOfFiles: 'Max number of files exceeded',
    uploadedBytes: 'Uploaded bytes exceed file size',
    emptyResult: 'Empty file upload result'
  };
</script>

<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
  <tr class="template-upload fade">
    <td class="preview"><span class="fade"></span></td>
      <td class="name"><span>{%=file.name%}</span></td>
        <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
        {% if (file.error) { %}
          <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
        {% } else if (o.files.valid && !i) { %}
          <td>
            <div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div>
            </td>
            <td class="start">{% if (!o.options.autoUpload) { %}
              <button class="btn btn-primary">
                <i class="icon-upload icon-white"></i>
                  <span>{%=locale.fileupload.start%}</span>
                </button>
            {% } %}</td>
        {% } else { %}
          <td colspan="2"></td>
        {% } %}
        <td class="cancel">{% if (!i) { %}
          <button class="btn btn-warning">
            <i class="icon-ban-circle icon-white"></i>
              <span>{%=locale.fileupload.cancel%}</span>
            </button>
        {% } %}</td>
    </tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
  <tr class="template-download fade">
    {% if (file.error) { %}
      <td></td>
        <td class="name"><span>{%=file.name%}</span></td>
          <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
            <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td>
        {% } else { %}
          <td class="preview">{% if (file.thumbnail_url) { %}
            <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a>
            {% } %}</td>
            <td class="name">
              <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a>
            </td>
            <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
            <td colspan="2"></td>
        {% } %}
        <td class="delete">
          <button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
            <i class="icon-trash icon-white"></i>
              <span>{%=locale.fileupload.destroy%}</span>
            </button>
            <input type="checkbox" name="delete" value="1">
        </td>
    </tr>
{% } %}
</script>

和javascript:

$(function () {  
  // Initialize the jQuery File Upload widget:
  $('#fileupload').fileupload({
  completed: function(e, data) {
     console.log(data.result[0].picture_id); 
     $("#post_picture_ids").val(function(i,val) { 
          return val + (val ? ', ' : '') + data.result[0].picture_id;
     });
   }
 });

 // Load existing files:
 $.getJSON($('#fileupload').prop('action'), function (files) {
  var fu = $('#fileupload').data('fileupload'), 
  template;
  fu._adjustMaxNumberOfFiles(-files.length);
  template = fu._renderDownload(files)
  .appendTo($('#fileupload .files'));
  // Force reflow:
  fu._reflow = fu._transition && template.length &&
  template[0].offsetWidth;
  template.addClass('in');
 $('#loading').remove();
 });
}); 

对此的任何帮助将不胜感激。

EDIT2:对于一种解决方案,请参见下面的@SybariteManoj 答案。另一种解决方案是使用:

$.getJSON($('#fileupload').prop('action') + '/' + $('#current_post_id').val(), function (files) {

在 get 函数的开头,然后为图片控制器添加一个路由,如下所示:

get 'pictures/:id', to: 'pictures#index'

然后,图片控制器中的索引操作将过滤此解决方案中的 id 参数,如下所示:

def index
  @pictures = Picture.where(:post_id => params[:id])
  render :json => @pictures.collect { |p| p.to_jq_upload }.to_json
end 

我想我更喜欢@SybariteManoj 的完整解决方案,因此不需要路线,索引操作现在看起来像这样。

def index
  @pictures = Picture.where(:post_id => params[:post_id])
  render :json => @pictures.collect { |p| p.to_jq_upload }.to_json
end 
4

3 回答 3

1

由于您正在编辑帖子,因此帖子params[:id]可用于帖子控制器的update操作,而不是其他人可用,这是在 rails 中编辑表单后的默认操作调用。

如果您想要params[:id]index操作中,那么您需要在调用更新操作后重定向到索引操作,或者您需要将显示所选图片的逻辑仅放在更新操作中。

您还可以创建自定义操作方法来处理显示属于帖子的图片的过程。

于 2013-02-01T10:39:41.170 回答
1

我想您Picture有一个名为 foreign_key 的名称post_id,您可以在index操作中简单地使用它来仅获取属于Post.

尝试这样的事情:

def index
  @pictures = @post.pictures 
  render :json => @pictures.collect { |p| p.to_jq_upload }.to_json
end

编辑

由于您的图片belong_to是您的帖子,您还需要修改newcreate操作,以便为您的帖子创建图片。

一种方法是find_post在您的Picture控制器中创建一个方法,并进行before_filter如下回调:

class PicturesController < ApplicationController
  before_filter :find_post, :only => [:index, :new, :create]

  def find_post
    @post = Post.find(params[:post_id]) unless params[:post_id].nil?
  end

  def new
    @picture = @post.pictures.new
  end

  ## Same thing for the create action
end

在您看来,在创建表单时也这样做:

<%= simple_form_for @post.pictures.new

希望这可以帮助。

于 2013-02-01T10:43:09.893 回答
1

我想我找到了罪魁祸首。在您的 javascript 中,$.getJSON($('#fileupload').prop('action')这是传递图像上传表单的 action 属性的值。

尝试在编辑视图文件中的某处添加此行

<%= hidden_field_tag :current_post_id, @post.id, :id => 'current_post_id' %>

并替换此行

$.getJSON($('#fileupload').prop('action'), function (files) {

$.getJSON($('#fileupload').prop('action') + '?post_id=' + $('#current_post_id').val(), function (files) {

我尚未对其进行测试,但我很确定这应该可以解决您的问题。

于 2013-02-01T14:58:07.007 回答