Upload doesn't work using Carrierwave in Rails 5 - ruby-on-rails

So I was working on my app and trying to put on an uploader feature.
First I generated a course uploader and allowed jpeg, jpg, png and gif.
Next I've added the ff code mount on my course model:
mount_uploader :thumb_image, CoursesUploader
mount_uploader :main_image, CoursesUploader
Next, I place the file upload form code on my new.html.erb file:
<div class="field">
<%= f.file_field :main_image %>
</div>
<div class="field">
<%= f.file_field :thumb_image %>
</div>
And when I tried to submit my form with my images uploaded it did not even show the index page instead I refresh the page and then see if it got uploaded and the form was submitted successfully but it did not.
I also look at the strong params on my controller and these two items are there:
# Never trust parameters from the scary internet, only allow the white list through.
def course_params
params.require(:course).permit(:title, :price, :body, :main_image, :thumb_image)
end
Any idea what am I missing here?
Here's something I got from my terminal after submission:
Started POST "/courses" for 127.0.0.1 at 2019-01-16 20:52:20 +0800
Processing by CoursesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wlKpv8czsuC6AZjCctxYk203wry4cb0dnOYI9IoAkzRZNV2vB4/vREU5L5u4G7vh5ZhCbHZlJ6nHPN95qO+cbA==", "course"=>{"title"=>"Goody", "price"=>"33", "main_image"=>#<ActionDispatch::Http::UploadedFile:0x007f81e52eed48 #tempfile=#<Tempfile:/var/folders/3_/8bmsd3j13bxfdl1jp7gzvvsm0000gn/T/RackMultipart20190116-2359-17w6pb.jpg>, #original_filename="61230.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"course[main_image]\"; filename=\"61230.jpg\"\r\nContent-Type: image/jpeg\r\n">, "thumb_image"=>#<ActionDispatch::Http::UploadedFile:0x007f81e52eecd0 #tempfile=#<Tempfile:/var/folders/3_/8bmsd3j13bxfdl1jp7gzvvsm0000gn/T/RackMultipart20190116-2359-2mcy4i.jpg>, #original_filename="61230.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"course[thumb_image]\"; filename=\"61230.jpg\"\r\nContent-Type: image/jpeg\r\n">, "body"=>""}, "commit"=>"Create Course"}
(0.5ms) BEGIN
↳ app/controllers/courses_controller.rb:27
Course Exists (1.5ms) SELECT 1 AS one FROM "courses" WHERE "courses"."id" IS NOT NULL AND "courses"."slug" = $1 LIMIT $2 [["slug", "goody"], ["LIMIT", 1]]
↳ app/controllers/courses_controller.rb:27
(0.6ms) ROLLBACK
↳ app/controllers/courses_controller.rb:27
Rendering courses/new.html.erb within layouts/application
Rendered courses/new.html.erb within layouts/application (12.6ms)
Rendered shared/_application_nav.html.erb (6.2ms)
Rendered shared/_application_footer.html.erb (1.3ms)
Completed 200 OK in 394ms (Views: 356.6ms | ActiveRecord: 2.6ms)
UPDATE: FULL MODEL CONTENT
class Course < ApplicationRecord
include DefaultsConcern
enum status: { draft: 0, published: 1 }
validates_presence_of :title, :price, :body, :main_image, :thumb_image
mount_uploader :thumb_image, CoursesUploader
mount_uploader :main_image, CoursesUploader
extend FriendlyId
friendly_id :title, use: :slugged
end
FULL FORM CONTENT:
<h1>New Form</h1>
<%= form_for(#course) do |f| %>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :price %>
<%= f.number_field :price %>
</div>
<div class="field">
<%= f.file_field :main_image %>
</div>
<div class="field">
<%= f.file_field :thumb_image %>
</div>
<div class="field">
<%= f.label :body %>
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

Validation failed as params[:course][:body] is nil due to which creating course rolled back
validates_presence_of :title, :price, :body, :main_image, :thumb_image
=> So just fillup body field in form or remove validates_presence_of :body

I can see the Image is ActionDispatch already but are you sure you created your table column like this -Regardless of creating table or adding_column-
I'm focusing on
:string, array: true, default: []
Migration should look like:
add_column :courses, :main_image, :string, array: true, default: []
As creating the column as String won't let carrierwave add it's object as an array inside it, so it should be an array
Also you can set thumb and main images in one uploader if you are going to change the size only, otherwise you're fine to use :thumb_image and :main_image but make sure the migration is correct
If you can't change it, just drop and re-create it

Related

Unknown parameter in Rails 5.1 strong parameters issue

So my reconciliation model looks like this:
class Reconciliation < ApplicationRecord
belongs_to :location
belongs_to :company
has_and_belongs_to_many :inventory_items
accepts_nested_attributes_for :inventory_items, allow_destroy: true
end
My InventoryItem model looks like this:
class InventoryItem < ApplicationRecord
belongs_to :product
belongs_to :location, inverse_of: :inventory_items
has_and_belongs_to_many :reconciliations
end
In my ReconciliationsController, this is what my reconciliation_params looks like:
def new
#location = Location.find(params[:location_id])
#reconciliation = #location.reconciliations.new
#inventory_items = #location.inventory_items
#start_index = 0
#next_index = #start_index + 1
end
def reconciliation_params
params.require(:reconciliation).permit(:inventory_item_id, :location_id, :display_id, :inventory_items,
inventory_items_attributes: [:id, :quantity_left, :quantity_delivered, :_destroy]
)
end
This is the relevant section of my routes.rb:
resources :locations, shallow: true do
resources :inventory_items
resources :reconciliations
end
This is my views/reconciliations/_form.html.erb:
<%= simple_form_for #reconciliation, url: :location_reconciliations do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :location_id, as: :hidden %>
<%= f.simple_fields_for :inventory_item do |inventory| %>
<%= inventory.input :quantity_left %>
<%= inventory.input :quantity_delivered %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit, "Update", class: "btn btn-primary" %>
</div>
<% end %>
This is my app/views/reconciliations/new.html.erb:
<% if params[:next].nil? %>
<%= render 'form', reconciliation: #reconciliation, inventory_item: #inventory_items[#start_index] %>
<% else %>
<%= render 'form', reconciliation: #reconciliation, inventory_item: #inventory_items[#next_index] %>
<% end %>
This is my log when I try to create a reconciliation object:
Started POST "/locations/2/reconciliations" for 127.0.0.1 at 2018-03-24 23:16:33 -0500
Processing by ReconciliationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JZvhwloo0+XM9bmptxXGfnDw==", "reconciliation"=>{"location_id"=>"2", "inventory_item"=>{"quantity_left"=>"1", "quantity_delivered"=>"170"}}, "commit"=>"Update", "location_id"=>"2"}
Unpermitted parameter: :inventory_item
Location Load (0.9ms) SELECT "locations".* FROM "locations" WHERE "locations"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
(0.6ms) BEGIN
(0.7ms) ROLLBACK
Rendering reconciliations/new.html.erb within layouts/application
InventoryItem Load (1.0ms) SELECT "inventory_items".* FROM "inventory_items" WHERE "inventory_items"."location_id" = $1 [["location_id", 2]]
Product Load (1.0ms) SELECT "products".* FROM "products" WHERE "products"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
Rendered reconciliations/_form.html.erb (45.9ms)
Rendered reconciliations/new.html.erb within layouts/application (66.8ms)
Rendered shared/_navbar.html.erb (1.3ms)
Completed 200 OK in 202ms (Views: 115.1ms | ActiveRecord: 29.1ms)
I have tried simply adding :inventory_item to my params.require(:reconciliation).permit(..), but that doesn't work.
What am I missing?
Edit 1
When I checked the HTML for the inputs on my form, within the simple_fields_for, the HTML seems to be fine:
<input class="string required" type="text" name="reconciliation[inventory_item][quantity_left]" id="reconciliation_inventory_item_quantity_left">
Edit 2
When I change the simple_fields_for call to be plural, i.e. :inventory_items, rather than :inventory_item like this:
That entire portion of the form disappears altogether.
This is what the HTML looks like:
<div class="form-inputs">
<div class="input hidden reconciliation_location_id"><input class="hidden" type="hidden" value="2" name="reconciliation[location_id]" id="reconciliation_location_id"></div>
</div>
This is how the HTML looks when that simple_field_for :inventory_item is singular:
<div class="form-inputs">
<div class="input hidden reconciliation_location_id"><input class="hidden" type="hidden" value="2" name="reconciliation[location_id]" id="reconciliation_location_id"></div>
<div class="input string required reconciliation_inventory_item_quantity_left"><label class="string required" for="reconciliation_inventory_item_quantity_left"><abbr title="required">*</abbr> Quantity left</label><input class="string required" type="text" name="reconciliation[inventory_item][quantity_left]" id="reconciliation_inventory_item_quantity_left"></div>
<div class="input string required reconciliation_inventory_item_quantity_delivered"><label class="string required" for="reconciliation_inventory_item_quantity_delivered"><abbr title="required">*</abbr> Quantity delivered</label><input class="string required" type="text" name="reconciliation[inventory_item][quantity_delivered]" id="reconciliation_inventory_item_quantity_delivered"></div>
</div>
I have tried simply adding :inventory_item to my params.require(:reconciliation).permit(..), but that doesn't work.
If you want permit inventory_item, you must specify its structure, because it is not a simple field, but a hash:
def reconciliation_params
params.require(:reconciliation).permit(:location_id, :display_id, inventory_item: [:id, :quantity_left, :quantity_delivered] )
end
By looking at your log, you are not passing the inventory_item_id, which might be needed to update this specific item:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JZvhwloo0+XM9bmptxXGfnDw==",
"reconciliation"=>{"location_id"=>"2", "inventory_item"=>
{"quantity_left"=>"1", "quantity_delivered"=>"170"}},
"commit"=>"Update", "location_id"=>"2"}
You could add it as a hidden field in the nested form.
Form of association should be plural f.simple_fields_for :inventory_items.
You should initialize a new inventory_item object in the new controller's action
def new
#reconciliation = Reconciliation.new
# you can create as many new items as you want
#reconciliation.inventory_items.build
end
If you want to dynamically add items to the form i advise you to use https://github.com/nathanvda/cocoon
BUT it looks like you want to add existing inventory_item to a new reconciliation, you better use has_many through assocations http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many
Its easier to add a join model objects with neccessary fields and associations.
Another advise: do not send local variable to partial if you are using instance variable in this partial
# render partial
render 'form', reconciliation: #reconciliation
# partial with form for local variable
simple_form_for reconciliation
and i think your form partial will not work for the edit action because of hardcoded url, you can pass url in a variable:
# new html
render 'form', reconciliation: #reconciliation, url_var: location_reconciliations(#location)
# edit
render 'form', reconciliation: #reconciliation, url_var: reconciliations(#reconciliation)
# form
simple_form_for reconciliation, url: url_var

