How can I upload multiple images using CarrierWave?
I followed "drjorgepolanco" answer from
Rails 4 multiple image or file upload using carrierwave
but I keep getting a error
undefined method `[]' for #<AssignmentpicUploader:0x007eff7831a4d8>
Extracted source (around line #25):
ActionView::Template::Error (undefined method `[]' for #<AssignmentpicUploader:0x007eff7831a4d8>):
22:
23:
24: <div id="img">
25: <%= image_tag #assignment.picture[1].url(:large) %>
26: </div>
27:
28: </br>
app/views/assignments/show.html.erb:25
assignment.rb
class Assignment < ActiveRecord::Base
validates :name, length: { minimum: 1, maximum:120 }
validates :description, length: { minimum: 1 }
mount_uploader :picture, AssignmentpicUploader
end
assignments_controller.rb
class AssignmentsController < ApplicationController
before_action :authenticate_user!
before_filter :admin_access, only: [:new, :create, :edit, :update, :destroy]
def index
#assignments = Assignment.all.order("created_at DESC")
end
def show
#assignment = Assignment.find(params[:id])
end
def new
#assignment = Assignment.new
end
def create
#assignment = current_user.assignments.build
#assignment.name = params[:assignment][:name]
#assignment.description = params[:assignment][:description]
#assignment.picture = params[:assignment][:picture]
if #assignment.save
flash[:notice] = "Assignment was saved successfully."
redirect_to #assignment
else
flash.now[:alert] = "Error creating assignment. Please make sure there is a name and description."
render :new
end
end
def edit
#assignment = Assignment.find(params[:id])
end
def update
#assignment = Assignment.find(params[:id])
#assignment.name = params[:assignment][:name]
#assignment.description = params[:assignment][:description]
#assignment.picture = params[:assignment][:picture]
if #assignment.save
flash[:notice] = "Assignment was updated successfully."
redirect_to #assignment
else
flash.now[:alert] = "Error saving assignment. Please try again."
render :edit
end
end
def destroy
#assignment = Assignment.find(params[:id])
if #assignment.destroy
flash[:notice] = "\"#{#assignment.name}\" was deleted successfully."
redirect_to action: :index
else
flash.now[:alert] = "There was an error deleting the assignment."
render :show
end
end
private
def assignment_params
params.require(:assignment).permit(:name, :description, picture: [])
end
end
assignments/new.html.erb
...
<div class="col-md-8">
<%= form_for #assignment, :html => { :multipart => true } do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', placeholder: "Enter assignment name" %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, rows: 8, class: 'form-control', placeholder: "Enter assignment description" %>
</div>
<div class="form-group">
<%= f.label :picture %>
<%= f.file_field :picture, :multiple => true %>
</div>
<br />
<%= f.submit "Save", class: 'button' %>
<% end %>
</div>
</div>
assignments/show.html.erb
<%= image_tag #assignment.picture[1].url(:large) %>
schema.rb
create_table "assignments", force: :cascade do |t|
t.string "name"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "picture"
end
add_index "assignments", ["user_id"], name: "index_assignments_on_user_id"
Carrierwave documentation says:
Add a column which can store an array. This could be an array column or a JSON column for example. Your choice depends on what your database supports.
Your "picture" is just a string. Add serialize :picture, JSON to your model.
Related
I have a model where students can enter information about themselves and others can view them. Since there are a lot of profiles, I have added a search section too. If they want only CS majors, they can select from a drop down. I had things like major, college... today I added "level", which is level of education and I get an error (Error shown at the end). I know this is long, but any help would be really really useful. Thanks!
(Userinfo is the student model)
My controller looks like this:
class UserinfosController < ApplicationController
before_action :find_userinfo, only: [:show, :edit, :update, :destroy, :log_impression]
def index
#userinfors = Userinfo.search(params[:search])
#search = Search.new
#college = Userinfo.uniq.pluck(:college)
#major = Userinfo.uniq.pluck(:major)
#level = Userinfo.uniq.pluck(:level)
end
def show
end
def new
#userinformation = current_user.build_userinfo
end
def create
#userinformation = current_user.build_userinfo(userinfo_params)
if #userinformation.save
redirect_to userinfo_path(#userinformation)
else
render 'new'
end
end
def edit
end
def update
if #userinformation.update(userinfo_params)
redirect_to userinfo_path(#userinformation)
else
render 'edit'
end
end
def destroy
#userinformation.destroy
redirect_to root_path
end
private
def userinfo_params
params.require(:userinfo).permit(:name, :email, :college, :gpa, :major, :token, :skills, :level)
end
def find_userinfo
#userinformation = Userinfo.friendly.find(params[:id])
end
end
My information fill out form (please note how the way of input is different in major and level of edu, maybe thats the problem?):
<%= simple_form_for #userinformation, :html => { :multipart => true } do |f| %>
<%= f.input :name, required: true, label: 'Full name' %>
<%= f.input :college, required: true, label: 'Name of college' %>
<%= f.input :gpa, required: true, label: 'Enter GPA' %>
<%= f.input :email, required: true, label: 'Enter email address' %>
<%= f.input :major, required: true, label: 'Major' %>
<%= f.input :level, collection: ["College undergrad", "College grad"], required: true, label: 'Level of education' %>
<%= f.input :skills, required: true, label: 'Skills' %>
<%= f.button :submit, 'Create account' %>
<% end %>
Search controller:
class SearchesController < ApplicationController
def new
#search = Search.new
#college = Userinfo.uniq.pluck(:college)
#major = Userinfo.uniq.pluck(:major)
#level = Userinfo.uniq.pluck(:level)
end
def create
#search = Search.create(search_params)
redirect_to #search
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit(:keyword, :college, :min_gpa, :major, :token, :level )
end
end
Search model:
class Search < ActiveRecord::Base
def search_userinfos
userinfos = Userinfo.all
userinfos = userinfos.where(["name LIKE ?","%#{keyword}%"]) if keyword.present?
userinfos = userinfos.where(["college LIKE ?", college]) if college.present?
userinfos = userinfos.where(["cast(gpa as numeric) >= ?", min_gpa]) if min_gpa.present?
userinfos = userinfos.where(["major LIKE ?", major]) if major.present?
userinfos = userinfos.where(["level LIKE ?", level]) if level.present?
userinfos = userinfos.order("gpa")
return userinfos
end
end
This is where the search section is displayed (index view):
<%= simple_form_for #search do |s| %>
<%= s.input :keyword, label: 'Name' %>
<label>College</label>
<%= s.select :college, options_for_select(#college), :include_blank => true %>
<%= s.input :min_gpa, label: "Minimum GPA" %>
<label>Major</label>
<%= s.select :major, options_for_select(#major), :include_blank => true %>
<label>Job type</label>
<%= s.select :level, options_for_select(#level), :include_blank => true %>
<%= s.button :submit, "Search" %>
<% end %>
The error I get when I try to visit the index view:
NoMethodError in Userinfos#index
Showing app-path/index.html.erb where line #25 raised:
undefined method `level' for #<Search:0x000000139d6c38>
Line 25 is:
<%= s.select :level, options_for_select(#level), :include_blank => true %>
Everything works if I remove that line. When I show the education level in the user profile page, it works perfectly.
Schema for searches:
create_table "searches", force: :cascade do |t|
t.string "keyword"
t.string "college"
t.decimal "min_gpa"
t.string "major"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
As you commented, you do not have a level attribute in your Search model.
rails g migration add_level_to_searches level:string
And of course
rails db:migrate
Happy to help!
Another newb question. A Band has_many Albums. I'm getting the error:
ActiveRecord::AssociationTypeMismatch (Band(#70076964285020) expected,
got "1" which is an instance of String(#12787800)):
app/controllers/albums_controller.rb:20:in `create'
... which is the build line in #create
albums controller
def new
binding.pry
#band = Band.find(params[:band])
authorize #band, :admin?
#album = Album.new
respond_to do |format|
format.js
end
end
def create
binding.pry
#band = Band.find(params[:album][:band].to_i)
authorize #band, :admin?
#album = #band.albums.build(album_params)
if #album.save
#albums = #band.albums
##eps = #band.eps
#songs = #band.songs
respond_to do |format|
format.js
end
else
#fail = "fail"
respond_to do |format|
format.js
end
end
end
def album_params
params.require(:album).permit(:band, :album_name, :album_release_date, :etc)
end
the form:
<%=simple_form_for(#album, remote: true, :authenticity_token => true, format: :js) do |f| %>
<%= f.hidden_field :band, :value => #band.id %>
<%= f.input :album_name %>
<%= f.input :album_release_date %>
<%= f.input :etc %>
<div id="albumsubmit">
<div class="form-actions">
<%= f.button :submit, "Create Album", class: "btn btn-primary" %>
</div>
</div>
schema
create_table "albums", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "band_id"
t.string "album_name"
t.string "album_release_date"
t.index ["band_id"], name: "index_albums_on_band_id"
end
when you passing to save method param with that have has_many Association he expect the instance of "band", just set the param name to band_id
here:
<%= f.hidden_field :band, :value => #band.id %>
to:
<%= f.hidden_field :band_id, :value => #band.id %>
and here:
params.require(:album).permit(:band, :album_name, :album_release_date, :etc)
to:
params.require(:album).permit(:band_id, :album_name, :album_release_date, :etc)
I've been having this problem with Paperclip for a while. New/Edit form submits and saves/updates, but create.js and update.js renders the code (that normally would be a view) as text to http://localhost:3000/albums/9.js (if it's the 9th album being updated), instead of a view in a modal on localhost:3000.
so instead of rendering a view, i get this text on /albums/9.js: $("#actionEdit").html("Album Updated.")
album model
belongs_to :band
has_many :songs
has_attached_file :album_artwork_1,
styles: { thumb: ["64x64#", :jpg] },
convert_options: { thumb: "-strip",
original: "-strip" }
has_attached_file :album_artwork_2,
styles: { thumb: ["64x64#", :jpg] },
convert_options: { thumb: "-strip",
original: "-strip" }
has_attached_file :album_artwork_3,
styles: { thumb: ["64x64#", :jpg] },
convert_options: { thumb: "-strip",
original: "-strip" }
do_not_validate_attachment_file_type :album_artwork_1
do_not_validate_attachment_file_type :album_artwork_2
do_not_validate_attachment_file_type :album_artwork_3
validates :album_name, presence: true
validates :album_release_date, presence: true
albums controller
def new
binding.pry
#band = Band.find(params[:band])
authorize #band, :admin?
#album = Album.new
respond_to do |format|
format.js
end
end
def create
#band = Band.find(params[:album][:band].to_i)
authorize #band, :admin?
#album = #band.albums.build(album_params)
if #album.save
#records = []
#band.albums.each do |album|
#records << album
end
#band.eps.each do |ep|
#records << ep
end
#band.songs.each do |song|
#records << song
end
#records_ordered = #records #.sort.reverse!
respond_to do |format|
format.js
end
else
respond_to do |format|
format.js
end
end
end
def edit
#band = Band.find(params[:band])
authorize #band, :admin?
#album = Album.find(params[:id])
respond_to do |format|
format.js
end
end
def update
binding.pry
#band = Band.find(params[:album][:band])
authorize #band, :admin?
#album = Album.find(params[:id])
if #album.update(album_params)
respond_to do |format|
format.js
end
else
#fail = "w4rd"
respond_to do |format|
format.js
end
end
end
form
<%=simple_form_for(#album, remote: true, :authenticity_token => true, format: :js) do |f| %>
<% if #album.album_artwork_1.present? %>
<%= link_to image_tag(#album.album_artwork_1.url(:thumb), class: 'media-object'), #album.album_artwork_1.url, target: '_blank' %>
<% end %>
<div class="form-group">
<%= f.input :album_artwork_1, as: :file %>
</div>
<% if #album.album_artwork_2.present? %>
<%= link_to image_tag(#album.album_artwork_2.url(:thumb), class: 'media-object'), #album.album_artwork_2.url, target: '_blank' %>
<% end %>
<div class="form-group">
<%= f.input :album_artwork_2, as: :file %>
</div>
<% if #album.album_artwork_3.present? %>
<%= link_to image_tag(#album.album_artwork_3.url(:thumb), class: 'media-object'), #album.album_artwork_3.url, target: '_blank' %>
<% end %>
<div class="form-group">
<%= f.input :album_artwork_3, as: :file %>
</div>
<br><br>
<div id="albumsubmit">
<% if params[:action] === "edit" %>
<div class="form-actions">
<%= f.button :submit, "Update Album", class: "btn btn-primary" %>
</div>
<% else %>
<div class="form-actions">
<%= f.button :submit, "Create Album", class: "btn btn-primary" %>
</div>
<% end %>
</div>
<% end %>
update.js.erb
$("#actionEdit").html("<%= j render 'updated' %>")
schema
create_table "albums", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "album_artwork_1_file_name"
t.string "album_artwork_1_content_type"
t.integer "album_artwork_1_file_size"
t.datetime "album_artwork_1_updated_at"
t.string "album_artwork_2_file_name"
t.string "album_artwork_2_content_type"
t.integer "album_artwork_2_file_size"
t.datetime "album_artwork_2_updated_at"
t.string "album_artwork_3_file_name"
t.string "album_artwork_3_content_type"
t.integer "album_artwork_3_file_size"
t.datetime "album_artwork_3_updated_at"
params coming into #update
[1] pry(#<AlbumsController>)> params
=> <ActionController::Parameters {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"B/g/tnhObi6YmY6gqY0hTzJyiewshxVN6S1Dv+1yspGiRQZAlr8qdRiMtDyOh1/1VYvmr1FW9AsClLnW6xt9rg==", "album"=>{"band"=>"1", "album_name"=>"Test", "album_release_date"=>"2017-04-29", "produced_by"=>"", "recorded_at"=>"", "engineered_by"=>"", "second_engineers"=>"", "mixed_by"=>"", "mastered_by"=>"", "artwork_by"=>"", "photography_by"=>"", "art_direction_by"=>"", "construction_by"=>"", "booking"=>"", "litigation"=>"", "additional_musicians"=>"", "copyright"=>"", "websites"=>"", "contacts"=>"", "other"=>"", "album_artwork_2"=>#<ActionDispatch::Http::UploadedFile:0x007f681a3b4ca8 #tempfile=#<Tempfile:/tmp/RackMultipart20170416-32079-mie4xo.jpg>, #original_filename="c.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"album[album_artwork_2]\"; filename=\"c.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Update Album", "controller"=>"albums", "action"=>"update", "id"=>"7", "format"=>"js"} permitted: false>
[2] pry(#<AlbumsController>)>
Apparently you can't upload via remote: true without the gem remotipart, which resolved the issue.
My app was working perfectly an hour ago, then I added two columns, :pick_up and :send to the 'orders' table, and after that I got this error
wrong number of arguments (1 for 0)
I don't see why that should be causing this error though.
Here is orders_controller.rb:
class OrdersController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
before_action :set_order, only: [:show, :edit, :destroy]
def index
#orders = Order.all?
end
def new
#images = ["1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg"]
#random_no = rand(5)
#random_image = #images[#random_no]
if #cart.product_items.empty?
redirect_to root_url, notice: 'Your Cart is Empty'
return
end
#order = Order.new
#client_token = Braintree::ClientToken.generate
end
def create
#order = Order.new(order_params)
if #order.save
charge
if #result.success?
#order.add_product_items_from_cart(#cart)
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
OrderNotifier.received(#order).deliver
redirect_to root_url, notice: 'Thank You for Your Order'
else
flash[:error] = 'Please Check Your Cart'
redirect_to root_url, alert: #result.message
#order.destroy
end
else
#client_token = Braintree::ClientToken.generate
render :new
end
end
def show
end
def destroy
#order.destroy
redirect_to root_url, notice: 'Order deleted'
end
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:name, :email, :address, :city, :country, :pick_up, :send)
end
def charge
#result = Braintree::Transaction.sale(
amount: #cart.total_price_usd,
payment_method_nonce: params[:payment_method_nonce] )
end
end
This is _form.html.erb for the orders:
<%= form_for #order do |f| %>
<%= render 'msg' %>
<div class="container">
<div class="col-md-10">
<h3>Please Enter Your Details</h3>
</div>
<div class="form-group">
<div class="col-md-10">
<%= f.label :name %>
<%= f.text_field :name, size: 40, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<%= f.label :email%>
<%= f.email_field :email, size: 40, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<%= f.label :address %>
<%= f.text_area :address, cols: 40, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<%= f.label :city %>
<%= f.text_field :city, size: 40, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<div class="col-md-5">
<%= f.label :country %>
<%= f.country_select :country, { priority_countries: [ "IS", "US", "DE", "ES", "PT" ]}, { class: "form-control" }%>
</div>
</div>
<div class="form-group">
<div id="payment-form"></div>
<div class="col-md-10">
<br>
<%= f.submit 'Place Order', class: 'buttons' %>
</div>
</div>
</div>
<% end %>
Here is the order part of schema.rb:
create_table "orders", force: :cascade do |t|
t.string "name"
t.string "email"
t.text "address"
t.string "city"
t.string "country"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "shipped", default: false
t.string "pick_up"
t.string "send"
end
I fear send is not a lucky name for an identifier because the send method.
http://ruby-doc.org/core-2.3.1/Object.html#method-i-send
I am trying to create categories for my posts. To do so, I generated a new category model. Although I have associated the two models, I am still receiving this error:
ActiveRecord::UnknownAttributeError: unknown attribute 'category_id' for Post.
I have doublechecked the schema which does include category_id for the post table:
add_index "comments", ["post_id"], name: "index_comments_on_post_id"
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "cost"
t.integer "openspots"
t.boolean "approval"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "category_id"
end
add_index "posts", ["user_id"], name: "index_posts_on_user_id"
Here are my associations as well:
class Category < ActiveRecord::Base
has_many :posts
end
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :comments
default_scope { order('created_at DESC') }
end
Finally I wanted to include my posts controller:
class PostsController < ApplicationController
def new
# #post = Post.new
#post = Post.new
#categories = Category.all.map{|c| [ c.name, c.id ] }
end
def create
#post = Post.new(params.require(:post).permit(:title, :description, :cost, :openspots, :approval, :category_id))
#post.category_id = params[:category_id]
#post.user = current_user
if #post.save
flash[:notice] = "Post was saved."
redirect_to #post
else
flash[:error] = "There was an error saving the post. Please try again."
render :new
end
end
def update
#post = Post.find(params[:id])
#post.category_id = params[:category_id]
if #post.update_attributes(params.require(:post).permit(:title, :description))
flash[:notice] = "Post was updated."
redirect_to #post
else
flash[:error] = "There was an error saving the post. Please try again."
render :edit
end
end
def edit
#post = Post.find(params[:id])
#post.category_id = params[:category_id]
end
def destroy
end
def index
#posts = Post.all
end
def show
#post = Post.find(params[:id])
end
end
Whenever I create a new post, the post is created successfully;however, the category id is never saved.
Here is my view as well:
<h1>New Post</h1>
<div class="row">
<div class="col-md-4">
<p>Guidelines for posts</p>
<ul>
<li>Make sure it rhymes.</li>
<li>Don't use the letter "A".</li>
<li>The incessant use of hashtags will get you banned.</li>
</ul>
</div>
<div class="col-md-8">
<%= form_for #post do |f| %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control', placeholder: "Enter post title" %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, rows: 8, class: 'form-control', placeholder: "Enter post description" %>
</div>
<div class="form-group">
<%= f.label :cost %>
<%= f.number_field :cost, rows: 8, class: 'form-control', placeholder: "Enter cost" %>
</div>
<div class="form-group">
<%= f.label :openspots %>
<%= f.number_field :openspots, rows: 8, class: 'form-control', placeholder: "Enter Number of Open Spots" %>
</div>
<div class="form-group">
<%= f.label :approval %>
<%= f.check_box :approval, rows: 8, class: 'form-control', placeholder: "Check if Approval Necessary" %>
</div>
<div class="form-group">
<%= f.label :category %>
<%= f.collection_select :category_id, Category.order(:name),:id,:name, include_blank: true %>
</div>
<div class="form-group">
<%= f.submit "Save", class: 'btn btn-success' %>
</div>
<% end %>
</div>
</div>