Application.html.erb in rails 4 - html

I am new to rails 4.0.2 .
I am working on a application with rails version 4 and ruby 2. In views the application.html.erb file is not working. It is not replicating on all the view files.
This is my code in application.html.erb file:
<!DOCTYPE html>
<html>
<head>
<title>Myapp</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
I have a controller named xyz_controller.rb which has the following code:
class xyzController << ApplicationController
end
The application_controller.erb file has the following code:
class ApplicationController < ApplicationController
def login
end
end
The login.erb file contains the normal html code.
Thanks in advance.

Your application controller should look like this:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end
Your XYZ controller should look like this:
class XyzController < ApplicationController
def action
#here you define instance variables used in your view for this action
end
...
end
... so your login action, for instance, would be defined there.
Your view should be named action.html.erb, where action matches your controller action and that file should be in app/views/xyz.
The Rails mantra is convention over configuration. This means that everything will be a lot easier if you (very closely) follow the Rails conventions for naming, etc. I strongly recommend working your way through a good tutorial like Hartl's if you haven't already.
Hope this helps.

Related

Trying to load a view in application layout and calling its action on every page

I am trying to load a view with a list of Product Type. I need the view to be displayed on every page. But the action is not getting called in other pages, please tell me where I'm going wrong and suggest any alternatives.
index.html.erb
<h1>Listing the types of products</h1>
<% content_for :sidebar do %>
<% #types.each do |type| %>
<li><%= link_to type.name, product_type_path(type)%> <!-- go to product_type controller show action-->
<%= link_to "Edit", edit_product_type_path(type) %> <!-- go to product_type controller edit action -->
<%= link_to "Delete", product_type_path(type) , method: :delete, data: { confirm: "Are U Sure?" }%> <!-- go to product_type controller delete action and a pop to confirm the action -->
</li>
<% end %>
<h3><%= link_to "New Type Of Product", new_product_type_path %></h3>
<h3><%= link_to "All Types of Products", products_path %></h3> <!-- All types of products listed for admin's ease -->
<% end %>
This is the Application layout I'm using.
Application.html.erb
<!DOCTYPE html>
<html>
<head>
<%= render 'layouts/title' %>
<%= render 'layouts/rails_defaults'%>
<%= render 'layouts/shim' %>
</head>
<body>
<aside><%= yield: sidebar %></aside>
<%= render 'layouts/header' %>
<%= render 'layouts/flash' %>
<div class="container">
<%= yield %>
</div>
<%= render 'layouts/footer' %>
</body>
</html>
As you can see I'm using yield: sidebar , but its not working properly, in the sense the action index is not getting called if I go to different page.
Product_types Controller
class ProductTypesController < ApplicationController
def index
#types = ProductType.all #to get all the records to an instance variable(array in the case) lasts only until the scope lasts. Since the is defined in index, it lasts only till you are using the index view
end
def new
#type = ProductType.new #to create a new record into the respective model
end
def show
#type = ProductType.find(params[:id]) #Finding the type of product click on
#products = Product.where(value: #type.value) #finding all the products whose value field is same as the type of product value(primary key)
end
def create
#type = ProductType.new(type_params) #type params defined below in private class
if #type.save #save the product created
redirect_to root_url #and redirect to root
else #if doesnt save and error occurs
render 'new' #error occurs and render 'new' view
end
end
def edit
#type = ProductType.find(params[:id])
end
def update
#type = ProductType.find(params[:id])
if #type.update(type_params) #update the params
redirect_to root_url #if updated redirect to root
else
render 'edit' #else if error occurs render 'edit' view again
end
end
def destroy
ProductType.find(params[:id]).destroy #destroy the record
redirect_to root_url #redirect to root
end
private
def type_params
params.require(:product_type).permit(:name,:value) #used to only permit type and value thorugh request(to prevent hacking) used in create and update action above
end
end
The action is not getting called whenever i jump to another page.
please suggest alternatives.
content_for / yield are for the current view only invoked by just the current action. So if the other pages dont have a content_for :sidebar in their views, then they wont have a sidebar. And if you just include in the content_for directly, it still wont execute any extra controller logic required.
Use a helper or partial like your layouts/header if you want resuable content, rather than a reusable "space".
For things you dont want to do only in a partial, but also not only in direct Ruby (with content_tag, etc.), you might combine a partial and a helper.
class ApplicationHelper # Or any other helper
def products_sidebar
products = Product.where(show_on_sidebar: true).order(:popularity) # Or whatever you like
render partial: "shared/products_sidebar", locals: {products: products}
end
end
shared/_products_sidebar.html.erb (Id definitely give consideration to other template engines)
<div id="products_sidebar">
<% products.each do |product| %>
<div><%=product.name%></div> <!--whatever you want it to look like-->
<% end %>
</div>
Then in your index, you can just call it, and it wont depend on the action/controller currently being processed.
<body>
<aside><%= products_sidebar %></aside>

