I've been trying to add uploads to my rails project following this article: How To: Secure Upload. Everything seems to work fine, but I am getting a no method error on the index view:
ActionView::Template::Error (undefined local variable or method `f' for #<#<Class:0x007f690e634600>:0x007f690e620718>):
24:
25: <tr>
26: <td><%= resume.name %></td>
27: <td><%= link_to File.basename(f.resume.url), "/uploads/#{f.id}/#{File.basename(f.resume.url)}" %></td>
28: <td><%= button_to "Delete", resume, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{resume.name}?" %></td>
29: </tr>
30:
app/views/resumes/index.html.erb:27:in block in _app_views_resumes_index_html_erb___1440061793164452865_70044592937660'
app/views/resumes/index.html.erb:23:in_app_views_resumes_index_html_erb___1440061793164452865_70044592937660'
My model:
class Resume < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader # Tells rails to use this uploader for this model.
validates :name, presence: true # Make sure the owner's name is present.
end
My Controller:
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 download
path = "/#{resume.resume}"
send_file path, :x_sendfile=>true
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(:name, :attachment)
end
end
My Index View:
<% if !flash[:notice].blank? %>
<div class = "alert alert-info">
<%= flash[:notice] %>
</div>
<% end %>
<br />
<%= link_to "New Resume", new_resume_path, class: "btn btn-primary" %>
<br />
<br />
<table class = "table table-bordered table-striped">
<thead>.
<tr>
<th>Name</th>
<th>Download Link</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #resumes.each do |resume| %>
<tr>
<td><%= resume.name %></td>
<td><%= link_to File.basename(f.resume.url), "/uploads/#{f.id}/#{File.basename(f.resume.url)}" %></td>
<td><%= button_to "Delete", resume, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{resume.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
I've been googling answers for hours and can't seem to track down a solution based on previous answers. Apologies if one was overlooked.
there is a typo in the how-to (and this how-to aslo http://www.tutorialspoint.com/ruby-on-rails/rails-file-uploading.htm) . just rename #resumes -> #resume in the view and the controller.
Related
I searched for the answer, but I couldn't find the same problem.
Basically - I'm building a simple CMS, and I'm building a controller with a view, but it isn't working. I can press the submit button, but the form gives no response, it doesn't even output any errors.
I also noticed it changes the url from /pages/new to /pages, but it stays on the form.
Page Controller:
def index
#pages = Page.sorted
end
def show
#page = Page.find(params[:id])
end
def new
#page = Page.new
end
def create
#page = Page.new(page_params)
if #page.save
flash[:notice] = "Page created succesfully."
redirect_to pages_path
else
render('new')
end
end
def edit
#page = Page.find(params[:id])
end
def update
#page = Page.find(params[:id])
if #page.update_attributes(page_params)
flash[:notice] = "Subject updated succesfully."
redirect_to page_path(#page)
render('edit')
end
end
def delete
#page = Page.find(params[:id])
end
def destroy
#page = Page.find(params[:id])
#page.destroy
flash[:notice] = "Page '#{#page.name}' destoyed succesfully."
redirect_to(pages_path)
end
private
def page_params
params.require(:page).permit(:subject_id, :name, :position, :visible, :permalink)
end
new.html.erb:
<%= link_to("<< Back To List", pages_path, :class => 'back-link') %>
<div class = "pages new">
<h2>Create Page</h2>
<%= form_for(#page, :url => pages_path, :method => 'post') do |f| %>
<table summary = "Page form fields">
<tr>
<th> Name: </th>
<td><%= f.text_field(:name) %></td>
</tr>
<tr>
<th> Subject ID: </th>
<td><%= f.text_field(:subject_id) %></td>
</tr>
<tr>
<th> Permalink: </th>
<td><%= f.text_field(:permalink) %></td>
</tr>
<tr>
<th>Position: </th>
<td><%= f.text_field(:position) %></td>
</tr>
<tr>
<th>Visible: </th>
<td><%= f.text_field(:visible) %></td>
</tr>
</table>
<div class="form-buttons">
<%= f.submit("Create Page") %>
</div>
<% end %>
</div>
EDIT:
tried changing the form code to <%= form_for(#page) do |f| %>, but I still have the same problem
I added the #page.save! part of the code and it gave me a error which showed me errors which are deeper down in my code! At least I fixed this problem. Thank you very much.
It seems that the information from your form is not valid, try using save! instead of save in your create action:
def create
#page = Page.new(page_params)
if #page.save!
flash[:notice] = "Page created succesfully."
redirect_to pages_path
else
render('new')
end
end
That will show the error on your logs.
I looked through several other similar help questions, and I'm not seeing my error. I have destroy, new, create all working, but post and show throw errors. Also oddly enough, clicking the 'edit' button on the index view throws an error, but going directly to http://localhost:3000/images/1 gives me the 'show' page (no idea why it isn't giving an edit page).
relevant files:
images_controller.rb
class ImagesController < ApplicationController
def index
#images = Image.all
end
def new
#image = Image.new
end
def create
#image = Image.new(image_params)
if #image.save
redirect_to images_path, notice: "Your image #{#image.name} has been uploaded."
else
render "new"
end
end
def edit
#image = Image.find(params[:id])
end
def destroy
#image = Image.find(params[:id])
#image.destroy
redirect_to images_path, notice: "The image #{#image.name} has been removed from the database."
end
def show
#image = Image.find(params[:id])
end
private
def image_params
params.require(:image).permit(:name, :attachment)
end
end
routes.rb
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
resources :images#, only: [:index, :new, :create, :update, :edit, :show, :destroy]
root "images#index"
end
Note: I have also added the lines
get 'images/edit'
get 'images/details'
But to no avail.
index.html.erb:
<% if !flash[:notice].blank? %>
<div class="alert alert-info">
<%= flash[:notice] %>
</div>
<% end %>
<br />
<%= link_to "New Image", new_image_path, class: "btn btn-primary" %>
<br />
<br />
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>View Link</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #images.each do |image| %>
<tr>
<td><%= image.name %></td>
<td><%= link_to "#{image.name}", image.attachment_url %></td>
<td><%= button_to "Edit", image, method: :edit, class: "btn btn-primary", confirm: "edit #{image.name}?" %></td>
<td><%= button_to "Show", image, method: :show, class: "btn btn-primary"%></td>
<td><%= button_to "Delete", image, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{image.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
I suppose there are no HTTP methods like this:
method: :edit, method: :show
Try to do smth like this:
link_to "Edit", edit_image_path(image)
link_to "Show", image_path(image)
And remove this line from routes.rb
get 'images/edit'
resources has already created rout to edit action for you. You can see it http://localhost:3000/rails/info/routes
button_to by default will make post request you need link_to "edit" to make get request. when you type in your browser http://localhost:3000/images/1 you are making get request so it works.
link_to "Edit", edit_image_path image
check these links for link_to and button_to
http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
http://apidock.com/rails/ActionView/Helpers/UrlHelper/button_to
This is the error I'm getting:
No route matches [POST] "/specials/1"
I understand that it's not able to produce the post route, or it isn't available.
Here's my view/form code:
<%= form_for(:special, :url => {:action => 'update', :id => #special.id}) do |f| %>
<table class="table table-responsive table-striped table-condensed table-hover" summary="Special form fields">
<tr>
<th>Order</th>
<td><%= f.text_field :order, class: "form-control" %></td>
</tr>
<tr>
<th>Name</th>
<td><%= f.text_field :name, class: "form-control" %></td>
</tr>
<tr>
<th>Description</th>
<td><%= f.text_field :description, class: "form-control" %></td>
</tr>
<tr>
<th>Fine Print</th>
<td><%= f.text_field :fine_print, class: "form-control" %></td>
</tr>
<tr>
<th>Active</th>
<td><%= f.text_field :active, class: "form-control" %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Update Special") %>
</div>
<% end %>
Heres's my controller code:
class SpecialsController < ApplicationController
def index
#specials = Special.sorted
end
def show
#special = Special.find(params[:id])
end
def new
#special = Special.new
end
def create
#Instantiation of object using form parameters
#special = Special.new(special_params)
#Save the object
if #special.save
#If success, redirect to index action
redirect_to(:action => 'index')
else
# Redisplay the form so user can fix problems
render('new')
end
end
def edit
#special = Special.find(params[:id])
end
def update
#Find an existing object using form parameters
#special = Special.find(params[:id])
#Update the object
if #special.update_attributes(special_params)
#If succeeds, redirect to index action
redirect_to(:action => 'show', :id => #special.id)
else
# If update fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
end
private
def special_params
params.require(:special).permit(:name, :description, :fine_print, :active, :order)
end
end
I noticed that there is an update path:
PATCH /specials/:id(.:format) specials#update
I can't figure out why the post route isn't being applied. It's looking for the right #special instance, but it doesn't seem to have the route available. Any advice?
Usually when updating a record, we do a patch request to the route. Your form should look like this:
<%= form_for(#special) do |f| %>
Rails will determine the correct route is PATCH /specials/:id based on the fact that #special has been persisted to the database.
If you decide to use this same form as a partial in your new view, just make sure to add this to your controller:
def new
#special = Special.new
end
That way whether you are on the new route or the edit route, there will always be a #special object for form_for to infer whether to POST to /specials or PATCH /specials/:id
So I have this database where a user can borrow a book. We have books, users and people who borrow.
The code can be found here: https://gist.github.com/Veske/8490542
I am wondering, how can I make it so that I display all the books in borrows view, and then also be able to select thoes books for borrowing for my self or another user?
If I try to make a book instance variable in borrow controller for the view, hell gets loose. So I really have no idea now..
Edit: the #book in the view is not needed anymore as it did not work, i had a action in controller for it before.
This is my controller:
class BurrowsController < ApplicationController
before_action :signed_in_user, only: [:index,:edit,:update, :destroy]
before_action :admin_user, only: :destroy
def index
#burrow = current_user.burrows.build
#burrows = Burrow.all
end
def show
#burrow = Burrow.find(params[:id])
end
def new
#burrow = current_user.burrows.build
end
def create
#burrow = current_user.burrows.build(burrow_params)
if #burrow.save
flash[:success] = "Burrowing a book was successful!"
redirect_to #burrow
else
render current_user
end
end
# Private section, makes the page unable to be seen for non logged in users
private
def burrow_params
params.require(:burrow).permit(:user_id, :book_id)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
# Redirecting not logged in user etc.
def signed_in_user
unless signed_in?
store_location
redirect_to '/sessions/new', notice: "Please sign in!"
end
end
end
And this is my view for creating a new borrow entry:
<% provide(:title, "Burrow a book") %>
<b align="center">Choose the name of a book you want to burrow and enter 'Submit!'</b>
<%= form_for(#burrow) do |f| %>
<div class="forms">
<%= f.text_field :book_id, placeholder: "Type in the name of the book...", autofocus: true %>
<%= f.submit 'Submit!' %>
</div>
<% end %>
The view is bad currently, i am experimenting with absolutly everything all the time right now and I just don't understand what needs to be done.
Borrows index:
<% provide(:title, 'All burrowers') %>
<h2 align="center">All borrowers</h2><
<table align="center">
<tr>
<td align="left"><b>Who borrowed</b></td>
<td align="left"><b>Borrowed what</b></td>
<% if current_user.admin? && !current_user?(#user) %>
<td align="left"><b>Admin functions</b></td>
<% end %>
</tr>
<% #burrows.each do |burrow| %>
<tr>
<td align="left"><%= link_to burrow.user.name, burrow.user %></td>
<td align="left"><%= link_to burrow.book.name, burrow.book %></td>
<% if current_user.admin? && !current_user?(#user) %>
<td>
<%= link_to "Delete this user", burrow, method: :delete, data: { confirm: "You sure?" } %>
</td>
<% end %>
</tr>
<% end %>
</table>
One possible solution for this would be to use a select_tag list like this:
<%= form_for(#burrow) do |f| %>
<div class="forms">
<%= f.select("book_id", Book.all.collect {|b| [ b.name, b.id ] }, { include_blank: true }) %>
<%= f.submit 'Submit!' %>
</div>
<% end %>
Is that what you were looking for?
BTW - I think you mean 'borrow' rather than 'burrow'
I am very new to Rails and Web-programming and hope you can help me out with my very first project.
I am developing a website for a Real Estate Agency.
I have 3 tables in my database (Homes: Home_ID, Home_Name, Admin_ID; Admins: Admin_ID, Admin_Name, Admin_Email; Images: Image_ID, Image_Path, Image_Name, Home_ID, Admin_ID).
All 3 tables have been created using scaffold. The image information (name, path, image_id, home_id etc) have been entered in SQLite.
I get all text information of the different houses displayed correctly on the website except the pictures.
My attempt to link it in the view/home/index.html.erb created the following error:
undefined method `image_path' for #<Home:0xb63d85e0>
I used below code:
<% #homes.each do |home| %>
<tr>
<td><%= home.name %></td>
<td><%= home.details %></td>
<td><%= home.region %></td>
<td><%= home.address %></td>
<td><%= home.price %></td>
<td><%= home.admin_id %></td>
<td><%= home.image_path %></td>
</tr>
<% end %>
</table>
It looks like that the data entered in SQLite do not sync with rails.
Do you have any idea what I have done wrong and how I can fix it?
Thank you.
I'm not positive what the relationship would be between your images and home models would be so correct me if I'm wrong, but I'm guessing that homes will have many images. Each image would belong to one home. Is this correct? If so, you will need to declare that in your models like so:
models/home.rb
has_many :images
models/image.rb
belongs_to :home
You will then need to add this to the image database:
t.integer "home_id"
You can add it by going to the command line and typing:
rails g migration AddHomeToImages home_id:integer
You should look in db/migrate/ and then the most recent migration file and make sure it looks like this:
add_column :images, :home_id, :integer
Then run:
rake db:migrate
At this point you'll only need to update your controller and views to show this association. Let me know if this helps and if so I'll help you with your controller and views.
What's happening is that you are looping through a selection of records from the Home table. Because of this, when you call
<td><%= home.image_path %></td>
it's not recognizing the attribute image_path because you don't have image_path as a column of Home table. You only have Home_ID, Home_Name, Admin_ID for your columns. You will have to look into associations between models in order to figure out how to grab the image_path for each home record. You can start here.
If you update the code later on I'll be glad to comment on it.
I think that the best solution here will be to use paperclip gem.
You can take a look at this very old railscast eoisode just to understand how it works:
http://railscasts.com/episodes/134-paperclip
And here is github repository:
https://github.com/thoughtbot/paperclip
Paperclip will help you with paths, styles and preview for your images.
Thanks Jason,
I agree that it is a bit big for newbies, but the requirements were that we do a website where we need to read and write from/to a database. We had a quick introduction to rails with partnerwork and are now on our own and a "bit" lost and running out of time.
Here is the error message I am getting:
NameError in Homes#index
undefined local variable or method `image' for
<#:0xb62f7aa4>
Extracted source (around line #20):
17: <% #homes.each do |home| %>
18: <tr>
19: <td><%= home.name %></td>
20: <td><%= image.home_id %></td>
21: <td><%= home.details %></td>
22: <td><%= home.region %></td>
23: <td><%= home.address %></td>
When I create the database tables I had an Image_ID in the homes table, but I was told that I don`t need it and that it is enough to have only Home_ID in the images table.
I understand that the error is caused because of image.home_id.
What is your opinion? Should I add the Image_ID back to the homes table in order to display all images for the respective home_id or is there another way? I would like to be able to decide which picture will be displayed as the main picture and which ones as the smaller pictures.
Here is the code I use:
models/home.rb
class Home < ActiveRecord::Base
attr_accessible :address, :admin_id, :details, :name, :price, :region
has_many :images
end
models/image.rb
class Image < ActiveRecord::Base
attr_accessible :image_description, :image_name, :image_path
belongs_to :home
end
views/homes/index.html.erb
<h1>Listing homes</h1>
<table>
<tr>
<th>Name</th>
<th>Image</th>
<th>Details</th>
<th>Region</th>
<th>Address</th>
<th>Price</th>
<th>Admin</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #homes.each do |home| %>
<tr>
<td><%= home.name %></td>
<td><%= image.home_id %></td>
<td><%= home.details %></td>
<td><%= home.region %></td>
<td><%= home.address %></td>
<td><%= home.price %></td>
<td><%= home.admin_id %></td>
<td><%= link_to 'Show', home %></td>
<td><%= link_to 'Edit', edit_home_path(home) %></td>
<td><%= link_to 'Destroy', home, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Home', new_home_path %>
views/homes/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #home.name %>
</p>
<p>
<b>Image:</b>
<%= #image.home_id %>
</p>
<p>
<b>Details:</b>
<%= #home.details %>
</p>
<p>
<b>Region:</b>
<%= #home.region %>
</p>
<p>
<b>Address:</b>
<%= #home.address %>
</p>
<p>
<b>Price:</b>
<%= #home.price %>
</p>
<p>
<b>Admin:</b>
<%= #home.admin_id %>
</p>
<%= link_to 'Edit', edit_home_path(#home) %> |
<%= link_to 'Back', homes_path %>
views/images/_form.html.erb
<%= form_for(#image) do |f| %>
<% if #image.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#image.errors.count, "error") %> prohibited this image from being saved:</h2>
<ul>
<% #image.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :image_name %><br />
<%= f.text_field :image_name %>
</div>
<div class="field">
<%= f.label :image_path %><br />
<%= f.text_field :image_path %>
</div>
<div class="field">
<%= f.label :image_description %><br />
<%= f.text_area :image_description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
controllers/images_controller.rb
class ImagesController < ApplicationController
# GET /images
# GET /images.json
def index
#images = Image.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #images }
end
end
# GET /images/1
# GET /images/1.json
def show
#image = Image.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #image }
end
end
# GET /images/new
# GET /images/new.json
def new
#image = Image.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #image }
end
end
# GET /images/1/edit
def edit
#image = Image.find(params[:id])
end
# POST /images
# POST /images.json
def create
#image = Image.new(params[:image])
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: 'Image was successfully created.' }
format.json { render json: #image, status: :created, location: #image }
else
format.html { render action: "new" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# PUT /images/1
# PUT /images/1.json
def update
#image = Image.find(params[:id])
respond_to do |format|
if #image.update_attributes(params[:image])
format.html { redirect_to #image, notice: 'Image was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# DELETE /images/1
# DELETE /images/1.json
def destroy
#image = Image.find(params[:id])
#image.destroy
respond_to do |format|
format.html { redirect_to images_url }
format.json { head :no_content }
end
end
end
Thank you so much. I really appreciate your help!!!