I've seen this question answered here for Rails 2, but not Rails 3.
I have an app I'm running on localhost called Skynet, which provides one-click access to the scripts that I use regularly:
I have:
config/routes.rb:
Skynet::Application.routes.draw do
resources :robots do
member do
get "cleaner"
end
end
end
app/controllers/robots_controller.rb:
class RobotsController < ApplicationController
def index
respond_to do |format|
format.html
end
end
def cleaner
#output = ''
f = File.open("/Users/steven/Code/skynet/public/input/input.txt", "r")
f.each_line do |line|
#output += line
end
output = Sanitize.clean(#output, :elements => ['title', 'h1', 'h2', 'h3', 'h4', 'p', 'td', 'li'], :attributes => {:all => ['class']}, :remove_contents => ['script'])
newfile = File.new("/Users/steven/Code/skynet/public/output/result.txt", "w")
newfile.write(output)
newfile.close
redirect_to :action => "index"
end
end
(Will refactor later.)
In app/views/robots/index.html.haml I have:
= link_to "test", cleaner_robot_path
When I type rake routes, I get:
cleaner_robot GET /robots/:id/cleaner(.:format) {:controller=>"robots", :action=>"cleaner"}
So why, then, when I point my browser at http://localhost:3000/, do I get the following?
ActionController::RoutingError in Robots#index
Showing /Users/steven/Code/skynet/app/views/robots/index.html.haml where line #1 raised:
No route matches {:action=>"cleaner", :controller=>"robots"}
Extracted source (around line #1):
1: = link_to "test", cleaner_robot_path
Rails.root: /Users/steven/Code/skynet
Application Trace | Framework Trace | Full Trace
app/views/robots/index.html.haml:1:in `_app_views_robots_index_html_haml___2129226934_2195069160_0'
app/controllers/robots_controller.rb:4:in `index'
Request
Parameters:
None
Show session dump
Show env dump
Response
Headers:
None
you defined cleaner as a member function of the resource robots this means you have to supply an id as you can see in your rake routes message /robots/:id/cleaner(.:format)
So your link should look like
= link_to "test", cleaner_robot_path(some_id)
but
I think you want to use cleaner as a collection function:
Skynet::Application.routes.draw do
resources :robots do
collection do
get "cleaner"
end
end
end
then your link has to look like:
= link_to "test", cleaner_robots_path
Notice that robot is now plural!
According to your error message I guess you've tried that but used the collection in plural... Maybe you have to restart your server if you are in production mode.
You can read more about this routing stuff in the Ruby on Rails Guide
Related
I am trying to add a post action button to upload a CSV to get data from CSV into postGreSQL database. But getting the following error(copied the error from request response of chrome devtools)
NoMethodError in Admin::UnitsController#import
undefined method `content_type' for nil:NilClass
Extracted source (around line #15):
#13 file = params[:file]
#14
*15 return redirect_to import_admin_tenant_site_units_path, notice: 'Only CSV please' unless file.content_type == "text/csv"
I have tried the following which is giving me the error.
Following the routes.rb
namespace :admin do
get '', to: 'dashboard#index', as: 'root'
# resourceful routes
resources :oauth_clients
resources :tenants do
resources :sites do
#resources :production_shifts
resources :units do
resources :log_data_fields, only: [:create, :index]
# collection route
collection do
post :import #post action
end
member do
get :logs
get :export_log
end
resources :reports
resources :grafana_dashboards
resources :data_adapters, except: [:show]
get 'data_adapters/start'
end
end
resources :users
resources :login_activities
# resources :login_activities
end
end
where post action "import" is of concern currently for this error.
I have included the import method's logic in the units_controller.rb as follows :
class Admin::UnitsController < Admin::BaseController
# import request(this is gonna be a POST action)
def import
logger.debug("*****Testing the logger.*****")
file = params[:file]
return redirect_to import_admin_tenant_site_units_path, notice: 'Only CSV please' unless file.content_type == "text/csv"
file = File.open(file)
csv = CSV.parse(file, headers: true)
binding.b
redirect_to import_admin_tenant_site_units_path, notice:"Imported tags !"
end
More things are to be done and I cannot even show complete code in public due to restricted reasons.
My rails debugging gem debug doesnt work either means it doesnt gets invoked even after mentioning it there as binding.b. Earlier it was working few days back but I dont know what mistakes I did.
And Sorry for poor explaining language.
Here I am also showing the frontend view code of the part where the csv file gets uploaded from. importtags.html.haml :
%p{:style => "color: green"}= notice
= form_with model:#log_data_field, url: import_admin_tenant_site_units_path, method: :post do |form|
- if #log_data_field.errors.any?
#error_explanation
%h2= "#{pluralize(#log_data_field.errors.count, "error")} prohibited this log_data_field from being saved:"
%ul
- #log_data_field.errors.full_messages.each do |message|
%li= message
= form.file_field :file, accept: ".csv"
<br>
<br>
-#button.btn.primary{:type => "submit", data: { disable_with: "Please wait..."}}
%button.btn.primary{:type => "submit"}
-#= form.button "Import"
= "Import"
PS : -# are indicating comments in the above haml code.
params[:file] is nil so the local file variable is going to be nil as well.
In the rails log you can see the params hash usually after Started POST and Processing by lines like Parameters: {...}
But you can always just use puts inside the controller to debug like p params to see its content.
I bet the file key inside the params hash is going to be nested under the name of your model.
Try file = params[:YOUR_MODEL_NAME][:file]
Maybe file = params[:log_data][:file]?:D
I am trying to go through the 'Ruby on Rails Getting Started' tutorial(guides.rubyonrails.org) and I am running into this issue I cannot seem to figure out. I reached the point in the tutorial where I can create an article, but the redirect to see the article immediately after creation does not work and I get an error that says:
NoMethodError in Blog::ArticlesController#create
undefined method `article_url' for #<Blog::ArticlesController:0x00007f814841af20>
Here is my article controller code:
class Blog::ArticlesController < ApplicationController
def new
#article = Article.new
end
def create
#article = Article.new(params.require(:article).permit(:title, :category, :text))
#article.save
redirect_to #article # <-- This line throws error
end
def show
#article = Article.find(params[:id])
end
end
and here is my routes.rb (omitted irrelevant code):
Rails.application.routes.draw do
# <-- other get functions here
get 'blog', to: 'blog#index'
namespace :blog do
resources :articles # <-- Suggestions were to make these plural
end
root 'about#index'
end
The only deviation I have done from the tutorial is that I wanted to place the articles in a name space, as well as 1 extra value to enter in the form(category). The only suggestions for fixing my issue when I searched was to make resource into plural but my code already has this and to add #article = Article.new into def new in the controller but this addition made no difference.
I found a work around that will properly redirect after creating a new article that is the line as follows:
redirect_to :action => "show", :id => #article.id
But this doesn't seem like the "Rails Way"(Convention over Configuration), and I really don't understand why the suggested code in the tutorial is not working for me
The Rails-ey way to redirect to the proper route would be to first check in the terminal with rails routes.
There you will see if you want to route to articles#show under the namespace blog that the prefix (first column) is blog_article.
You can use this prefix with the _path method like so:
redirect_to blog_article_path(#article)
I'm trying to create a view with a button calling a controller action for a Redmine Plugin (unfortunately, I'm quite new at Rails). I'd need to create a method for my controller (here A Controller) so i can update some Active Records.
I created a controller:
redmine_a_controller.rb
class RedmineAController < ApplicationController
def prova(input)
puts input
return input
end
def p
puts 'vuoto'
returns 'vuoto'
end
end
The actions work correctly when called from the console. Unfortunately, when called from my view _a.html.erb:
<%=
button_to l(:imp_update), {
:controller => 'RedmineAController',
:action => 'p',
method: :post
}
%>
It returns this error:
ActionView::Template::Error (No route matches {:action=>"p", :controller=>"RedmineAController", :id=>"prova", :method=>:post, :tab=>"important_users"}):
I tried by calling the action on a new instance:
<%=
button_to l(:imp_update), {
:action => RedmineImportantUsersController.new.prova(1),
method: :post
}
%>
but it looks for the action in the Projects controller
ActionView::Template::Error (No route matches {:action=>"1", :controller=>"projects", :id=>"prova", :method=>:post}):
How can I make button_to call the correct prova method in the RedmineAController controller?
Thanks in advance for any help.
Add routes in routes.rb file
resources :redmine_as do
collections do
post :a
end
end
After that, Please fine the Routes url by typing on terminal below command
rake routes | grep p
Set the url in Link or button
link_to "Your Link Name", p_redmine_as_path
p_redmines_path it will be return by that "rake routes
| grep p" command.
As Ketan indicated, I was missing a route!
I put in my routes.rb:
resources :important_user do
collection do
post :u_update
end
end
and in my controller:
def u_update
puts params[:p_id]
puts "update!"
end
I'm having issues with my static pages strategy on rails.
I have a controller that handles static pages. Basically, it reads templates in the app/views/static directory and render as asked. Like so:
class StaticController < ApplicationController
def show
templ = File.join(params[:controller], params[:page])
puts params, templ
render templ
rescue ActionView::MissingTemplate => e
if e.message =~ %r{Missing template #{templ}}
raise ActionController::RoutingError, 'Not Found'
else
raise e
end
end
end
These are my routes:
Rails.application.routes.draw do
root 'static#show', page: 'home'
get ':page', to: 'static#show', as: :static, constraints: { page: /a-zA-Z\-_\/+/ }
end
The root route works fine, I am able to access the view just fine. I get no errors.
Now, on my header partial, I have this, edited for simplicity/relevance:
<%= link_to('Home', static_path(:home)) %>
There is no other ruby code in the partial or the main template. I'm not sure what I'm doing wrong. The error just does NOT make sense.
ActionController::UrlGenerationError - No route matches {:action=>"show", :controller=>"static", :format=>nil, :page=>:home} missing required keys: [:page]
Where exactly is the required key missing from? I don't have any objects other or models.
Now this works just fine:
<%= link_to('Home', controller: 'static', action: 'show', page: 'home') %>
So how do I make static_path work like that?
Thanks.
I think there's a problem with the regexp your using for the constraint, I'd suggest dropping it from the route definition, as you already check if template is present in the controller.
Also, you should check out high_voltage gem which handles creating static pages quite nicely.
My first guess would be:
<%= link_to 'Home', static_path("home") %> #-> try passing a string, rather than symbol
This should allow you to reference the required path
--
class StaticController < ApplicationController
def show
templ = File.join(params[:controller], params[:page])
puts params, templ
render templ
rescue ActionView::MissingTemplate => e
if e.message =~ %r{Missing template #{templ}}
raise ActionController::RoutingError, 'Not Found'
else
raise e
end
end
end
I would personally make this a lot simpler:
class StaticController < ApplicationController
def show
render "pages#{params[:page]}
end
end
I have models Drill and Exercise. Exercises belong to Drills and I have routes.rb with:
resources :drills do
resources :exercises do
end
Therefore it is not surprising to see this output from rake routes:
drill_exercises GET /drills/:drill_id/exercises(.:format) exercises#index
POST /drills/:drill_id/exercises(.:format) exercises#create
new_drill_exercise GET /drills/:drill_id/exercises/new(.:format) exercises#new
edit_drill_exercise GET /drills/:drill_id/exercises/:id/edit(.:format) exercises#edit
drill_exercise GET /drills/:drill_id/exercises/:id(.:format) exercises#show
PUT /drills/:drill_id/exercises/:id(.:format) exercises#update
DELETE /drills/:drill_id/exercises/:id(.:format) exercises#destroy
What is surprising is that this line of code:
<%= link_to t('.new', :default => t("helpers.links.prompt")),
new_drill_exercise_path,
:class => 'btn btn-primary', :remote => true %>
Is resulting in this error:
ActionController::RoutingError at /drills/6/edit
No route matches {:action=>"new", :controller=>"exercises"}
Despite the fact that when I call controller.methods in IRB one of the results I get back is :new_drill_exercise_path
So... what's up with that?
More info:
exercises_controller.rb
class ExercisesController < InheritedResources::Base
def new
#drill = Drill.find(params[:id])
#exercise = Exercise.new
respond_to do |format|
format.html { redirect_to(:action => 'edit') }
format.js
end
end
end
You are missing the drill_id that is required for the path. Try:
new_drill_exercise_path(#drill)
or:
new_drill_exercise_path(params[:id]) # assumes this is inside `DrillsController#show` or similar