Uploading via a nested form and carrierwave doesn&

2019-06-27 16:54发布

问题:

I have a Profile model and Transcript model.

My Profile model looks like this:

class Profile < ActiveRecord::Base
  has_many :transcripts, dependent: :destroy
  accepts_nested_attributes_for :transcripts, allow_destroy: true
end

Transcript model looks like this:

class Transcript < ApplicationRecord
  belongs_to :profile
  mount_uploader :url, TranscriptUploader
end

This is my TranscriptUploader

class TranscriptUploader < CarrierWave::Uploader::Base
  storage :fog

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def content_type_whitelist
    "application/pdf"
  end

  def extension_whitelist
    %w(jpg jpeg gif png pdf)
  end    
end

I am using the Cocoon gem to handle the nested attributes for the form.

This is my profile/_form.html.erb:

<%= simple_form_for @profile, html: { class: "form-horizontal" } do |f| %>
  <%= f.error_notification %>

    <div id="transcripts" class="text-center">
      <%= f.simple_fields_for :transcripts do |transcript| %>
        <%= render 'transcript_fields', f: transcript %>
      <% end %>
      <div class="links">
        <%= link_to_add_association 'Add Transcript', f, :transcripts, class: "btn btn-success add-transcript-button" %>
      </div>
 <% end %>

Then this is the profile/_transcript_fields.html.erb partial:

<div class="nested-fields form-inline">
    <label class="col-lg-3 control-label">Document</label>
    <div class="col-lg-6">
      <%= f.file_field :url, class: 'col-lg-4 form-control' %>
      <%= f.input_field :url_cache, as: :hidden, class: 'form-control '%>
    </div>
      <%= link_to_remove_association f, class: 'pull-left' do %>
        <i class="fa fa-trash-o fa-lg"></i>
      <% end %>
</div>

And the params in my profiles_controller.rb looks like this:

Update Action

  def update    
    respond_to do |format|
      if @profile.update(profile_params)
        format.html { redirect_to @profile, notice: 'Profile was successfully updated.' }
        format.json { render :show, status: :ok, location: @profile }
      else
        format.html { redirect_to edit_profile_path(@profile), message: @profile.errors.messages }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end


def profile_params
  params.require(:profile).permit(:id, :first_name, :last_name, transcripts_attributes: [:id, :url, :name, :transcript, :remove_transcript, :transcript_cache, :_destroy])
end

This is what the log looks like after a 'successful' Profile#Update operation:

