Rails : acting weird : why layout is rendered when format.js

I don’t know why I am getting this issue. I have set remote: true in link_to helper method in view. and the controller is supposed to look like

class ProfilesController < ApplicationController
  def index
  end

  def profile_setting
    respond_to do |format|
      format.js
    end
  end
end

I have the file views/profiles/profile_setting.js.erb. I can even pry into the .js template using binding.pry [using pry-rails gem]. It renders the template but also renders layout i.e. layouts/application.html.erbContinue reading

Advertisements

Rails : Martin Fowler’s Tell Don’t Ask principle in Ruby

As Martin Fowler said

Tell-Don’t-Ask is a principle that helps people remember that object-orientation is about bundling data with the functions that operate on that data. It reminds us that rather than asking an object for data and acting on that data, we should instead tell an object what to do. This encourages to move behavior into an object to go with the data.

Continue reading

Rails : XSS (Cross Site Scripting) : Sanitize your data from harmful HTML tags : , , etc

Do you know what XSS is?

One if the most widespread, an devastating security vulnerabilities in web applications is XSS. This malicious attack injects client-side executable code into HTML document via the data-stored via HTML forms. Rails provides helper methods to fend these attacks off.

Any <script> tag in the user-input data may lead to cookie-theft. So use the following configuration to avoid such vulnerabilities.

class Application < Rails::Application
  config.action_view.sanitized_allowed_tags = %w(del dd h3 address big sub tt a ul h4 cite dfn h5 small kbd code b ins img h6 sup pre strong blockquote acronym dt br p samp li ol var em div h1 i abbr h2 span hr)
  config.action_view.sanitized_allowed_attributes = %w(name href style cite class title src xml:lang height datetime alt abbr width)
end

How to use?

= sanitize comment.message.gsub("\n", '<br>').html_safe

Rails: Save Markups in variables for later use

content_for(name, content = nil, options = {}, &block) public

Calling content_for stores a block of markup in an identifier for later use. In order to access this stored content in other templates, helper modules or the layout, you would pass the identifier as an argument tocontent_for.

Note: yield can still be used to retrieve the stored content, but calling yield doesn’t work in helper modules, while content_for does.

<% content_for :not_authorized do %>
  alert('You are not authorized to do that!')
<% end %>

You can then use content_for :not_authorized anywhere in your templates.

<%= content_for :not_authorized if current_user.nil? %>

This is equivalent to:

<%= yield :not_authorized if current_user.nil? %>

content_for, however, can also be used in helper modules.

module StorageHelper
  def stored_content
    content_for(:storage) || "Your storage is empty"
  end
end

This helper works just like normal helpers.

<%= stored_content %>

You can also use the yield syntax alongside an existing call to yield in a layout. For example:

<%# This is the layout %>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>My Website</title>
  <%= yield :script %>
</head>
<body>
  <%= yield %>
</body>
</html>

And now, we’ll create a view that has a content_for call that creates the script identifier.

<%# This is our view %>
Please login!

<% content_for :script do %>
  <script>alert('You are not authorized to view this page!')</script>
<% end %>

Then, in another view, you could to do something like this:

<%= link_to 'Logout', action: 'logout', remote: true %>

<% content_for :script do %>
  <%= javascript_include_tag :defaults %>
<% end %>

That will place script tags for your default set of JavaScript files on the page; this technique is useful if you’ll only be using these scripts in a few views.

Note that content_for concatenates (default) the blocks it is given for a particular identifier in order. For example:

 <% content_for :navigation do %>
   <li><%= link_to 'Home', action: 'index' %></li>
 <% end %>

And in other place:

 <% content_for :navigation do %>
   <li><%= link_to 'Login', action: 'login' %></li>
 <% end %>

Then, in another template or layout, this code would render both links in order:

<ul><%= content_for :navigation %></ul>

If the flush parameter is true content_for replaces the blocks it is given. For example:

<% content_for :navigation do %>
  <li><%= link_to 'Home', action: 'index' %></li>
<% end %>

<%#  Add some other content, or use a different template: %>

<% content_for :navigation, flush: true do %>
  <li><%= link_to 'Login', action: 'login' %></li>
<% end %>

Then, in another template or layout, this code would render only the last link:

