I am using CarrierWave to handle image uploading for my rails app (rails 4.1).
The issue is I am getting this
undefined method `images_path' for #<#
error every time try to go to /image/new.
I have checked my routes, my views, my controller, my model, and my uploader and everything seems fine. any advice or ideas?
Code:
image_uploader.rb:
class ImageUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
/models/image.rb:
class Image < ActiveRecord::Base
mount_uploader :image, ImageUploader
end
Relevant Routes:
Rails.application.routes.draw do
resources :image
image_controller.rb
class ImageController < ApplicationController
def new
#image = Image.new(:image => params[:image_params])
end
def create
#image = Image.create( image_params )
if #image.save
redirect_to #image
else
render 'new'
end
end
def show
end
private
def image_params
params.require(:image).permit(:title, :description, :image
end
def find_image
#image = Image.find(params[:id])
end
end
new.html.erb
<div class="col-md-12 col-md-offset-2">
<%= form_for #image, html: { multipart: true } do |f| %>
<%= f.file_field #image %>
<p id="uploadClick">Click to Upload</p>
<br>
<%= submit_tag 'Upload Image', id: 'submitPhoto' %>
<% end %>
</div>
Any help with this would be greatly appreciated, thanks!
SOLUTION:
in new.html.erb I had to change:
<%= form_for #asset, html: { multipart: true } do |f| %>
to
<%= form_for :asset, html: { multipart: true } do |f| %>
my new action is now working correctly after those changes, hope this helps people in the future.
Try changing resources :image to resources :images in routes.rb and change new and create methods in the controller like below
def new
#image = Image.new
end
def create
#image = Image.new(image_params)
if #image.save
redirect_to #image
else
render 'new'
end
end
Related
I'm trying to pass through some parameters using form_for in rails, how do I pass them so that they can be accessed in the controller like this: params[:image]? the start of my form_for tag looks like this:
<%= form_for(#image, as: :image, url: create_image_path(current_user), html: { multipart: true }, method: :post) do |f| %>
I can give you an example wtih carrierwave
gem install carrierwave
rails g model Resume attachment:string
rails g uploader attachment
**Add this in your model , controller and view **
class Resume < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader # Tells rails to use this uploader for this model.
end
class ResumesController < ApplicationController
def index
#resumes = Resume.all
end
def new
#resume = Resume.new
end
def create
#resume = Resume.new(resume_params)
if #resume.save
redirect_to resumes_path, notice: "The resume #{#resume.name} has been uploaded."
else
render "new"
end
end
def destroy
#resume = Resume.find(params[:id])
#resume.destroy
redirect_to resumes_path, notice: "The resume #{#resume.name} has been deleted."
end
private
def resume_params
params.require(:resume).permit( :attachment)
end
end
<div class = "well">
<%= form_for #resume, html: { multipart: true } do |f| %>
<%= f.file_field :attachment %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
</div>
I'm a newbie on rails. My rails version is 4.2.6, simple_form_for version is 3.2.1. I want to redirect to the new page after I validated the params is false. And I get the error message.
undefined method `model_name' for nil:NilClass <%= simple_form_for
[:account, #station] do |f| %>
...
let me show you. This is my routes.rb
namespace :account do
resources :stations, expect: [:index]
end
stations_controller.rb
def new
#lines = Line.where(line_status: 1)
#station = Station.new
end
def create
unless check_post_params post_params
flash[:notice] = "miss params"
render action: :new # not work
# render :new # not work
# render 'new' # not work
# it work for me, but can I use render?
#redirect_to '/account/stations/new'
else
#station = Station.new(post_params)
if #station.save
redirect_to '/account/lines'
else
flash[:notice] = 'failed'
redirect_to 'account/stations/new'
end
end
end
private
def post_params
params.require(:station).permit(...)
end
def check_post_params(post_params)
if ...
return false
else
return true
end
end
_form.html.erb
<%= simple_form_for [:account, #station] do |f| %>
<div class="form-group">
<%= f.label :line_id, t('line.line_name') %>
<%= f.input_field :line_id,
... %>
<% end %>
The original I open the URL is http://localhost:3000/acoount/stations/new. After I click the submit, and I want to render :new, it will redirect to original URL, but I found the URL become http://localhost:3000/account/stations. The URL's /new is disappear. I have guessed it's about my routes.rb config.
And I tried to use rake routes to check my routes.
$ rake routes
...
POST /account/stations(.:format) account/stations#create {:expect=>:index]}
new_account_station GET /account/stations/new(.:format) account/stations#new {:expect=>[:index]}
...
I tried to use render account_stations_new_path and render new_account_station_path, but still not work for me. Thanks your help.
Edit
I know how to modify my code. I should validate my params on my model. And then I should use redirect_to not use render. I will update my code later.
Edit 2
I modified my model.
class Station < ActiveRecord::Base
belongs_to :line
has_many :spot_stations
validates :name, presence: true, uniqueness: { case_sensitive: false }
validates :line_id, presence: true
validates ....
end
And I modified my controller.
def new
# Because this #lines did't exist when I render 'new' on the create method. So I deleted it. And I create a method on the helper.
# #lines = Line.where(line_status: 1)
#station = Station.new
end
def create
#station = Station.new(post_params)
if #station.save
redirect_to '/account/lines'
else
flash[:notice] = 'failed'
render 'new'
end
end
I add a method for getting lines data
module Account::StationsHelper
def get_lines
#lines = Line.where(line_status: 1)
end
end
I will use it on my _form.html.erb
<%= simple_form_for [:account, #station] do |f| %>
<div class="form-group">
<%= f.label :line_id, t('line.line_name') %>
<%= f.input_field :line_id,
collection: get_lines,
label_method: :line_name,
input_html: { class: 'form-control' },
value_method: :id,
prompt: t('common.please_select') %>
</div>
...
<% end %>
This work great for me. Thanks your help.
try this:
if #station.save
redirect_to account_stations
else
flash[:notice] = 'failed'
render 'new'
end
as argument for render method you must pass action name, not url.
I have a model named 'Image.rb' to store uploaded images, a controller 'images_controller.rb' and 'static_pages_controller.rb' with action 'tournaments'. I get the following error on navigating to '/tournaments':
ArgumentError in StaticPages#tournament
Showing ../static_pages/tournament.html.erb where line #9 raised:
First argument in form cannot contain nil or be empty
Extracted source (around line #9):
7 This is the information bulletin for the upcoming tournament
8 </h2>
9 <%= form_for(#image, html: {multipart: true}) do |f| %>
10 <%= render 'shared/error_messages', object: f.object %>
11 <span class="picture">
routes.rb
.
.
get 'tournaments' => 'static_pages#tournament'
resources :images
tournament.html.erb
<%= form_for(#image, html: {multipart: true}) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<span class="picture">
<h4> </h4>
<h3>Upload a picture here!</h3>
<%= f.label :name %>
<%= f.text_field :name, placeholder: "Give it a caption.." %>
<%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
<%= f.submit "Post picture!" %>
</span>
<% end %>
static_pages_controller.rb
class StaticPagesController < ApplicationController
def tournaments
#image = Image.new
#images = Image.paginate(page: params[:page])
end
end
images_controller.rb
class ImagesController < ApplicationController
before_action :logged_in_user
def create
#image = Image.new(image_params)
if #image.save
flash.now[:success] = "Uploaded successfully"
redirect_to tournaments_path
else
flash.now[:alert] = "Something went wrong"
redirect_to tournaments_path
end
end
private
def image_params
params.require(:image).permit(:name, :picture)
end
end
image.rb
class Image < ActiveRecord::Base
mount_uploader :picture, PictureUploader
validates :name, presence: true, length: {maximum: 50}
validate :picture_size
private
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "Should be less than 5MB.")
end
end
end
I cannot understand where I'm going wrong. Any helpful pointers to resolving this error would be much appreciated.
You should change your def tournaments method to def tournament
def tournament
#image = Image.new
#images = Image.paginate(page: params[:page])
end
changed action tournaments to tournament.
I am building a Rails app where I need users to upload a profile image on the registration form/have an image edit feature for profile photo. Carrierwave should be properly installed and so far Devise seems to be running fine. When I go to upload the photo and then click "Create Profile", it simply refreshes to the same page and resets the file upload field each time.
SOLUTION: Updated update method in controller to:
def update
#pet = Pet.find(params[:id])
if #pet.update(pet_params)
redirect_to pets_path
else
render :edit
end
end
It's uploaded in my app/uploaders/profile_photo_uploader.rb file:
class ProfilePhotoUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
I have a "profile_photo" string in my schema, as well.
And my controller actions for create and edit/update are here:
def create
#pet = Pet.new(pet_params)
if #pet.save
flash[:notice] = 'Your pet profile was saved!'
redirect_to pets_path
else
flash.now[:notice] = 'Your pet profile could not be saved.'
render :new
end
end
def show
#pet = Pet.find(params[:id])
end
def edit
#pet = Pet.find(params[:id])
end
def update
#pet = Pet.find(params[:id])
if #pet.save
redirect_to pets_path
else
render :edit
end
end
def pet_params
params.require(:pet).permit(:name, :breed, :age,
:color, :weight, :personality, :favorite_things, :owner_id, :profile_photo)
end
My new form using SimpleForm:
<h1>New Pet Profile</h1>
<%= simple_form_for #pet, html: { multipart: true } do |f| %>
<%= f.input :name, required: true, label: "Pet Name:" %>
<%= f.input :profile_photo, type: :file %>
...
<%= f.button :submit %>
<% end %>
Routes:
Rails.application.routes.draw do
devise_for :owners
resources :pets
resources :owners do
resources :pets, shallow: true
end
end
Application Controller:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :profile_photo
end
end
You need to have your model set app/models/pet.rb with
class Pet < ActiveRecord::Base
validates_presence_of :profile_photo
belongs_to :owner
mount_uploader :profile_photo, ProfilePhotoUploader
end
Also, side note, if you're using Heroku it won't save pictures since it's a static service. You need to integrate a service like Cloudinary with Carrierwave.
After your form line <%= simple_form_for #pet, html: { multipart: true } do |f| %> put this in
<% if #pet.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#pet.errors.count, "error") %> prohibited this pet from being saved:</h2>
<ul>
<% #pet.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
and this line <%= f.input :profile_photo, type: :file %> to this <%= f.file_field :profile_photo %>
At the end of your pet_controller's file make sure you've given permission for the form to submit the data
def pet_params
params.require(:pet).permit(:name, :profile_photo)
end
Since I see you're using devise you might consider assigning the owner to the pet. Consider the line in your pet_controller.rb
def create
#pet = Pet.new(pet_params)
#pet.owner = current_user
And see the line in model belongs_to :owner
I was hoping someone can give me some insights on how nested resources and more specifically how to tie it with CarrierWave.
I'm getting an error undefined method 'photos_path' and am a bit stuck on how do go about getting this to work.
I want to be able to have the following urls
Create a new photo
site.com/animal/dog/photos/new
Show photo
site.com/animal/dog/photos/my-dog-in-the-park
Should I be using a nested form? any help is much appreciated.
My Routes
root to: "home#index"
resources :animal do
resources :photos
end
My home view
<%= link_to "Add Dog Photo", new_animal_photo_path(animal_permalink: "dog") %>
My _form partial
<%= form_for [#animal, #photo], :html => {:multipart => true} do |f| %>
<%= f.hidden_field :animal_permalink %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.file_field :image %>
</p>
<p>
</p>
<p><%= f.submit %></p>
<% end %>
My Photo model
class Photo < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
before_create :set_permalink
before_update :set_permalink
belongs_to :dog
mount_uploader :image, PhotoUploader
def set_permalink
self.permalink = title.parameterize
end
def to_param
permalink.parameterize
end
end
My Animal model
class Animal < ActiveRecord::Base
include ActiveModel::ForbiddenAttributesProtection
has_many :photos
scope :dog, where(name: "Dog")
def to_param
permalink.parameterize
end
end
My PhotoController
class PhotosController < ApplicationController
def show
#photo = Photo.find(params[:id])
end
def new
#animal = Animal.find_by_permalink(params[:id])
#photo = Photo.new
end
def create
#photo = Photo.new(photo_params)
if #photo.save
flash[:notice] = "Successfully created photo."
redirect_to root_url
else
render :action => 'new'
end
end
def edit
#photo = Photo.find(params[:id])
end
def update
#photo = Photo.find(params[:id])
if #photo.update_attributes(photo_params)
flash[:notice] = "Successfully updated photo."
redirect_to root_url
else
render :action => 'edit'
end
end
def destroy
#photo = Photo.find(params[:id])
#photo.destroy
flash[:notice] = "Successfully destroyed photo."
redirect_to root_url
end
private
def photo_params
params.require(:photo).permit(:title, :image, :animal_id)
end
end
Thanks for taking a look. Any help is much appreciated.
I've made a few adjustments to your code.
Notice I've added an "s" to animal
root to: "home#index"
resources :animals do
resources :photos
end
notice I've removed an "s" from animals. I've changed animal_permalink to id because that is the default that would be expected by a nested resource. Also, note that, in your photos controller new method you check for the "id" param, not the animal_permalink param.
new_animal_photo_path(id: "dog")
In your _form. set the value of the animal_permalink
<%= f.hidden_field :animal_permalink, value: #animal.permalink %>
This assumes that Photo will be able to recognize the animal_permalink attribute and that you've defined an animal.permalink method/attribute. I'm not familiar with the permalink approach, so you may have to fiddle around a bit, but this should steer you in the right direction (I would normally set the :dog_id/:animal_id attribute).
Let me know how that goes.