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'