2012-02-20 11 views
12

Szukałam dla niektórych przykładów, ale mają pochodzić skrócie:Rails 3 + jQuery File-Upload + zagnieżdżony model

próbuję wdrożyć jQuery File przesłać na projekt jestem pracuję nad, ale gubię się, jak zmusić go do pracy z zagnieżdżonymi atrybutami.

Krótki opis:

2 modele:

Comment [has_many :attachments] 
Attachment [belongs_to :comment] 

Komentarz accepts_nested_attributes_for :attachments. Również - używam Dragonfly.

Przejrzałem podręczniki Rails 3 na stronie z plikami do przesyłania plików JQuery, ale zakładają, że jest to pojedynczy model, więc wszystko opiera się na formularzu. Czy ktoś ma jakieś przykłady ich implementacji lub czy istnieje już samouczek, na który jeszcze się nie natknąłem?

Jestem pewien, że ktoś miał podobny problem ... jest JQuery-File-Upload do odpowiedniego narzędzia lub powinienem spojrzeć na coś innego?

+0

Hej, Mam podobny problem, w którym nie mogę użyć pliku JQuery-File-Upload z gemem nested_form. Czy byłeś w stanie znaleźć rozwiązanie tego problemu? –

+0

Pytasz o przesłanie AJAX-a, tak jak w pliku wysyłanym, podczas gdy użytkownik nadal wypełnia resztę formularza, tak? Czy pracujesz z obrazami lub po prostu plikami? A czy model załącznika ma w sobie coś innego niż pliki - jakiekolwiek zatwierdzenia itp.? – Andrew

Odpowiedz

1

Mam podobne ustawienia działające z Carrierwave. Oto co mam. Używam obrazów jako zagnieżdżonego zasobu dla projektów.

Project.rb:

has_many :images, :dependent => :destroy 
accepts_nested_attributes_for :images, :allow_destroy => true 

Image.rb:

include Rails.application.routes.url_helpers 
    mount_uploader :image, ImageUploader 

    belongs_to :project 

    #one convenient method to pass jq_upload the necessary information 
    def to_jq_upload 
    { 
    "name" => read_attribute(:image), 
    "size" => image.size, 
    "url" => image.url, 
    "thumbnail_url" => image.thumb.url, 
    "delete_url" => image_path(:id => id), 
    "delete_type" => "DELETE" 
    } 
    end 

Images_controller.rb:

def create 
    @image = Image.new(params[:image]) 
    @image.project_id = params[:project_id] 
    @project = Project.find(params[:project_id]) 
    @image.position = @project.images.count + 1 
    if @image.save 
     render :json => [ @image.to_jq_upload ].to_json 
    else 
     render :json => [ @image.to_jq_upload.merge({ :error => "custom_failure" }) ].to_json 
    end 
    end 

Należy pamiętać, że był to * @ ^%! aby zacząć działać.

UPDATE: projekty/_form.html.erb

<div id="fileupload" class="image_add"> 
    <%= form_for Image.new, :html => {:multipart => true} do |f| %> 
     <div class="fileupload-buttonbar"> 
      <label class="fileinput-button"> 
       <span>Add files...</span> 
       <%= hidden_field_tag :project_id, @project.id %> 
       <%= f.file_field :image %> 
      </label> 
      <button type="submit" class="start">Start Upload</button> 
      <button type="reset" class="cancel">Cancel Upload</button> 
      <button type="button" class="delete">Delete Files</button> 
     </div> 
    <% end %> 
    <div class="fileupload-content"> 
     <div class="dropzone-container"> 
      <div class="dropzone">Drop Image Files Here</div> 
     </div> 
     <table class="files"></table> 
    </div> 
</div> 
+0

Hej dzięki za tę odpowiedź. Próbuję uruchomić to samo rozwiązanie. Czy możesz też opublikować widok formularza? Dzięki! – Marc

+0

To jest ogromna * # & * (# do pracy.) Próbuję dowiedzieć się, jak sformatować formularz. Zagnieżdżona forma nie wydaje się działać ... Marc

+1

Sure Marc, Minęło dużo czasu odkąd zajrzałem do tego kodu, ale tutaj jest kod formularza do przesyłania zdjęć. Właśnie przekazuję project_id w hidden_field_tag, więc mogę go później złapać .. Powodzenia! – Stone

6

Chciałem rzucić moją odpowiedź tutaj jak Stone'a. Spędziłem prawie dwa solidne dni, aby to zadziałało (Stone miał rację, to była PITA!), Więc mam nadzieję, że moje rozwiązanie pomoże komuś. Zrobiłem to tylko dotyk inny niż Stone.

Moja aplikacja ma Features (komiks, puzzle, text-kolumnę, etc) oraz FeatureAssets (wersje indywidualne panele komiks/kolorów, pytanie & plików odpowiedzi dla konkretnej krzyżówki, etc). Od FeatureAssets są wyłącznie związane z jednym Feature, zagnieżdżiłem modele (jak widać w moim formularzu przesyłania).

Największym problemem dla mnie było to, że mój params[:feature_asset], który był wysyłany na serwer, był w rzeczywistości zbiorem obiektów uploader'd file, zamiast tylko tych, z którymi byłem przyzwyczajony. Po odrobinie błahostki z iterowaniem każdego pliku i utworzeniem z niego FeatureAsset działało jak czar!

Mam nadzieję, że przetłumaczyć to wyraźnie. Wolałbym podać trochę za dużo informacji niż za mało. Trochę dodatkowego kontekstu nigdy nie boli, gdy interpretujesz czyjś kod.

funkcja.rb

