I have an html file as follows, located under views/admin/ve_files/new.html.erb
<div class="page-header">
<h3>Hi</h3>
</div>
<%= simple_form_for #ve_file do |f| %>
<%= f.file_field :file %>
<br><br>
<%= f.submit "Upload" %>
<% end %>
<br>
And then I have a controller located under controllers/admin/ve_files_controller.rb which looks like so
require 'CSV'
class Admin::VeFilesController < ApplicationController
layout 'admin'
def new
authorize! :create, :ve_file
#ve_file = VeFile.new
end
def create
puts "hello"
authorize! :create, :ve_file
#puts params
#ve_file = VeFile.new(params[:ve_file])
puts "okay"
if #ve_file.save
CSV.foreach(#ve_file.file.path) do |row|
puts row[0]
end
redirect_to admin_ve_path, :notice => 'Hi'
else
render :new
end
end
end
So when I click the Upload button in the html file, where does the program try to route me to? Where in the code is that specified? I get the following error and there is no output to the terminal:
Routing Error
uninitialized constant VeFilesController
because it should be Admin::VeFilesController
You are using a namespace called :admin, so that needs to be specified in your call to simple_form_for.
You can do so like this:
<%= simple_form_for [:admin, #ve_file] do |f| %>
Related
im making a twitter clone and trying to make it so the users username appears next to their tweet.
Ive made it work through adding a user and a tweet in the seed file, hoever when i add a create,new method and a form it comes up with the error "Couldn't find User without an ID" and highlighting the first line of my create method. not sure what the issue is, thanks.
class TweetsController < ApplicationController
before_action :authenticate_user!, :except => [:index, :new, :create]
def index
#tweets = Tweet.all.order("created_at DESC")
#tweet = Tweet.new
end
def show
#tweet = Tweet.find(params[:id])
end
def new
# #tweet = Tweet.new
end
def create
#user = User.find(params[:id])
#tweet = Tweet.new(tweet_params)
#tweet.user = #user
if #tweet.save
redirect_to tweets_path
end
end
def edit
#tweet = Tweet.find(params[:id])
end
def update
#tweet = Tweet.find(params[:id])
#tweet.update(tweet_params)
redirect_to tweets_path
end
private
def tweet_params
params.require(:tweet).permit(:user_id,:content)
end
end
<h1>TWEETS</h1>
<%= simple_form_for [#user,#tweet], id: "form-submit" do |f| %>
<%= f.input :content, label: "Tweet" %>
<%= f.input :user %>
<%= f.button :submit, class: "btn btn-danger" %>
<% end %>
<br>
<% #tweets.each do |tweet| %>
<ul>
<li>
<%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %> <br>
<%= tweet.content %>
<%= tweet.user.username %>
</li>
</ul>
<% end %>
You need to define #user in a variable in your index method.
Any variable you use in the form needs to be declared somewhere, either in the helper, controller, or view. Rails convention is to declare them in the controller normally.
I would need to see your config/routes.rb file for the error message you are getting in the image, but if you type rails routes at the command line, you can see a list of all available routes, when you use:
simple_form_for [#user, #tweet]
Rails will interpret [#user, #tweet] as user_tweets_path, and try to submit the form to this path. That path is defined in your config/routes.rb file.
The error is telling you that you have not defined this path in the routes file. To define this path you can add this line to your routes file:
resources :users do
resources :tweets
end
please try to understand my question:
when i shut down the webrick server and again restart it ,then in my index view file there are some records after starting server if i click on any of three option (show,edit,delete)it gives me error "undefined method id' for nil:NilClass" and for "show" option "undefined methodname' for nil:NilC"
but if i add new record then every thing works fine i dont know what is the error
this is delete file
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div>
<h2>Delete vendor</h2>
<%= form_for(:vendor, url: {action:'destroy', id: #vendor.id}) do |f| %>
<p>Are you sure you want to permanently delete this vendor?</p>
<p><%= #vendor.name %></p>
<div>
<%= submit_tag("Delete vendor") %>
</div>
<% end %>
</div>
and this is controller
class VendorController < ApplicationController
def index
#vendors=Vendor.all
end
def new
#initiate new vendor which hits back to create
#vendor=Vendor.new
end
def create
#vendor=Vendor.new(vendor_params)
if#vendor.save
flash[:notice]="vendor ceated"
redirect_to(action: 'index')
else
flash[:notice]="there is error"
render('new')
end
def show
#vendor=Vendor.find(params[:id])
end
def edit
#vendor=Vendor.find(params[:id])
end
def update
#vendor=Vendor.find(params[:id])
if #vendor.update_attributes(vendor_params)
flash[:notice]='record updated'
redirect_to(action:'index')
else
flash[:notice]='there is some error'
render('edit')
end
end
def delete
#vendor=Vendor.find(params[:id])
end
def destroy
#vendor=Vendor.find(params[:id]).destroy
if #vendor.destroy
redirect_to(action: 'index')
else
render('delete')
end
end
end
private
def vendor_params
params.require(:vendor).permit(:name ,:image_url)
end
end
this is edit
<%= link_to("<< Back to List", {:action => 'index'}) %>
<div>
<h2>update Vendor</h2>
<%= form_for(:vendor, :url => {:action => 'update', id: #vendor.id }) do |f| %>
<%= render(partial:"form" , locals: {f: f}) %>
<div class="form-buttons">
<%= submit_tag("Update vendor") %>
</div>
<% end %>
</div>
this is show
<%= link_to("<<BAck to main",{action:"index"}) %>
<div>
<h1>showing <%=#vendor.name %></h1>
<p><%=#vendor.image_url %></p>
</div>
Good to see you fixed the problem.
--
For the benefit of future visitors, the error was caused by your controller name being singular, rather than plural.
All controllers should be named in the plural; all models in the singular:
#app/models/vendor.rb
class Vendor < ActiveRecord::Base
end
#app/controllers/vendors_controller.rb
class VendorsController < ApplicationController
end
As an added recommendation, your forms could be tidied up considerably by using the #vendor variable:
#app/views/vendors/edit.html.erb
<%= form_for #vendor do |f| %>
This will auto-fill the path and method, depending on the construct of the object you've passed.
I'm using rails 4.0.8. I added a comment section to a model called 'Things', but I keep getting the same error "param is missing or the value is empty: thing" when I press the submit comment button. It says the error is in the Things#Controller. What am I doing wrong?
UPDATE: I removed the url path from the form, but a new error returns "Couldn't find Thing without an ID". The error is in Comments#Controller.
VIEW FOR THING/SHOW
<div id= "thing">
<h1>
<%= #thing.name %>
</h1>
<br>
<div id= "commentsection">
Comments
<div id= "comments">
<br>
<% #thing.comments.each do |c| %>
<%= c.username %>
<br>
<%= c.text %>
<% end %>
<%= form_for #comment, :url => thing_path do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :comment %>
<%= f.text_field :text %>
<%= f.submit "Enter", class: "btn btn-small btn-primary" %>
<% end %>
</div>
</div>
</div>
THINGS CONTROLLER
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#thing.comments.build
#comment = Comment.new
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :avatar)
end
end
COMMENTS CONTROLLER (I put asterisks around the line where the error is)
class CommentsController < ApplicationController
def show
#comment = Comment.find(params[:id])
end
def new
#comment = Comment.new
#comments = Comment.all
end
def create
****#thing = Thing.find(params[:thing_id])****
#comment = #thing.comments.create(comment_params)
redirect_to thing_path(#thing)
end
end
private
def comment_params
params.require(:comment).permit(:user, :text, :upvotes, :downvotes, :thing_id)
end
end
ROUTES
Website::Application.routes.draw do
get "comments/new"
get "comments/show"
get "things/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things
resources :good_comments
get "things/show"
get "things/results"
end
You are posting the #comment form to post '/things' path.
<%= form_for #comment, :url => thing_path do |f| %>
It should just be <%= form_for #comment do %> (Rails is smart enough to plug in the comments_path) or if you feel like being more explicit (even though it's not necessary)
<%= form_for #comment, url: :comments_path do %>
Another note though, if you want that Comment to be tied to that specific Thing then in your models it should be
Class Thing
has_many :comments
end
Class Comment
belongs_to :thing
end
Then make sure in your database comment has a thing_id foreign_key field and then your form for comment should actually look like
<%= form_for #thing, #comment do %>
<% end %>
I have an object "device" that contains a good deal of attributes. When editing one of the devices, I want to to have a copy button that when pressed will create a new device and load its "edit page" with the old devices parameters filled into the text_field. But I am very confused on how to called action control methods with buttons and I am currently getting an error saying
"No route matches {:action=>"clone", :controller=>"device", :id=>"1"}"
If I could just get the call to the "clone" method to work then I think I would be in good shape. Any help would be greatly appreciated! My current code is as followed:
edit.html.erb
<div class="row">
<%= form_for(#device) do |f| %>
<div class="span3 offset0">
<%= f.label "Unit Name" %>
<%= f.text_field :unitName %>
.
.
.
<%= f.label "Router Terminal Server IP" %>
<%= f.text_field :routerTerminalServerIp %>
</div>
<div class="span3 offset0">
<%= f.label "N2x Server" %>
<%= f.text_field :n2xServer %>
.
.
.
<%= f.label "Last Changed On" %>
<%= f.text_field :updated_at %>
<%= f.label "Update, Copy, or Delete Device" %>
<%= f.submit "Update", class: "btn btn-medium btn-info" %>
<%= link_to "Clone", :controller => "device", :action => "clone" %>
<%= link_to "Delete", device_path, class: "btn btn-medium btn-danger" %>
</div>
<% end %>
</div>
routes.rb
App::Application.routes.draw do
resources :devices
root 'static_pages#home'
match 'devices/clone', to: 'devices#clone', via: 'get'
end
devices_controller.rb
class DevicesController < ApplicationController
def new
#device = Device.new
end
def clone
oldDevice = Device.find(params[:id])
#device = Device.new
#device = #oldDevice.dup
#device.save
redirect_to edit_device_path(#device.id)
end
def create
#device = Device.new(device_params)
#device.lastChangedBy = request.remote_ip
if #device.save
redirect_to edit_device_path(#device.id)
else
render 'new'
end
end
def show
#device = Device.find(params[:id])
end
def edit
#device = Device.find(params[:id])
end
def update
#device = Device.find(params[:id])
#device.lastChangedBy = request.remote_ip
if #device.update_attributes(device_params)
redirect_to edit_device_path(#device)
else
render "edit"
end
def destroy
Device.find(params[:id]).destroy
redirect_to root_url
end
end
private
def device_params
params.require(:device).permit(:unitName, ...., :owner)
end
end
You should specify the route like this:
resources :devices do
member do
get :clone
end
end
Then you can use the clone_device_path(id) helper.
Also, you should consider using post method for this action and use button instead of link.
You're going to have no end of obscure problems if you name your controller method 'clone', as that is already defined in ruby on Object: http://ruby-doc.org/core-2.0.0/Object.html#method-i-clone
It used to be overridden in ActiveRecord, but lately ActiveRecord uses #dup for this functionality. You can still use 'clone' in your route and in the link label, but use something else for the actual method in your controller; you might want to use an ' :as => 'my_clone' ' option in your routes, if you call your method 'my_clone" for instance.
I have a controller that has the following index action :
def index
if request.post?
flash[:notice] = "Searching.."
redirect_to songs_path # where songs_path is this index page that i am on
end
end
in my application layout i have defined the flash section as such
<% if flash[:notice] %>
<div id='notice'><%= flash[:notice] %></div>
<% end %>
and on my pages_path i've got
<% form_for :search do |f| %>
<%= f.label :search_text %>
<%= f.text_field :search_text %>
<p>
<%= f.submit "Search" %>
</p>
<% end %>
The final result should be a search through a youtube api ( youtube-g) but now i would only wish to make that flash notification appear when i click on the "Search" button , and it doesn't .. any ideas why ?
index action ordinary is GET request. So, if in your routes.rb there is something like resources :searches then your code won't work.
try this:
def create
render :text => "Searching.."
end
because POST /searches will refer to create action
you should update your RESTful route to like this
resources :songs do
collection do
get 'search'
end
end
Then in your Controller
def search
# Perform Your search here like Youtube ..
flash[:notice] = "Searching.."
redirect_to songs_path # This should work now.
end