argurments not being passed on edit action, nested objects

I'm trying to write an edit action for a my post object which is nested inside the projects one. By the looks of it I'm doing everything as it should be but for some reason when I comes down to load the form, this error message appears "First argument in form cannot contain nil or be empty"
The params being sent are correct "project_id"=>"308", "id"=>"41", however it seems like the form does not know what to do with them.
form
.....
<div class="row">
<div class="col-md-12" id="postform">
<%= form_for ([#project, #post]), html: { multipart: true } do |f| %>
....
view
....
<% if current_user?(post.user) %>
<%= link_to edit_project_post_path(#project, post ) do %>
....
controller
....
before_action :logged_in_user, only: [:create, :edit]
def edit
#project = Project.find(params[:project_id])
#post = #project.posts.find(params[:id])
end
....
post is a nested object of projects and so it has been config on the route s file.
Any ideas what might be causing this problem?
I thought that maybe I need to specify on the form what are these values used for...
Thanks for the help
---- Edit ----
resources :projects do
resources :comments,:posts
end
resources :posts, only: [:create, :destroy, :edit]
form_for is not supposed to work with multipart: true, try removing that or try with form_tag.
Best regards.

will_paginate comments partial not rendering?

I was following the instructions on the wiki for this gem:
https://github.com/mislav/will_paginate/wiki
And it works great for my listings controller :/ I was able to get them paginate but I have no idea how to get it work with my comments. My comments controller doesn't have a show method.
class CommentsController < ApplicationController
before_action :authenticate_user!, :except => [:show]
def create
#comment = Comment.new(params[comment_params])
#comment.listing_id = params[:listing_id]
#comment.user_id = current_user.id
#comment.body = params[:comment][:body]
if #comment.save
flash[:success] = "Comment Successful."
redirect_to listing_path(#comment.listing)
else
flash[:alert] = "Comment Failed."
end
end
def destroy
#comment = #listing.comments.find(params[:id])
#comment.destroy
flash[:success] = "Comment Removed."
redirect_to listing_path(#listing)
end
private
def comment_params
params.require(:comment).permit(:user, :body)
end
end
This is the show method I have inside my ListingsController:
def show
#comment = Comment.new
#comment.listing_id = #listing_id
end
It's what sets the comments to my understanding
This is the listings/show.html.erb file's part where it renders the comments:
<div class="commentblock">
<div class="text-left">
<%= render partial: 'comments/form' %>
<%= render partial: 'listings/comment', collection: #listing.comments.reverse %>
</div>
</div>
I know the first part of ruby code actually renders the forms but I don't understand how or what the collection part works or how to apply the pagination to this.
The listings/comment file looks like this:
<div class="panel panel-default">
<div class="panel-heading"><%= comment.user.username %>: <%= time_ago_in_words(comment.created_at)%> ago</div>
<div class="panel-body">
<%= comment.body %>
</div>
</div>
I've tried quite a few things but I still don't really get where or what to change in my code. I went into the listing/comment and tried adding:
<%= will_paginate(comment) %> # this crashed, undefined method `total_pages' for #<Comment:0x007ff556a36468>
EDIT: The will_paginate wiki says you to pass a paginated array when you get the error I got, but I don't know that is done >.>; it doesn't show how you would do that...
EDIT:
http://csnipp.com/s/709 this website said all you had to do was create a file config/initializers/will_paginate.rb and place this line of code in it:
require 'will_paginate/array'
But that didn't help
EDIT:
If you guys need to see more of the code it's actually on github:
https://github.com/ilovemysillybanana/pastie/
I'm really stuck on this D: I followed a tutorial on how to make the comments but theirs didn't paginate.
EDIT:
I fixed it!
The way to do it was by replacing this line:
<%= render partial: 'listings/comment', collection: #listing.comments.reverse %>
with this line:
<%= render partial: 'listings/comment', collection: #list_comments = #listing.comments.paginate(:page => 1, :per_page => 5) %>
But for some reason I don't get the numbers to change the comment pages :/
<%= render partial: 'listings/comment', collection: #listings = #listing.comments.reverse.paginate(:page => params[:page], :per_page => 10) %>
My code was correct, what I wasn't realizing is that #listings or #list_comments was creating a local variable that needed to be paginated itself. I was trying to find a way to paginate either in one command(which if possible I don't care, but if you know how it'd be nice to know for the future I guess) anyway, all that I needed to do to fix this was add this:
<%= will_paginate #listing_comments %>

Rails POST params not accessed in controller

I'm trying to write an application that will have to interact with POST but I'm having issues accessing the parameters. This is not meant to be useful right now but I'm just trying to flash the result of the form. According to google dev tools, the POST parameter is set to 1.
Here's my routes.rb file
devise_scope :user do
put 'users/toggle_activation' => 'users/sessions#toggle_activation'
get 'users/sign_out' => 'users/sessions#destroy'
post 'pages/home' => 'users/sessions#activities'
end
This is the controller in question
def activities
params.permit(:tennis)
current_user.save
flash[:notice] = params[:tennis]
redirect_to root_path
end
This is the form code
<%= form_for :user do |f| %>
<%= f.check_box :tennis %>
<%= f.submit %>
<% end %>
Any help is appreciated.
If you're using "form_for", then the check_box name will result as "user[tennis]", not just "tennis". View source in your browser and you should see this.
Do something like the following in your controller method (although I'm not sure how it will be called with "form_for :user" because your "activities" route isn't in your routes.rb in the code above):
user_params = params.require(:user).permit(:tennis)
flash[:notice] = user_params[:tennis]

Rails: Can you have render html: in a controller populate a div in the current view?

I am building a form for a Model called SchoolApplication. If someone unsuccessfully fills out the form, I would like to render a bit of HTML above the form saying <strong> you messed up</strong>. Currently I have
some logic in the controller corresponding to my form that says:
if #school_application.save
redirect_to relevant_path
else
render html: '<strong>you messed up </strong>'
end
However instead of rendering this in the new page it just displays the text (including the HTML tags)
you messed up .
Is there a way I can have this message rendered on the page displayed before render redirected me? Specifically in a <div> created for that purpose?
You could use the rails flash variable to do this, from the documentation, you can do something like this:
class ClientsController < ApplicationController
def create
#client = Client.new(params[:client])
if #client.save
# ...
else
flash.now[:error] = "Could not save client"
render action: "new"
end
end
end
refer to http://guides.rubyonrails.org/action_controller_overview.html#the-flash for more details
also a common 'gotcha', don't forget to put a variation of this in your application.html.erb
<html>
<!-- <head/> -->
<body>
<% flash.each do |name, msg| -%>
<%= content_tag :div, msg, class: name %>
<% end -%>
<!-- more content -->
</body>
</html>