def show
render :text => params.inspect
end
What is render :text =>?
What is render, :text, and the =>?
Are they standard ruby?
The syntax you see used in that code snippet is not limited to render(), but it is common with many other Ruby on Rail methods.
The method is accepting a hash map, using a simplified syntax.
The code is equivalent to
def show
render({:text => params.inspect})
end
Other code snippets that include the same syntax are:
def sign
Entry.create(params[:entry])
redirect_to :action => "index"
end
url_for :controller => 'posts', :action => 'recent'
url_for :controller => 'posts', :action => 'index'
url_for :controller => 'posts', :action => 'index', :port=>'8033'
url_for :controller => 'posts', :action => 'show', :id => 10
url_for :controller => 'posts', :user => 'd', :password => '123'
def show
#article = Article.find(params[:id])
fresh_when :etag => #article, :last_modified => #article.created_at.utc, :public => true
end
render is rails API. See doc. For everything else, let me recommend you something and you will understand.
the syntax you have posted is a prettier way of writing
render({:text => "hello world"})
basically, you are calling a method, passing in a Hash object (which is a collection of key value pairs). The hash contains 1 pair, with a key of :text (: indicating it is a symbol called text), the value being a string of "hello world"
I think you should really be reading the ruby getting started guides before digging too deep in to rails.
The render :text idiom is for rendering text directly to the response, without any view. It's used here for debugging purposes, it's dumping the contents of the params hash to the response page without going through the page view.
render :text => "hello world!"
Renders the clear text "hello world" with status code 200
This is what the :text => ... means
refer http://api.rubyonrails.org/classes/ActionController/Base.html
Related
How to get the xml output of a view/controller as string within the same controler
This is the routes file
routes.rb
map.ccda '/ccda/ccda_patient_search', :controller => 'ccda', :action => :ccda_patient_search
map.ccda '/ccda/:id.:format', :controller => 'ccda', :action => :index
ccda_controller.rb
class CcdaController < ApplicationController
def index
#
# some process
# result = User.find(params[:id]).result
#
#ccda = result
respond_to do |format|
format.xml { render :layout => false, :template=> "index.xml.builder" }
format.any { redirect_to login_url }
end
end
def get_xml
# render_to_string 'index', :layout=>false, :formats=>[:xml], :locals=>{:id=>147} => Not working
# render_to_string '147.xml' => Not working
#
# How do I get the output of 'http://localhost/ccda/147.xml' here???
#
end
end
I will use the url localhost/ccda/147.xml to view/generate the users result as xml
Now I want the output of that url as a string without returning to browser
I've tried to get it from same controller using render_to_string method with diffrent parameters but nothing seems to work
FYI: I am using rails 2.3.12 and Builder::XmlMarkup API
How about using the following call (inside controller, have taken the known options from your question):
render_to_string(:template => 'ccda/index.xml.builder', :layout => false, :id => 147)
Due to the documentation, this will work up to Rails version 2.3.8, so I don't know if it is available any more in Rails 2.3.12 you are using.
PS: How about upgrading to at least last version of Rails 3? I don't have a change to test my solution, so it is guesswork more or less.
How about this below?
render_to_string :controller => 'ccda_controller', :action => 'index', :id => 147, :format => :xml
Finally I've found that we need to specify the view file manually because by default rails will be looking for index.erb so what I've done is this
render_to_string( :action=>"index", :view => "/ccda/index.xml.builder", :format=>:xml,:layout=>false,:id=>146, :template=>"/ccda/index.xml.builder" )
specifying :view and :template manually solved my problem
I have read up on other people's posts about this and I still can't get my head wrapped around the problem I am having. So I thought I would ask.
I have a form that gets for uploading an avatar.
This form is displayed from :controller => 'board', :action => 'show'
<% form_tag("avatar/upload", :multipart => true ) do %>
<%= error_messages_for :avatar %>
...
This works great. Problem is that I can't get the error messages to display.
The upload is handled by :controller => 'avatar', :action => 'upload'
if params_posted?(:avatar)
image = get_image(params)
#board = Board.find(session[:board_id])
#avatar = Avatar.new(#board.id, image)
if #avatar.save
# ???
end
end
Now this is the part that I have trouble with. I know I can't do a redirect_to or I will lose the error_messages_for #avatar and thus get no error messages but doing a render is a problem because I have some routes.
In my routes.rb I have the following:
map.connect 'board/celebrating/:id/:name', :controller => 'board', :action => 'show'
So what I want to know is how to display the board again located at :controller => 'board', :action => 'show' and display the error messages for #avatar?
Sorry if this seems trivial. To me its been a struggle.
Thank you in advance.
Mitchell
You can do it by rendering a template instead of redirecting or rendering an action. For example, if you want to render the boards/show.html.erb on a failure, you would do the following:
if params_posted?(:avatar)
image = get_image(params)
#board = Board.find(session[:board_id])
#avatar = Avatar.new(#board.id, image)
if #avatar.save
...
else
render :template => 'boards/show'
end
end
Keep in mind that the BoardsController#show action will not be run, so your flash messages and instance variables (#avatar, #board) will be preserved.
I've added a method inside of an existing Rails controller (reports_controller) to handle a specific action that is beyond the basic scope of REST. Let's call that action 'detail':
def detail
#report = Report.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #report }
end
end
I added the appropriate layout page (detail.html.erb) and routing to make sure that I can access the page from anywhere. This is how my route looks like:
map.connect "reports/:action", :controller => 'reports', :action => /[a-z]+/i
Right now I'm able to access any of the detail pages. An example page would look like this: http://127.0.0.1:3000/reports/detail/8
Now, I'm trying to create a link from the main Report index page to the detail pages, but when using the code below:
<%= link_to "Details", {:controller => "reports", :action => "detail", :id => #report }, {:title => "see details for this report"} %>
The link that is created does not include the report's ID on it an looks like this:
http://127.0.0.1:3000/reports/detail
Any idea of what's wrong with what I'm doing?
Thanks!
I think you might be looking for :member:
map.resources :reports, :member => { :detail => :get }
Using link_to:
link_to "Detail", detail_report_path(#report)
Syntax error, maybe?
Try no comma right after #report
I've got a simple Rails application running as a splash page for a website that's going through a transition to a new server. Since this is an established website, I'm seeing user requests hitting pages that don't exist in the Rails application.
How can I redirect all unknown requests to the homepage instead of throwing a routing error?
I just used route globbing to achieve this:
map.connect "/*other", :controller => "pages", :action => "index"
Note that this route should be at the end of routes.rb so that all other routes are matched before it.
You can use the following ways to handle errors in a common place. Place this code in you ApplicationController
def rescue_404
#message = "Page not Found"
render :template => "shared/error", :layout => "standard", :status => "404"
end
def rescue_action_in_public(exception)
case exception
when CustomNotFoundError, ::ActionController::UnknownAction then
#render_with_layout "shared/error404", 404, "standard"
render :template => "shared/error404", :layout => "standard", :status => "404"
else
#message = exception
render :template => "shared/error", :layout => "standard", :status => "500"
end
end
Modify it to suit your needs, you can have redirects as well.
HTH
I've just added a contact form to my Rails application so that site visitors can send me a message. The application has a Message resource and I've defined this custom route to make the URL nicer and more obvious:
map.contact '/contact', :controller => 'messages', :action => 'new'
How can I keep the URL as /contact when the model fails validation? At the moment the URL changes to /messages upon validation failure.
This is the create method in my messages_controller:
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = 'Thanks for your message etc...'
redirect_to contact_path
else
render 'new', :layout => 'contact'
end
end
Thanks in advance.
One solution would be to make two conditional routes with the following code:
map.contact 'contact', :controller => 'messages', :action => 'new', :conditions => { :method => :get }
map.connect 'contact', :controller => 'messages', :action => 'create', :conditions => { :method => :post } # Notice we are using 'connect' here, not 'contact'! See bottom of answer for explanation
This will make all get request (direct requests etc.) use the 'new' action, and the post request the 'create' action. (There are two other types of requests: put and delete, but these are irrelevant here.)
Now, in the form where you are creating the message object change
<%= form_for #message do |f| %>
to
<%= form_for #message, :url => contact_url do |f| %>
(The form helper will automatically choose the post request type, because that is default when creating new objects.)
Should solve your troubles.
(This also won't cause the addressbar to flicker the other address. It never uses another address.)
.
Explanation why using connect is not a problem here
The map.name_of_route references JUST THE PATH. Therefore you don't need a new named route for the second route. You can use the original one, because the paths are the same. All the other options are used only when a new request reaches rails and it needs to know where to send it.
.
EDIT
If you think the extra routes make a bit of a mess (especially when you use it more often) you could create a special method to create them. This method isn't very beautiful (terrible variable names), but it should do the job.
def map.connect_different_actions_to_same_path(path, controller, request_types_with_actions) # Should really change the name...
first = true # There first route should be a named route
request_types_with_actions.each do |request, action|
route_name = first ? path : 'connect'
eval("map.#{route_name} '#{path}', :controller => '#{controller}', :action => '#{action}', :conditions => { :method => :#{request.to_s} }")
first = false
end
end
And then use it like this
map.connect_different_actions_to_same_path('contact', 'messages', {:get => 'new', :post => 'create'})
I prefer the original method though...
I just came up with a second solution, guided by Omar's comments on my first one.
If you write this as your resources route
map.resources :messages, :as => 'contact'
This gives (amongst others) the following routes
/contact # + GET = controller:messages action:index
/contact # + POST = controller:messages action:create
So when you move your 'new' action code into your 'index' action, you will have the same result. No flicker and an easier to read routes file. However, your controller will make no more sense.
I, however, think it is a worse solution because you'll soon forget why you put your 'new' code into the index action.
Btw. If you want to keep a kind of index action, you could do this
map.resources :messages, :as => 'contact', :collection => { :manage => :get }
This will give you the following route
manage_messages_path # = /contact/manage controller:messages action:manage
You could then move your index action code into the manage action.
I suspect you are posting to '/messages' from the form which creates the message which explains why you see that in your URL.
Any reason why this won't work:
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = 'Thanks for your message etc...'
redirect_to contact_path
else
flash[:notice] = 'Sorry there was a problem with your message'
redirect_to contact_path
end
end
Not to my knowledge, no. Since im assuming you want to render so that you keep the #message object as is with the errors attached.
There is a horrible solution that I have which will let you do it, but, its so horrible, I wouldn't recommend it:
before_filter :find_message_in_session, :only => [:new]
def new
#message ||= Message.new
end
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = 'Thanks for your message etc...'
redirect_to contact_path
else
flash[:notice] = 'Sorry there was a problem with your message'
store_message_in_session
redirect_to contact_path
end
end
private
def find_message_in_session
#message = session[:message]; session[:message] = nil
end
def store_message_in_session
session[:message] = #message
end