<ul><%= content_for :navigation %></ul>

Lastly, simple content can be passed as a parameter:

<% content_for :script, javascript_include_tag(:defaults) %>

WARNING: content_for is ignored in caches. So you shouldn’t use it for elements that will be fragment cached.

Rails : Layout and rendering :: Gist/Theme

2 Creating Responses

From the controller’s point of view, there are three ways to create an HTTP response:

  • Call render to create a full response to send back to the browser
  • Call redirect_to to send an HTTP redirect status code to the browser
  • Call head to create a response consisting solely of HTTP headers to send back to the browser

    2.1 Rendering by Default: Convention Over Configuration in Action

    if you have this code in your BooksController class:

    class BooksController < ApplicationController
    end

    And the following in your routes file:

    resources :books

    And you have a view file app/views/books/index.html.erb:

    <h1>Books are coming soon!</h1>

    Rails will automatically render app/views/books/index.html.erb when you navigate to /books and you will see “Books are coming soon!” on your screen.

  • The rule is that if you do not explicitly render something at the end of a controller action, Rails will automatically look for the action_name.html.erb template in the controller’s view path and render it. So in this case, Rails will render the app/views/books/index.html.erb file
    2.2.1 Rendering Nothing

    Perhaps the simplest thing you can do with render is to render nothing at all:

    render nothing: true
    or
    head :bad_request
    2.2.2 Rendering an Action’s View

    If you want to render the view that corresponds to a different template within the same controller, you can use render with the name of the view:

    def update
      @book = Book.find(params[:id])
      if @book.update(book_params)
        redirect_to(@book)
      else
        render "edit"
       # render :edit you can rather use symbol
      end
    end

    If the call to update fails, calling the update action in this controller will render the edit.html.erbtemplate belonging to the same controller.

    2.2.3 Rendering an Action’s Template from Another Controller
    you can render the results of an action to a template in app/views/products this way:
    render "products/show"

    you can use the :template option (which was required on Rails 2.2 and earlier):

    render template: "products/show"
    2.2.4 Rendering an Arbitrary File
    render "/u/apps/warehouse_app/current/app/views/products/show"
    or
    render file: "/u/apps/warehouse_app/current/app/views/products/show"
    2.2.7 Rendering Text

    You can send plain text – with no markup at all – back to the browser by using the :plain option to render:

    render plain: "OK"

    Rendering pure text is most useful when you’re responding to Ajax or web service requests that are expecting something other than proper HTML.

    2.2.9 Rendering JSON

    JSON is a JavaScript data format used by many Ajax libraries. Rails has built-in support for converting objects to JSON and rendering that JSON back to the browser:

    render json: @product
    2.2.10 Rendering XML

    Rails also has built-in support for converting objects to XML and rendering that XML back to the caller:

    render xml: @product
    2.2.11 Rendering Vanilla JavaScript

    Rails can render vanilla JavaScript:

    render js: "alert('Hello Rails');"

    This will send the supplied string to the browser with a MIME type of text/javascript.

    2.2.13 Options for render

    Calls to the render method generally accept four options:

    • :content_type
    • :layout
    • :location
    • :status

2.2.13.1 The :content_type Option

render file: filename, content_type: "application/rss"
By default, Rails will serve the results of a rendering operation with the MIME content-type of text/html (or application/json if you use the :json option)
2.2.13.2 The :layout Option
You can use the :layout option to tell Rails to use a specific file as the layout for the current action:
render layout: "special_layout"

You can also tell Rails to render with no layout at all:

render layout: false
2.2.13.3 The :location Option

You can use the :location option to set the HTTP Location header:

render xml: photo, location: photo_url(photo)
2.2.13.4 The :status Option

Rails will automatically generate a response with the correct HTTP status code (in most cases, this is 200 OK). You can use the :status option to change this:

render status: 500
render status: :forbidden

To include app/assets/stylesheets/main.css and app/assets/stylesheets/columns.css:

<%= stylesheet_link_tag "main", "columns" %>

To include app/assets/stylesheets/main.css and app/assets/stylesheets/photos/columns.css:

<%= stylesheet_link_tag "main", "photos/columns" %>

To include http://example.com/main.css:

<%= stylesheet_link_tag "http://example.com/main.css" %>