How do you use pundit for partial authorization - ruby-on-rails

Consider the following block of ruby on rails code:
<% unless current_user %>
<%= card title: 'Things you can do', bodyless: true do %>
<ul class="list-group list-group-flush">
<li class="list-group-item" style="background: transparent"><i class="fa fa-key"></i> MEET OTHERS LIKE YOU</li>
<li class="list-group-item" style="background: transparent"><i class="fa fa-question-circle-o"></i> ASK A QUESTION</li>
<li class="list-group-item" style="background: transparent"><i class="fa fa-users"></i> SHARE YOUR JOURNEY</li>
</u>
<% end %>
<% end %>
The "card" is shown, but only to logged in users.
Can Pundit Authorization policies be used determine which divs/partials/cards are shown to the visitor on a website?

Yes you can, if you defined a policy and then want to show some div/partial just if that policy, then you can do it like this for example
<% if policy(#post).update? %>
<%= link_to "Edit post", edit_post_path(#post) %>
<% end %>

Related

<% if !current_page?(action: 'edit') %> error . No route matches {:action=>"edit", :controller=>"…"}

My _footer.html.erb is (simplified):
<footer class="footer">
<nav class="navbar navbar-default navbar-fixed-bottom navbar-inverse">
<% if logged_in? %>
<li class="btn btn-primary"> <%= link_to 'Add New Connection', new_year_path %></li>
<li class="btn btn-primary"> <%= link_to 'Add New Person', new_person_path %> </li>
<li class="btn btn-primary"> <%= link_to 'Add New Address/Location', new_location_path %> </li>
<% end %>
</nav>
</footer>
But I don't want the footer to show up while editing; too easy to click on one of these buttons instead of Cancel or Submit which is down the page and my footer is stuck to the bottom. views/layouts/application.html.erb has <%= render 'layouts/footer' %>
I suppose I could have my three edit.html.ergs not use the defaults above, but seems easier if I could add another condition on the _footer.html.erg. Or some other way. Maybe something about leaving page without submitting?
Based on #tsrandrei comment I tried wrapping the footer in <% if !current_page?(action: 'edit') %> blah-blah <% end %> but then get error No route matches {:action=>"edit", :controller=>"…"} with the controller name being whatever the page is relevant to.
<% if current_page?(action: 'edit') %>
<footer class="footer">
<nav class="navbar navbar-default navbar-fixed-bottom navbar-inverse">
<% if logged_in? %>
<li class="btn btn-primary"> <%= link_to 'Add New Connection', new_year_path %></li>
<li class="btn btn-primary"> <%= link_to 'Add New Person', new_person_path %> </li>
<li class="btn btn-primary"> <%= link_to 'Add New Address/Location', new_location_path %> </li>
<% end %>
</nav>
</footer>
<% end %>
See https://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-current_page-3F
You will also have other methods for your views:
controller_path
controller_name
action_name
Also check Rails: How to determine controller/action in view

Link_to with anchor doesn't go to the specific id

In the footer of my website, I have a menu, where I create links to other pages. A part of that menu looks like this:
<ul class="footer-menu-content">
<li><%= link_to 'All games', games_path %></li>
<% Category.all.each do |category| %>
<li><%= link_to category.name, games_path(anchor: category.name.downcase.parameterize) %></li>
<% end %>
</ul>
And on the page, where games_path leads, the code is as follows:
<% #categories.each_with_index do |category, index| %>
<div id="<%= category.name.downcase.parameterize %>" class="row game-category">
<div class="col-lg-12 col-md-12 col-sm-12">
<p class="all-games-category-title"><span style="background: url(<%= category.cat_image %>) no-repeat">
</span><%= category.name %>
</p>
</div>
</div>
<% end %>
The link_to generates HTML, for example: Blackjack, and when I click the link, it redirects me to http://localhost:3000/games#blackjack, but it doesn't go to the specific element with id blackjack. If I copy the url and paste it into the browser, everything works fine. So, what can be wrong, and what can be done, to make the click work? Thanks.

Devise User Profile link in Navbar

I have the following code for the nav-bar in my application, using Devise for user authentication.
<ul class="nav pull-right">
<li class="">
<%= link_to root_path do %>
<i class="icon-home"></i> Home
<% end %>
</li>
<li class="">
<%= link_to current_user do %>
<i class="icon-book"></i> Portfolio
<% end %>
</li>
<li class="">
<%= link_to help_path do %>
<i class="icon-question-sign"></i> Help
<% end %>
</li>
<li class="">
<%= link_to(destroy_user_session_path, :method=>'delete') do %>
<i class="icon-signout"></i> Logout
<% end %>
</li>
</ul>
It works fine on the home page and the user profile page, but when I go to the other pages, such as the Projects or Help page( both of which have before_filter :authenticate_user! in their controllers ), it throws the following error
NoMethodError in Projects#index
undefined method `find_by_remember_token' for #<Class:0x3ec18d0>
It says that the offending code is this part:
<%= link_to current_user do %>
Which I use to link the user to his/her profile. Any ideas how to fix this error?
Update:
It seems like the problem solved itself after adding
#user = current_user
to the page's respective controllers.
Try to check if user signed in.
<%= link_to if_user_signed_in?, current_user %>

Trying to have a view & block have access to a variable from a another block that is used to determine which element number in array

I am newer to rails: My side navigation partial takes each step and provides an icon and a link for it. I would like for the current active step, to have the same icon in the top navigation as the side navigation. However, <%= icon[i] %> will not work since [i] comes from a different block in a different view. How would I make it so that the active link top's navigation has the same icon[i] as the side navigation without having access to i? See below.
_side_navigation.html.erb
<% icon= ["icon-link", "icon-bar-chart", "icon-edit", "icon-beaker","icon-link", "icon-bar-chart", "icon-edit", "icon-beaker"] %>
<% #step_list.each_with_index do |step, i| %>
<% case step.media_type %>
<% when 'video' %>
<li class="<%= nav_active step %>">
<a href = "
<i class='icon-info-sign icon-2x'></i>
<span>Video</span>
</a>
</li>
<% when 'excel' %>
<li class="<%= nav_active step %>">
<i class="<%= icon[i] %> icon-2x"></i> **<<I need this [i] in the other partial so I know which element of the array is chosen**
<span>Step <%= i %> </span>
</a>
</li>
<% else %>
<li class="<%= nav_active step %>">
<i class="<%= icon[i] %> icon-2x"></i>
<span>Step <%= i %></span>
</a>
</li>
<% end %>
<% end %>
_top_navigation.html.erb
<div class="area-top clearfix">
<div class="pull-left header">
<% case #step.media_type %>
<% when 'video' %>
<h3 class="title">
<i class="<%= icon[i] %>"></i></i> <<<here is the problem since, it does not have access to the current "i" from the other block
Video
</h3>
<h5>
A video for the course is here
</h5>
<% when 'excel' %>
<h3 class="title">
<i class="<%= icon[i] %>"></i></i>
Excel
</h3>
<h5>
Please use the excel sheet below to complete the challenge.
</h5>
<% else %>
<h3 class="title">
<i class="<%= icon[i] %>"></i></i>
Multiple Choice
</h3>
<h5>
Please choose from a selection below
</h5>
<% end %>
</div>
Is there no natural order to these steps? You don't have an 'i' you can pass in when you include the partial (partial local variables)?
If not, it sounds like you need a slightly smarter 'Step' object that is aware of its index in the workflow.
You could also place the icon list in a helper, like so:
def icons
["icon-link", "icon-bar-chart", "icon-edit",
"icon-beaker","icon-link", "icon-bar-chart",
"icon-edit", "icon-beaker"]
end
Gets it out of your view.
Since I am newer to rails, I feel like this is a hack way of doing it but nonetheless works. I created the method below, which essentially takes in the step, and if it is the active step, save the current index to a variable. There is a method within that, which returns the variable while not requiring any inputs (so as to be able to be used freely)
def nav_active_icon(step, i)
#x = i if params[:id].to_s == step.id.to_s
def display
return #x
end
end
At the bottom, it takes in the step and the index for the method above
<% #step_list.each_with_index do |step, i| %>
<% case step.media_type %>
<% when 'video' %>
<li class="<%= nav_active step %>">
<span class="glow"></span>
<a href = "
<%= course_level_step_path(#course.id, #level.id, step.id) %>" >
<i class='icon-info-sign icon-2x'></i>
<span>Video</span>
</a>
</li>
<% nav_active_icon(step, i) %>
Here it outputs the current index for the active step in display (in a different view from the block)
<% when 'excel' %>
<h3 class="title">
<i class="<%= icons[display] %>"></i></i>
Excel
</h3>
<h5>
Please use the excel sheet below to complete the challenge.
</h5>

Using ruby to make a class active via helper method - error in variables

I have been having problems with my coffeescript, so instead I would like to use ruby to make my classes active in the view when clicked. I created a helper method called nav "active", and I have a variable called 'link' in the view that increments up for each step. The idea is to have params[:id] == link , and make the class active when that is the case . However, being newer to rails and ruby I am not sure how to implement this. Any help would be appreciated.
My error
undefined local variable or method `link' for #<#<Class:0x007fb21e087820>:0x007fb21e53fd18>
My Method in application helper
def nav_active(options = {})
return "active" if params[:id] == link
end
My view
<% icon= ["icon-link", "icon-bar-chart", "icon-edit", "icon-beaker","icon-link", "icon-bar-chart", "icon-edit", "icon-beaker"] %>
<% link = 0 %>
<% #step_list.each_with_index do |step, i| %>
<% case step.media_type %>
<% when 'video' %>
<% link += 1 %>
<li class="<%= nav_active %>">
<span class="glow"></span>
<a href="<%= link %>">
<i class='icon-info-sign icon-2x'></i>
<span>Video</span>
</a>
</li>
<% when 'excel' %>
<% link += 1 %>
<li class="<%= nav_active %>">
<span class="glow"></span>
<a href="<%= link %>">
<i class="<%= icon[i] %> icon-2x"></i>
<span>Step <%= i %> </span>
</a>
</li>
<% else %>
<% link += 1 %>
<li class="dark-nav <%= nav_active %> ">
<span class="glow"></span>
<a href="<%= link %>">
<i class="<%= icon[i] %> icon-2x"></i>
<span>Step <%= i %></span>
</a>
</li>
<% end %>
The helper method nav_active doesn't have access to the local variables in your view. You have to pass that in as an argument.
# Helper
def nav_active(link)
return "active" if params[:id] == link
end
This helper now accepts an argument named link. Now link will be defined in the helper method.
<% link += 1 %>
<li class="dark-nav <%= nav_active link %> ">
In the view you also must also pass in the current value of link, so the helper method can operate on it.

Resources