Rails 4 nested attribute hash keys showing as unpermitted

I have a Category model and a Standard model. A category has many standards through a "join table" model CategoryStandard. In my view, I have a form where I can edit the category description, and then add or remove standards from that category. So, my nested attributes are for :category_standards, because I'm not editing the standard itself, just adding or removing relationships, if that makes sense.
Here's the important part of the view:
<%= form_for(#category) do |f| %>
...
<div class="field">
<%= f.label :description %>
<%= f.text_field :description %>
</div>
<%= label_tag nil, "Standards in this Category" %>
<div id="standard-list">
<%= f.fields_for :category_standards do |ff| %>
<div class="field">
<%= ff.object.standard.number_with_exceptions %>
<%= ff.hidden_field :standard_id %>
<%= ff.hidden_field :_destroy %>
<%= link_to "<span class='glyphicon glyphicon-remove'></span>".html_safe, "", class: "del-std-btn", title: "Remove standard from category" %>
</div>
<% end %>
<div class="hidden" id="std-add-new-template">
<div class="field">
<%= f.fields_for :category_standards, CategoryStandard.new, child_index: "new_id" do |ff| %>
<%= ff.collection_select :standard_id, #standards - #category.standards, :id, :number_with_exceptions, prompt: "Select a standard to add" %>
<% end %>
</div>
</div>
</div>
...
<% end %>
There's some jQuery under the hood to manipulate the "rows", but that works fine and I don't think it's part of my problem, so I'll omit it.
In my Category model, I have:
class Category < ActiveRecord::Base
has_many :category_standards, dependent: :destroy
has_many :standards, through: :category_standards
validates :description, presence: true,
uniqueness: true
accepts_nested_attributes_for :category_standards, allow_destroy: true, reject_if: proc { |attributes| attributes['standard_id'].blank?}
end
And in my Categories controller, I have:
def category_params
params.require(:category).permit(:description, category_standards_attributes: [:id, :standard_id, :_destroy])
end
But when I try to add a standard to a category, I get these lines in my server log (reformatted in the hopes of making it more readable):
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"***********",
"category"=>{
"description"=>"Drinking Water System Components",
"category_standards_attributes"=>{
"0"=>{
"standard_id"=>"2",
"_destroy"=>"false",
"id"=>"1"
},
"new_id"=>{
"standard_id"=>""
},
"1424899001814"=>{
"standard_id"=>"1"
}
}
},
"commit"=>"Save Changes",
"id"=>"2"
}
User Load (5.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Category Load (4.0ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" = $1 LIMIT 1 [["id", "2"]]
Unpermitted parameters: 0, new_id, 1424899001814
(4.0ms) BEGIN
Category Exists (6.0ms) SELECT 1 AS one FROM "categories" WHERE ("categories"."description" = 'Drinking Water System Components' AND "categories"."id" != 2) LIMIT 1
SQL (6.0ms) UPDATE "categories" SET "description" = $1, "updated_at" = $2 WHERE "categories"."id" = 2 [["description", "Drinking Water System Components"], ["updated_at", Wed, 25 Feb 2015 21:16:44 UTC +00:00]]
It updates the description field just fine, but what's up with the Unpermitted parameters? My attributes hash comes out just like the example in the Rails Guide on nested forms, and it even says "The keys of the :addresses_attributes hash are unimportant, they need merely be different for each address." And yet it's the keys that are getting denied for me.
Where have I gone wrong? Thanks!
Figured it out, after a lot of reading. The missing piece was here.
Hashes with integer keys are treated differently and you can declare the attributes as if they were direct children. You get these kinds of parameters when you use accepts_nested_attributes_for in combination with a has_many association:
# To whitelist the following data:
# {"book" => {"title" => "Some Book",
# "chapters_attributes" => { "1" => {"title" => "First Chapter"},
# "2" => {"title" => "Second Chapter"}}}}
params.require(:book).permit(:title, chapters_attributes: [:title])
The important part of that was "Hashes with integer keys". My hash keys were passing as "0", "new_id", "1240934304343". It isn't important that I use "new_id", because that's just a placeholder value that gets changed in my jQuery when new rows are added. Only the template row retains that value, which is fine, because it gets filtered out by my reject_if clause.
But the fact that "new_id" isn't an integer apparently was the thing that was mucking it all up. So I changed it to "-1", which Rails accepts (even though it is still filtered out by reject_if, as it should be).
<div class="hidden" id="std-add-new-template">
<div class="field">
<%= f.fields_for :category_standards, CategoryStandard.new, child_index: "-1" do |ff| %>
<%= ff.collection_select :standard_id, #standards - #category.standards, :id, :number_with_exceptions, prompt: "Select a standard to add" %>
<% end %>
</div>
</div>
Your attribute keys don't seem to match what you are expecting in your strong parameters, "new_id" and "1424899001814" certainly will not be permitted.
"new_id"=>{
"standard_id"=>""
},
"1424899001814"=>{
"standard_id"=>"1"
}
I suspect the way you are constructing your form is invalid. Try breaking it down to the simplest working form.. like:
<div id="standard-list">
<%= link_to "<span class='glyphicon glyphicon-remove'></span>".html_safe, "", class: "del-std-btn", title: "Remove standard from category" %>
<div class="hidden" id="std-add-new-template">
<div class="field">
<%= f.fields_for :category_standards do |ff| %>
<%= ff.object.standard.number_with_exceptions %>
<%= ff.hidden_field :standard_id %>
<%= ff.hidden_field :_destroy %>
<%= ff.collection_select :standard_id, #standards - #category.standards, :id, :number_with_exceptions, prompt: "Select a standard to add" %>
<% end %>
</div>
</div>
</div>
The intention is to have only one nested form, and by stripping it down create only one nested hash.
"category_standards_attributes"=>{
"0"=>{
"standard_id"=>"2",
"_destroy"=>"false",
"id"=>"1"
}
}
What happens with this?

Ruby Index and Show views are showing no data

I'm new to Ruby, and I'm developing my own app in Nitrous.
When I complete a form on my new.html.erb, and hit save, the show view loads. The page renders with HTML headers as expected, but no data fields from my model. I have also tried the index view, but there is no data being saved, I think.
I have generated a model called income, and run rake db:migrate successfully, wiht the right tables set up. I'm stumped as to what the problem is.
Any ideas gratefully received.
This is my controller: incomes_controller.rb
class IncomesController < ApplicationController
def index
#incomes = Income.all
end
def new
#income = Income.new
end
def create
#income = Income.new(income_params)
if #income.save
redirect_to(:action => 'show', :id => #income.id)
end
end
def show
#income = Income.find(params[:id])
end
private
def income_params
params.require(:income).permit(:first_name, :last_name, :date_of_birth, :income1, :income2, :income3, :income4, :income5, :income6, :income7, :income8, :income9, :income10)
end
end
My form in new.html.erb, is:
<%= simple_form_for #income do |f| %>
<%= f.input :first_name, label: 'First Name' %>
<%= f.input :last_name, label: 'Last Name' %>
<%= f.input :date_of_birth, label: 'Date of Birth', hint: 'dd/mm/yyyy' %>
<p>Income: Salary or Wages</p>
<%= f.input :income1, label: 'Take home salary or Wage' %>
<%= f.input :income2, label: 'Partner\'s salary or wage' %>
<%= f.input :income3, label: 'Other income from salary or wages' %>
<p>Other Income</p>
<%= f.input :income4, label: 'Maintanence or child support' %>
<%= f.input :income5, label: 'Boarders or lodgers' %>
<%= f.input :income6, label: 'Non-dependent contributions' %>
<%= f.input :income7, label: 'Student loands or grants' %>
<%= f.input :income7, label: 'Other' %>
<p>Benefits </p>
<%= f.input :income8, label: 'Sample input' %>
<%= f.input :income9, label: 'Sample input' %>
<%= f.input :income10, label: 'More sample inputs' %>
<%= f.button :submit, "Save and Proceed" %>
<h3>You will have a chance to review your form before you submit it. Once you click Save, you can come back and complete the rest of the form at a later date</h3>
<% end %>
And my show.html.erb file is:
<p>
<strong>First name:</strong>
<%= #income.first_name %>
</p>
<p>
<strong>Last name:</strong>
<%= #income.last_name %>
</p>
<p>
<strong>Date of Birth:</strong>
<%= #income.date_of_birth %>
</p>
<p>
<strong>Take home salary or Wage:</strong>
<%= #income.income1 %>
</p>
My model income.rb is:
class Income < ActiveRecord::Base
attr_accessor :first_name, :last_name, :date_of_birth, :income1, :income2, :income3, :income4, :income5, :income6, :income7, :income8, :income9, :income10
end
Development log output....
Processing by IncomesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"D4F40TAMcVsb7RbdUZwxXfsgGn1u/iD7R+DWvAwrtJ1q83mgequQbkyKPaheFjsLSZHlMBpDy+H7Rm+HdVeTFw==", "income"=>{"first_name"=>"Barak", "last_name"=>"Obama", "date_of_birth"=>"02/07/1990", "income1"=>"12345", "income2"=>"12345", "income3"=>"", "income4"=>"", "income5"=>"", "income6"=>"", "income7"=>"", "income8"=>"", "income9"=>"", "income10"=>""}, "commit"=>"Save and Proceed"}
[1m[35m (0.1ms)[0m begin transaction
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "incomes" ("created_at", "updated_at") VALUES (?, ?)[0m [["created_at", "2015-02-19 17:39:54.471034"], ["updated_at", "2015-02-19 17:39:54.471034"]]
[1m[35m (32.8ms)[0m commit transaction
Redirected to http://o-bot-laboratory-190030.euw1.nitrousbox.com/incomes/42
Started GET "/incomes/42" for 88.215.13.57 at 2015-02-19 17:39:54 +0000
Processing by IncomesController#show as HTML
Parameters: {"id"=>"42"}
[1m[36mIncome Load (0.3ms)[0m [1mSELECT "incomes".* FROM "incomes" WHERE "incomes"."id" = ? LIMIT 1[0m [["id", 42]]
Rendered incomes/show.html.erb within layouts/application (0.8ms)
Completed 200 OK in 94ms (Views: 75.6ms | ActiveRecord: 0.3ms)
Routes as requested....
Rails.application.routes.draw do
resources :incomes
root 'incomes#new'
end
Thanks to #RailsOuter and #jyrkim for your help. I found that the problem was indeed with my model file, and migration file.
I needed to remove the line attr_accessor from my model. I have since discovered that I must have modified my migration file to add columns, instead of generating a new migration. Now I have generated the new migration with the data columns, my data is showing!
Thanks again, very appreciative of your input to help out a newbie!

Update method not updating table using rails 4

I am having difficulty translating the Headfirst into Rails book which is based on Rails 2 into Rails 4 which is set up on my machine.
The exercise is trying to retrieve a record from a database and then, once edited, update the table.
I have tried many different ways and my current configuration is as follows - this will present the record for editing but will not actually update the record! (Infuriating!)
NB - I am not using 'strong_parameters' nor 'protected_attributes' - I did try this but was getting stack to deep and other errors.
My ad model is also empty - I have removed the att_accessible entries that I tried with the protected attributes gem.
Here is my - ad controller entry:
def update
#ad = Ad.find(params[:id])
#ad.update_attributes(update_params[:id])
redirect_to "/ads/#{#ad.id}"
end
private
def update_params
params.permit(:name, :description, :price, :seller_id, :email, :ad, :img_url)
end
end
EDIT VIEW:
<h1>Editing <%= #ad.name %></h1>
<%= form_for(#ad,:url=>{:action=>'update'}) do |f| %>
<p><b>Name</b><br /><%= f.text_field :name %></p>
<p><b>Description</b><br /><%= f.text_area :description %></p>
<p><b>Price</b><br /><%= f.text_field :price %></p>
<p><b>Seller</b><br /><%= f.text_field :seller_id %></p>
<p><b>Email</b><br /><%= f.text_field :email %></p>
<p><b>Img Url</b><br /><%= f.text_field :img_url %></p>
<p><%= f.submit "update" %></p>
<% end %>
Log Entry on Update:
Started PATCH "/ads/1/update" for 127.0.0.1 at 2013-08-13 22:35:51 +0100
Processing by AdsController#update as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"O4cN72FXCCkfkL7M6bozodbB0Aqor
NctOOV5sfXdado=", "ad"=>{"name"=>"Typewriter", "description"=>"Old manual typewr
iter. Many years useful service. Works best with a bottle next to it.", "price"=
>"71.95", "seller_id"=>"54", "email"=>"dhammett#email.com1", "img_url"=>"http://
homepage.mac.com/david_griffiths/typewriter.png"}, "commit"=>"update", "id"=>"1"
}
←[1m←[35mAd Load (1.0ms)←[0m SELECT "ads".* FROM "ads" WHERE "ads"."id" = ? L
IMIT 1 [["id", "1"]]
Unpermitted parameters: utf8, _method, authenticity_token, ad, commit, id
←[1m←[36m (0.0ms)←[0m ←[1mbegin transaction←[0m
←[1m←[35m (0.0ms)←[0m commit transaction
Redirected to http://localhost:3000/ads/1
Completed 302 Found in 54ms (ActiveRecord: 1.0ms)

Uploading multiple files with paperclip

I am having problems uploading multiple files using paper clip,
my models are as such
slider has_many imgarrays
imgarrays has_many imageobjects
imageobjects have_attachment(as for paperclip)
I have no problems receiving a single image and saving it using paperclip on my other models, but i am not sure of how to handle the array returned by imgarrays param during a multiple file upload.
Here is my rails server logs:
Started POST "/slider" for 127.0.0.1 at 2012-07-23 10:14:17 +0800
Processing by SliderController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"7HcHtSlOsU/bnxb9emhAsSl/GFBraIE6NxwijHl3REM=", "slider"=>{"question"=>"", "answer"=>"", "score"=>"", "industry_name"=>"",
"imgarrays"=>[#<ActionDispatch::Http::UploadedFile:0x007fb471e99f30 #original_filename="Icon.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"slider[imgarrays][]\"; filename=\"Icon.png\"\r\nContent-Type: image/png\r\n", #tempfile=#<File:/var/folders/2s/n9wb5x4534nfs1cbrlph32v00000gp/T/RackMultipart20120723-53499-1lyi4yf>>, #<ActionDispatch::Http::UploadedFile:0x007fb471e99dc8 #original_filename="Icon#2x.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"slider[imgarrays][]\"; filename=\"Icon#2x.png\"\r\nContent-Type: image/png\r\n", #tempfile=#<File:/var/folders/2s/n9wb5x4534nfs1cbrlph32v00000gp/T/RackMultipart20120723-53499-10lala2>>, #<ActionDispatch::Http::UploadedFile:0x007fb471e99d50 #original_filename="greenButton.png", #content_type="image/png", #headers="Content-Disposition: form-data; name=\"slider[imgarrays][]\"; filename=\"greenButton.png\"\r\nContent-Type: image/png\r\n", #tempfile=#<File:/var/folders/2s/n9wb5x4534nfs1cbrlph32v00000gp/T/RackMultipart20120723-53499-or2rdk>>]}, "commit"=>"Create!"}
Completed 500 Internal Server Error in 18ms
ActiveRecord::AssociationTypeMismatch (Imgarray(#70206507050500) expected, got ActionDispatch::Http::UploadedFile(#70206487229960)):
app/controllers/slider_controller.rb:12:in `new'
app/controllers/slider_controller.rb:12:in `create'
Rendered /Users/Kinnovate/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.4ms)
Rendered /Users/Kinnovate/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.4ms)
Rendered /Users/Kinnovate/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.1.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (6.5ms)
new.html.erb for slider
<div>
<%= form_for #slider ,:url=>"/slider" , :html => { :multipart => true } do |f| %>
<%= f.label :question , "question"%>
<%= f.text_field :question %> </br>
<%= f.label :answer , "answer array (comma seperated)"%>
<%= f.text_field :answer %> </br>
<%= f.label :score , "score"%>
<%= f.text_field :score %> </br>
<%= f.label :industry_name , "industry"%>
<%= f.text_field :industry_name %> </br>
<%= f.label :attachedimg , "image"%>
<%= f.file_field :imgarrays, :multiple =>:true %> </br>
<%= f.submit "Create", class: "btn btn-large btn-primary" %>
<% end %>
</div>
<%= link_to 'Cancel', slider_index_path %>
Here is my code that worked well to upload multiple file using paperclip:
We can achieve using nested attributes or using normal easy method.
The following code shows normal method:
User.rb
has_many :images, :dependent => :destroy
Image.rb
has_attached_file :avatar, :styles => { :medium => "300x300>" }
belongs_to :user
users/views/new.html.erb
<%= form_for #user, :html => { :multipart => true } do |f| %>
......
....
<%= file_field_tag :avatar, multiple: true %>
<% end %>
Users_controller:
.....
if #user.save
# params[:avatar] will be an array.
# you can check total number of photos selected using params[:avatar].count
params[:avatar].each do |picture|
#user.images.create(:avatar=> picture)
# Don't forget to mention :avatar(field name)
end
end
Thats it. images got uploaded, this may not be the good way but it works.

Resources