Started PATCH "/profiles/rebecca-nitzsche-st-george-s-college" for ::1 at 2016-10-20 11:27:13 -0500
Processing by ProfilesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"co0wAnec+xURD0Lw==", "profile"=>{"remove_avatar"=>"0", "avatar_cache"=>"", "first_name"=>"Rebecca", "last_name"=>"Nitzsche", "dob(3i)"=>"1", "dob(2i)"=>"10", "dob(1i)"=>"1998", "transcripts_attributes"=>{"0"=>{"url"=>#<ActionDispatch::Http::UploadedFile:0x007ff63fb9ae00 @tempfile=#<Tempfile:/var/folders/0f/hgplttnd7dg6q9m62qtbnpn00000gn/T/RackMultipart20161020-34279-42ou4z.pdf>, @original_filename="Analysis of Blackboard.pdf", @content_type="application/pdf", @headers="Content-Disposition: form-data; name=\"profile[transcripts_attributes][0][url]\"; filename=\"Analysis of Blackboard.pdf\"\r\nContent-Type: application/pdf\r\n">, "url_cache"=>"", "_destroy"=>"false", "id"=>"1"}, "1"=>{"url_cache"=>"", "_destroy"=>"false"}}      Profile Load (3.1ms)  SELECT  "profiles".* FROM "profiles" WHERE "profiles"."slug" = $1 ORDER BY "profiles"."id" ASC LIMIT $2  [["slug", "rebecca-nitzsche-st-george-s-college"], ["LIMIT", 1]]
  Grade Load (1.6ms)  SELECT "grades".* FROM "grades" WHERE "grades"."profile_id" = 7
  HABTM_Positions Load (1.7ms)  SELECT "positions_profiles".* FROM "positions_profiles" WHERE "positions_profiles"."profile_id" = 7
  Achievement Load (1.3ms)  SELECT "achievements".* FROM "achievements" WHERE "achievements"."profile_id" = 7
  Video Load (1.5ms)  SELECT "videos".* FROM "videos" WHERE "videos"."profile_id" = 7
  Transcript Load (1.3ms)  SELECT "transcripts".* FROM "transcripts" WHERE "transcripts"."profile_id" = 7
Unpermitted parameter: url_cache
Unpermitted parameter: url_cache
Unpermitted parameter: url_cache
Unpermitted parameter: url_cache
   (0.9ms)  BEGIN
  Position Load (1.3ms)  SELECT "positions".* FROM "positions" WHERE 1=0
  SQL (6.1ms)  UPDATE "profiles" SET "updated_at" = $1, "avatar" = $2 WHERE "profiles"."id" = $3  [["updated_at", 2016-10-20 16:27:13 UTC], ["avatar", "Akeem_Robotham.jpg"], ["id", 7]]
  SQL (3.4ms)  UPDATE "transcripts" SET "url" = $1, "updated_at" = $2 WHERE "transcripts"."id" = $3  [["url", "Analysis_of_Blackboard.pdf"], ["updated_at", 2016-10-20 16:27:13 UTC], ["id", 1]]
  SQL (5.2ms)  INSERT INTO "transcripts" ("profile_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["profile_id", 7], ["created_at", 2016-10-20 16:27:14 UTC], ["updated_at", 2016-10-20 16:27:14 UTC]]
   (93.4ms)  COMMIT
Redirected to http://localhost:3000/profiles/rebecca-nitzsche-st-george-s-college
Completed 302 Found in 1030ms (ActiveRecord: 120.7ms)

This is what the record looks like:

[30] pry(main)> t
=> #<Transcript:0x007f8d62d611f8 id: 1, profile_id: 7, url: "Analysis_of_Blackboard.pdf", name: nil, created_at: Thu, 20 Oct 2016 16:03:29 UTC +00:00, updated_at: Thu, 20 Oct 2016 16:27:13 UTC +00:00>

Edit 1

So the issue is that I am unable to properly access the mounted objected, per typical Carrierwave instructions.

Here is an example:

[42] pry(main)> t
=> #<Transcript:0x007f8d62d611f8 id: 1, profile_id: 7, url: "Analysis_of_Blackboard.pdf", name: nil, created_at: Thu, 20 Oct 2016 16:03:29 UTC +00:00, updated_at: Thu, 20 Oct 2016 16:27:13 UTC +00:00>
[43] pry(main)> t.url
=> "Analysis_of_Blackboard.pdf"
[44] pry(main)> t.url.url
NoMethodError: undefined method `url' for "Analysis_of_Blackboard.pdf":String
from (pry):44:in `__pry__'
[45] pry(main)> t.transcript
=> #<TranscriptUploader:0x007f8d5fdf3f38
 @model=
  #<Transcript:0x007f8d62d611f8
   id: 1,
   profile_id: 7,
   url: "Analysis_of_Blackboard.pdf",
   name: nil,
   created_at: Thu, 20 Oct 2016 16:03:29 UTC +00:00,
   updated_at: Thu, 20 Oct 2016 16:27:13 UTC +00:00>,
 @mounted_as=:transcript>
[46] pry(main)> t.transcript.url
=> nil
[47] pry(main)> t.transcript_identifier
=> nil
[48] pry(main)> t.transcript.identifier
=> nil
[49] pry(main)> t.transcript.current_path
=> nil
[50] pry(main)> t.identifier
NoMethodError: undefined method `identifier' for #<Transcript:0x007f8d62d611f8>
from .rvm/gems/ruby-2.3.1@myapp-rails-5.0/gems/activemodel-5.0.0.1/lib/active_model/attribute_methods.rb:433:in `method_missing'
[51] pry(main)> t.current_path
NoMethodError: undefined method `current_path' for #<Transcript:0x007f8d62d611f8>
from /.rvm/gems/ruby-2.3.1@myapp-rails-5.0/gems/activemodel-5.0.0.1/lib/active_model/attribute_methods.rb:433:in `method_missing'