class Feature < ActiveRecord::Base 
    belongs_to :user 
    has_many :feature_assets 

    attr_accessible :name, :description, :user_id, :image 

    accepts_nested_attributes_for :feature_assets, :allow_destroy => true 

    validates :name, :presence => true 
    validates :user_id, :presence => true 

    mount_uploader :image, FeatureImageUploader 
end 

feature_asset.rb

belongs_to :user 
    belongs_to :feature 

    attr_accessible :user_id, :feature_id, :file, :file_cache 

    validates :user_id,  :presence => true 
    validates :feature_id, :presence => true 
    validates :file,  :presence => true 

    mount_uploader :file, FeatureAssetContentUploader 

    # grabs useful file attributes & sends them as JSON to the jQuery file uploader 
    def to_jq_upload 
    { 
     "file" => file, 
     "file_name" => 'asdf', 
     "url" => file.url, 
     "delete_url" => id, 
     "delete_type" => "DELETE" 
    } 
    end 

feature_assets_controller.rb

def create 
    @feature = Feature.find(params[:feature_id]) 

    params[:feature_asset]['file'].each do |f| 
     @feature_asset = FeatureAsset.create!(:file => f, :feature_id => @feature.id, :user_id => current_user.id) 
    end 

    redirect_to @feature 
    end 

I nie to, że prawdopodobnie pomaga że dużo, ale mój feature_asset_uploader.rb jest poniżej. Jest dość rozebrany.

class FeatureAssetContentUploader < CarrierWave::Uploader::Base 

    storage :file 

end 

wyposażony _form.html.erb (podobny do Stone'a, ale nie całkiem)

<%= form_for [@feature, @feature_asset], :html => { :multipart => true } do |f| %> 
    <div class="row" id="fileupload"> 
    <div class=" fileupload-buttonbar"> 
     <div class="progressbar fileupload-progressbar nofade"><div style="width:0%;"></div></div> 
     <span class="btn btn-primary fileinput-button"> 
     <i class="icon-plus"></i> 
     <span><%= t('feature_assets.add_files') %>...</span> 
     <%= hidden_field_tag :feature_id, @feature.id %> 
     <%= hidden_field_tag :user_id, current_user.id %> 
     <%= f.file_field :file, :multiple => true %> 
     </span> 
     <button type="submit" class="btn btn-success">Start Upload</button> 
     <button type="reset" class="btn btn-warning">Cancel Upload</button> 
     <button type="button" class="btn btn-danger">Delete Files</button> 
    </div> 
    </div> 

Nie ma obsługi błędów lub jakiejkolwiek subtelności powinien mieć, ale to wersja Barebone tego.

Mam nadzieję, że pomaga komuś tam. Nie wahaj się zapytać mnie, jeśli masz jakieś pytania!

Kyle

+0

Próbuję zrobić to samo jak ty i kamień, ale potrzebuję feature_asset do być zawarte w tej samej formie. Jakieś wskazówki? –

+0

@AlainGoldman - W jaki sposób próbujesz utworzyć "Feature" i jego "FeatureAssets" w tej samej formie? To jest tutorial i aplikacja, z której oparłem swój kod. Dokładnie to robi! https://github.com/tors/jquery-fileupload-rails –

+0

Rozwiązałem to, używając rozwiązania podobnego do: http://www.railscook.com/recipes/multiple-files-upload-with-nested-resource- using-paperclip-in-rails/ – Galaxy

0

I radzą sobie z tym problemem i popełnił demo app aby pokazać, jak to zrobić.

W skrócie mam dwa modele: element i upload.

item.rb:

has_many :uploads 
accepts_nested_attributes_for :uploads, :allow_destroy => true 

upload.rb:

belongs_to :item 
    has_attached_file :upload, :styles => { :large => "800x800", :medium => "400x400>", :small => "200x200>" } 

dodałem uploads_attributes do kontrolera poz.

Teraz można dodać formularz jquery-file-upload do widzenia, ale jest jeden problem: to wysyła każde zdjęcie w oddzielnych wniosków. Więc nie jest mój jquery-file-upload inicjator, który przesyła wszystkie zdjęcia w jednym żądaniu (tworzenie modelu pozycja), a następnie przekierowanie do katalogu głównego aplikacji (trzeba użyć formularz elementu):

<script type="text/javascript" charset="utf-8"> 
    var num_added = 0; 
    var added = 0; 
    var all_data = {}; 
    $(function() { 
     // Initialize the jQuery File Upload widget: 
     $('#fileupload').fileupload({ 
      complete: function (e, data) { 
      window.location = "<%= root_url %>"; 
     }, 
      singleFileUploads: false 
     }) .bind('fileuploadadd', function (e, data) {num_added++;}) 
      .bind('fileuploadsubmit', function (e, data) { 
      if(added < num_added) 
      { 
      if (added == 0) 
      all_data = data; 
      else 
      { 
      $.each(data['files'], function(i, file){ 
      all_data['files'].push(file); 
      }); 
      $.each(data['context'], function(i, context){ 
      all_data['context'].push(context); 
      }); 
      } 
      added++; 
      if (added == num_added) 
      { 
      added++; 
      all_data.submit(); 
      } 
      return false; 
      } 
      }) 
      .bind('fileuploadsend', function (e, data) {num_added = 0; added = 0;}); 

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

    }); 
    </script> 
+0

Należy odradzać [linki-odpowiedzi] (http://meta.stackoverflow.com/tags/link-only-answers/info), odpowiedzi SO powinny być punktem końcowym poszukiwanie rozwiązania (w przeciwieństwie do kolejnego zatrzymania referencji, które z czasem stają się nieaktualne). Proszę rozważyć dodanie samodzielnego streszczenia tutaj, zachowując odnośnik jako odniesienie. – kleopatra

Powiązane problemy