Ruby - writing a basic controller - ruby-on-rails

I am trying to learn Ruby on Rails and trying to write some of the code by hand so that I learn how it works.
I made this tiny controller:
class TestsController < ApplicationController
def test
def show
render :text => "Hi from TestsController!"
end
end
end
and this is what is left of my view:
<h3> Hello test </h3>
and this is my routes.rb snippet:
resource :test
but it gives an error that: The action 'show' could not be found for TestsController
Thanks!
This is the output of rake routes:
home_index GET /home/index(.:format) home#index
root / home#index
test POST /test(.:format) tests#create
new_test GET /test/new(.:format) tests#new
edit_test GET /test/edit(.:format) tests#edit
GET /test(.:format) tests#show
PUT /test(.:format) tests#update
DELETE /test(.:format) tests#destroy

A basic controller looks like this:
class TestsController < ApplicationController
def show
end
end
You do not need the respond_to block if you only want to render the default view (in this case: app/views/tests/show.html.erb). The respond_to block is when you have some more advanced needs.

What #klump said is correct. Try running a basic scaffold. This will generate a controller, model and views for you. This generator is great when you are learning rails.
rails g scaffold Test
Also check out http://www.railsforzombies.com as it is a great way to learn rails.

You use respond_to when you want your action to respond to multiple formats. Client sets it's desired format in HTTP Accept header.
You can then specify different action for each format.
Example
def show
respond_to do |format|
format.html { Rails.logger.debug "rendering show.html" }
format.xml { Rails.logger.debug "rendering show.xml" }
format.js { Rails.logger.debug "rendering show.js" }
end
end
Refer to the API for more examples.

Related

`redirect_to #article` throws the `NoMethodError in Blog::ArticlesController#create` error

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)

Rails Routing: How to have controllers in series to respond to same matching path

In my Rails routes.rb file I'm wanting to do something like the following.
get '/:id' => 'pages#show'
get '/:id' => 'articles#show'
So that if a visitor types in
http://www.example.com/about-this-site
The pages controller in the above example would get first shot at handling it. Then if not, the next controller in line would get a shot.
REASONs for wanting to do this:
1) I'm trying to port my Wordpress site over without establishing new urls for all my pages and blog posts. As it stands, all of my blog post files and pages are accessed directly off the root uri '/' folder.
2) Because I'm not able to, it's a learning thing for me. But, I want to do it without a hack.
How about redirecting to the second controller from your first controller?
in PagesController
def show
unless Page.find_by(id: params[:id])
redirect_to controller: :articles, action: :show, id: params[:id]
end
end
in ArticlesController
def show
# Handle whatever logic here...
end
Edit
If you really don't want to redirect then you can consolidate the logic into a single action:
def show
if Page.find_by(id: params[:id])
render :show
elsif Article.find_by(id: params[:id])
render controller: :articles, action: :show
else
# Handle missing case, perhaps a 404?
end
end
However, I'd recommend using a redirect if possible. It's a cleaner solution and keeps your controller code isolated.

Ruby on rails - Template missing prob

I am having a hard time solving this problem because this is my first time to learn ruby on rail, i have a index.html.erb, new.html.erb, show.html.erb, edit.html.erb files. So when i go to localhost:3000/blogs/edit page the page that is showing is show.html.erb and when i delete the show.html.erb then access the edit.html.erb im having a template missing error. but when i access localhost:3000/blogs/new or just localhost:3000/blogs its working fine.So here's my code inside blogs_controller.rb
class BlogsController < ApplicationController
def index
#content_first = 'This 1' ;
#content_two = 'This 2' ;
end
def new
end
def create
end
def edit
end
def update
end
def show
end
def destroy
end
end
I think your problem is that you're trying to access /blogs/edit , and the route is probably /blogs/edit/:id. As in you need to provide the id of a blog object, so that you can edit it.
If you run
rake routes
You will be able to see your available routes.
Hope this helps =)

preview page signup redirecting to another static page error

I have a preview page up with a form that takes in emails(#premails). I've created a model & migration for this.
I have a pages controller with a Home, About & Contact actions and corresponding views.
After they submit their email on the Home page, I want to redirect them to a static About page. I have not been able to achieve this.
this is my pages controller:
class PagesController < ApplicationController
def home
#premail = Premail.new
if #premail.save
redirect_to about_path
else
render home_path
end
end
def about
end
end
But when I open my localhost with this code I get:
NameError in PagesController#home
undefined local variable or method `about_path' for #<PagesController:0x337ac40>
How can I make this happen?
For your case, use:
if #premail.save
redirect_to :action => :about
end
else is not needed here, since by default Rails would render app/views/pages/home.html.erb, be sure you have this file.
Also when you redirect to about, you will need app/views/pages/about.html.erb file to be present.
Update
Seems you don't have this route in config/routes.rb, for Rails 3.x:
match ':controller(/:action(/:id))'
In Rails 4:
match ':controller(/:action(/:id))', :via => [:get , :post]
If you are planning to just answer to get, i.e. there are nor forms posting to controllers:
get ':controller(/:action(/:id))'
This will detect routes like localhost:3000/asd/qwe/1 and:
Use asd as controller AsdController
Use qwe as action:
class AsdController
def qwe; end
params[:id] would be equal to 1.
() means optional, for example if you go in your browser to localhost:3000/asd, Rails would call Asd#index, i.e.:
class AsdController
def index
# whatever you have here
end

How do I add different types of GET routes that require parameters in Ruby on Rails

I have a list of users being displayed, you can click on "Show user" or "PDF" to see details of that user in HTML or as a PDF document. The show was automatically created with scaffolding, now I'm trying to add the option to view it as a PDF. The problem is adding a second GET option, if I pass the user along as a parameter, it is assumed to be a POST and I get an error that the POST route does not exist. I am not trying to update the user, just to show it in a different way, basically to add a second "show user" option.
How do I tell it that I want a GET, not a POST? Is there an easier way to do what I am trying to do? Thanks.
Please, create a controller like this:
class ClientsController < ApplicationController
# The user can request to receive this resource as HTML or PDF.
def show
#client = Client.find(params[:id])
respond_to do |format|
format.html
format.pdf { render pdf: generate_pdf(#client) }
end
end
end
Please, update route.rb file, action name with post and get, like below :
match 'action_name', to: 'controller#action', via: 'post'
match 'action_name', to: 'controller#action', via: 'get'
More info please read this link : "http://guides.rubyonrails.org/routing.html"
you haven't posted any code or details, so I am guessing you want something like this:
routes
resources :users
controller
class UsersController < ActionController::Base
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.pdf # handle the pdf response
end
end
end
view file in views/users/show.pdf.prawn
prawn_document() do |pdf|
#user.each {|r| pdf.text r.id} # will print user id of the user
end
The way above example will work is, if something visits the following URLs, they will get html file:
localhost:3000/users/1 #html is the default format in rails
localhost:3000/users/1.html
but if they visit .pdf, they will be served a pdf format.
localhost:3000/users/1.pdf
If the above assumptions are correct, then check prawn or wicked_pdf pdf gem. the above example uses prawn
Checkout this link http://apidock.com/rails/ActionController/MimeResponds/InstanceMethods/respond_to. You can add a new MIME type and pass on the :format as pdf in all your rails routes.
Hope this will help.
And for the POST-request check your
config/routes.rb
There shoud be a few routes already, so you can infer the route you need.
In your link you can pass an additional parameter called format for pdf. For e.g.
<%= link_to 'Display in PDF', "/user/pdf", :format => "pdf" %>

Resources