View:
!!!
%html
%head
%title= full_title(yield(:title))
=stylesheet_link_tag "application", media: "all"
=javascript_include_tag "application"
=csrf_meta_tags
=render 'layouts/shim'
%body
=render 'layouts/header'
.container
=flash.each do |key, value|
%div{class: "alert alert-#{key}"} #{value}
Controller
def create
#user = User.new(params[:user])
if #user.save
flash[:success] = "This is Correct"
redirect_to #user
else
flash[:wrong] = "no"
render 'new'
end
end
Regardless of the flash (:success or :wrong or otherwise) it always compiles the entire hash as html (below)
Output:
<!DOCTYPE html>
…
<div class='container'>
<div class='alert alert-wrong'>no</div>
{:wrong=>"no"}
</div>
</body>
</html>
I have no idea why {:wrong=>"no"} is being displayed. I've been staring at this terminal for hours. What's interesting is that the hash is being outputted with the container id, but not in the alert class. It feels like an indentation problem, but I went through several permutations with no success.
You need to use a - rather than a = when you call the each block:
-flash.each do |key, value|
%div{class: "alert alert-#{key}"} #{value}
From the docs:
It’s also possible to embed Ruby code into Haml documents. An equals sign, =, will output the result of the code. A hyphen, -, will run the code but not output the result.
So you're seeing the hash because = will output the result of the each block (the hash itself, i.e. {:wrong=>"no"}).
Related
I'm trying to learn web development as I go (I just need need to get this one project done. I don't plan on touching the subject ever again.) and I've run into the problem of getting data from a rails web page to its corresponding controller. My end goal is to get data from javascript variables and pass that to ruby, but I've decided to take small steps so for now I'm trying to get a button_to to send some hard coded strings from the new.html.erb to the corresponding create method in the controller. I've probably tried a hundred combinations of view, controller and, routs code and I can't get any of them to work. Here is the current iteration of my code for the controller, view, and routes (I'm not sure if routes even matters).
ponies_controller.rb
def create(name, pro)
##pony = Pony.new(params[:id])
#pony = Pony.new(name: name, profession: pro)
respond_to do |format|
if #pony.save
format.html { redirect_to #pony, notice: 'Pony was successfully created.' } |~
format.json { render :show, status: :created, location: #pony }
else
format.html { render :new }
format.json { render json: #pony.errors, status: :unprocessable_entity }
end
end
end
new.html.erb
<h1>New Pony</h1>
<%= render 'form', pony: #pony %>
<%= link_to 'Back', ponies_path %>
<%= button_to "create_pony", {action: create("s","ss")}, remote: true,from_class: "create_pony" %>
routes.rb (Not sure if this is important)
Rails.application.routes.draw do
resources :ponies
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
post 'ponies/:id/create' => 'pony#create', as: :create_pony
end
While this code doesn't work I think it shows how I think things should work. I feel like I should just be able to call the method and be done with things, but that is obviously wrong. What should I be doing to get button_to to post a new "pony"?
Here's the Rails way to do this in the simplest way (assuming you've set up your Pony model correctly):
# ponies_controller.rb
def create
#pony = Pony.new(pony_params)
if #pony.save
# success
else
# errors
end
end
private
def pony_params
params.require(:pony).permit(:name, :profession) # whitelist the parameters you want to accept from the pony creation form
end
and your pony form should like this
# new.html.erb
<h1> New Pony </h1>
<%= form_for #pony, remote: true do |f| %>
<%= f.text_field :name %> # this will be passed to the controller in the params hash
<%= f.text_field :profession %> # this too
<%= f.submit %>
<% end %>
also, resources :ponies will create all the routes you need for ponies so no need to define one yourself.
One of my model objects has a 'text' column that contains the full HTML of a web page.
I'd like to write a controller action that simply returns this HTML directly from the controller rather than passing it through the .erb templates like the rest of the actions on the controller.
My first thought was to pull this action into a new controller and make a custom .erb template with an empty layout, and just <%= modelObject.htmlContent %> in the template - but I wondered if there were a better way to do this in Rails.
In your controller respond_to block, you can use:
render :text => #model_object.html_content
or:
render :inline => "<%= #model_object.html_content %>"
So, something like:
def show
#model_object = ModelObject.find(params[:id])
respond_to do |format|
format.html { render :text => #model_object.html_content }
end
end
In latest Rails (4.1.x), at least, this is much simpler than the accepted answer:
def show
render html: '<div>html goes here</div>'.html_safe
end
Its works for me
def show
#model_object = ModelObject.find(params[:id])
respond_to do |format|
format.html { render :inline => "<%== #model_object['html'] %>" }
end
end
I want to make an Navigation with specific Tags.
These Tags are for example: HTML, CSS and Javascript.
So when i click on one of them it will show all posts with these tag.
How can i achieve that?
My code for the Navigation right now looks like this (it's in the Application.html.erb)
<%= link_to "Computer", tag_list.Computer %>
I get this Error:
undefined local variable or method `tag_list' for #<#:0x007feec764ff88>
tag_list is a local variable or method, so unless you've created it in a helper that's your first issue. The second is that called .Computer on it doesn't work because tag_list is a method that created by the gem to list all an objects tags, and calling the . (also knowing as chaining) is attempting to call a method named Computer, which doesn't exist, that should just be a string and strings have to be quoted.
So, in your layout view, you can do
= link_to "Computer", tagged_posts_url(tag: "Computer")
Then in your posts_controller.rb add an action called tagged
def tagged
if params[:tag].present?
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.all
end
end
To maintain a DRY set of views, you can even tell it to render the index view since you most likely already have a list of posts, now it will look exactly the same but only contain posts with that tag. e.g.
def tagged
if params[:tag].present?
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.all
end
render "index"
end
Then in your config/routes.rb add a route for your new controller action under your existing post route
resources :posts do
collection do
get "/posts/tagged", as: :tagged
end
I got it myself.
Here is the Code:
<%= link_to 'Computer', { :controller => 'posts', :action => 'index', :tag => 'Computer'} %>
The controller looks like this:
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag]).order('created_at DESC')
else
#posts = Post.all.order('created_at DESC')
end
end
I don't like the way rails does page titles by default (just uses the controller name), so I'm working on a new way of doing it like so:
application controller:
def page_title
"Default Title Here"
end
posts controller:
def page_title
"Awesome Posts"
end
application layout:
<title><%=controller.page_title%></title>
It works well because if I don't have a page_title method in whatever controller I'm currently using it falls back to the default in the application controller. But what if in my users controller I want it to return "Signup" for the "new" action, but fall back for any other action? Is there a way to do that?
Secondly, does anyone else have any other ways of doing page titles in rails?
I disagree with the other answers, I believe the title shouldn't be set per action, but rather within the view itself. Keep the view logic within the view and the controller logic within the controller.
Inside your application_helper.rb add:
def title(page_title)
content_for(:title) { page_title }
end
Then to insert it into your <title>:
<title><%= content_for?(:title) ? content_for(:title) : "Default Title" %></title>
So when you are in your views, you have access to all instance variables set from the controller and you can set it there. It keeps the clutter out of the controller as well.
<%- title "Reading #{#post.name}" %>
I like to put a catchall, default title in my layout that can be overridden from an action by setting #title:
<title><%= #title || "Default Title Here" %></title>
Then you can generate a title in your action:
def show
#post = Post.find_by_id params[:id]
#title = "tybro's blog: #{#post.title}"
end
I would do this:
# Application Controller
before_filter :set_page_title
private
def set_page_title
#page_title = "Default Title"
end
overwrite it in your other controllers
# Users Controller
before_filter :set_page_title
def new # in Users controller
...
#page_title = "Sign up"
...
end
private
def set_page_title
#page_title = "Users"
end
In your view:
<title><%= h #page_title %></title>
Have a look at Ryan Bates (ryanb from railscasts.com) nifty layout. He has a method in there that does what you are looking for. It's similar to Garrett's way, only he moves the default values in the helper too. Check out the helper.rb file and how he link textuses it.
You can install is as gem (and use the other nice features) or just use his way of doing it. You only need to pass the title value to title in each view (or let it fall to the default) and there you go. I'm with Garrett to put these things in the view.
Layout template
In your layout (e.g. application.html.erb) add:
<title><%= content_for(:page_title) || "Fallback title" %></title>
Page template
In the page template you'd like to a specify a title from:
<%- content_for(:page_title, "Specific page title") %>
class ApplicationController < ActionController::Base
before_action :set_page_title
private
def set_page_title
#page_title = t(".page_title", default: '').presence || t("#{controller_name}.page_title", default: '').presence || controller_name.titleize
end
end
I recently started taking this approach then outputting #page_title in the layout. It seems to work quite nicely for me.
I would like to use HTML 4.01 Strict, and used a DOCTYPE of it in my application template. But look like when a style sheet is included by a helper function
<%= stylesheet_link_tag 'style' %>
the code produced is XHTML:
<link href="/stylesheets/style.css?1243210734" media="screen" rel="stylesheet" type="text/css" />
is there a way to ask Rails to produce HTML instead of XHTML? (so that the HTML will validate for example)
Just a quick fix to the included code above, which does work.
module ActionView::Helpers::TagHelper
def tag_with_html(name, options = nil, open = true, escape = true)
tag_without_html(name, options, true, escape)
end
alias_method_chain :tag, :html
end
Thanks for the tip!
Not really, no.
Edit: in line with my comment below, this should work (I still feel uneasy, but I can't think of anything that will break because of this)
module ActionView::Helpers::TagHelper
def tag_with_html(name, options = nil, open, escape = true)
tag_without_html(name, options, true, escape)
end
alias_method_chain :tag, :html
end