Rails Navbar application controller variable - ruby-on-rails

I have a value that I use inside the navbar. Think of it as some sort of low skill notification. On the root page I have access to it because I define it inside that method:
#conversations = Conversation.where("sender_id = ? OR recipient_id = ?",current_user.id,current_user.id)
If I move to a different method(page), the scope of that variable will be out and I'd have to redefine it again.
How can I define this variable as a cross-controller variable as every page has the same navbar?
<li> Conversations <%= #conversations.count %> </li>

ApplicationController
....
before_action: :conversation_count
def conversation_count
#conversations =
Conversation.where("sender_id = ? OR recipient_id = ?",current_user.id,current_user.id) if current_user.present?
end
...
Navbar Show count only if user is loggedin
<ul>
<li> About </li>
<% if current_user.present %>
<li>Conversations <%= #conversations.count %></li>
<% end %>
</ul>
Navbar Show count irrespective of user is logged in or no
<ul>
<li> About </li>
<li>Conversations <%= #conversations.try(:count).to_i %></li>
</ul>

You need to place the navbar in the layouts/application.html.erb and the rest of the content by calling the yield block so you are actually not changing the navbar based on controller(It is fixed).
Also assign the variable in the application_controller's method so as to access it throughout the other controllers.
If current_user is not accessible from application_controller may be you have to restart your server(but usually it is accessible).
use
if current_user.present?
instead of
if current_user.present
question mark is missing

As someone else said, current_user works in application controller.
If you copy and paste whatever code you have from your conversations controller to your application controller, you'll have access to it from every controller than inherits from application controller (all of them unless you specify otherwise).

Related

Ruby on Rails: 'don't show on all these pages' condition

I am new to Ruby on Rails and am having a difficult time figuring out how to not show a div on more than one page. Currently, I've only been able to make the following work for a single page:
<% if signed_in? %>
<% unless current_page?(account_setup_path) %>
<!--job seeker options-->
<% if current_user.job_seeker? %>
test
<% end %>
<!--end job seeker options-->
<!--employer options-->
<% if current_user.employer? %>
<% end %>
<!--end employer options-->
<% end %>
<% end %>
Any help will be much appreciated! Thanks in advance!
Since you want a div to not be shown on multiple pages you have several options. First, if the div is only meant to be shown on pages with a certain controller you'll want to move that div into a partial and reference it from all the associated views. If you want in only shown on one page you should put it in the view directly. If you need it shown on several different pages accross your app. you can simply check if the controller in your params hash matches. For example:
#I want this div shown on any pages handled by my `Admins` and `Users` controllers.
<% if params[:controller] == 'admins' || params[:controller] == 'users' %>
div here
<% end %>
This will add overhead to maintenance so you should think hard whether this div should be in a partial, in a specific view, or in the layout/application file etc.

Moving rails from to from _form.html.erb to application.html.erb

I have most of the functionality done for a site. Now I am trying to make it look nice. I have a _form.html.erb that works great.
<%= form_for(#card) do |f| %>
<% if #card.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#card.errors.count, "error") %> prohibited this card from being saved:</h2>
<ul>
<% #card.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :event %><br />
<%= f.text_field :event %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Files
view
- cards
-- new.html.erb
-- index.html.erb
-- show.html.erb
- layouts
-- application.html.erb
- pages
-- index.html.erb
I make a call for the form from new.html.erb and it works sends it to show.html.erb, just as I want. I'm using bootstrap and decided to make use of the nav bar. I have placed the nav bar code into the application.html.erb. It works just fine, well kind of. I want what would normally be a search function to be the add a new card.
When I add the form call it does not work, when I add it directly to the application page it does not work. I'm not sure, I have spent hours on this. I got it to work only on the show.html.erb page, both index pages would error out. I honestly don't remember how I did this though.
I'm trying to learn by doing, but I am stuck and need some help.
Thank you,
Ian
I guess that when you say that its working in your new.html.erb you have a new action inside your cards_controller, and inside this action you have something like: #card = Card.new
Well, if you want to put this form in another view, like in the application.html.erb you need to set first your #card variable, so you can do something like:
# application_controller:
before_filter :new_card
def new_card
#card = Card.new
end
be aware that all the controller that inherits from application controller will set this #card variable
#instance_variable
The underlying problem here is that you're calling a partial - by design, these are meant to give you the ability to call the functionality the file contains anywhere in your application
The problem you have is you're referencing an #instance_variable directly in your partial.
This isn't normally an issue - if you're using partials like you were originally (to modularize views), it should be okay. The problems arise when you try and use the partials in a more generalized way, as you are doing now:
#app/views/controller/_form.html.erb
<%= form_for(#card) do |f| %>
This relies on the #card instance variable being made available, which won't be if you're loading the partial in any other controller than the cards_controller.
--
Fix
The way to fix this is to either populate the #card instance variable in the application controller (as described by edymerchk), or to pass the raw value through the locals hash of the partial call:
This will allow you to use the card local variable in your partial:
#app/views/controller/_form.html.erb
<%= form_for card do |f| %>
-
Alternatively, you could also set the #card instance variable, as recommended in another answer:
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
before_action :set_card
private
def set_card
#card = Card.new
end
end

How does one properly create a second view for a controller in Rails?

I am quite new to Rails and have created a second controller to display a list of items without providing the edit and destroy options. (it is meant as the front end) I am now trying to create a show view for that particular listing but am not sure what steps take. Having created a second view file, I seem unable to access information in the model, receiving undefined variable errors. I am able to access them in the main index view for the controller so I expect there is either something in routing or the controller itself that I have to add.
Thanks in advance for your help.
Updated October 1, 2013 16:15PST
The second view called show.html.erb, just contains the following code to see if it will pull up the data:
<p><%= plant.botanical_name %></p>
The first view, called index.html.erb, contains this and it pulls the variables correctly:
<h1>Plant Display</h1>
<% #plants.each do |plant| %>
<div class="listingItem">
<div class="showThumbnail">
<%= link_to display_show_path do %>
<%= image_tag plant.photo.url(:medium) %>
<% end %>
</div>
<div class="listingItemInformation">
<p><%= plant.botanical_name %></p>
<p><%= plant.family %></p>
<p><%= plant.common_name %></p>
</div>
</div>
<div class="clear">
</div>
<% end %>
The controller just has this:
class DisplayController < ApplicationController
def index
#plants = Plant.order(:botanical_name)
end
end
Also, in terms of versions: Rails 4.0.0.rc1 and Ruby 1.9.3p392
The plant variable in the index view is actually an argument to the iteration block. When you write this:
it iterates over all the plants in #plants, and on each iteration plant is assigned to a plant. #plants itself is defined in the index controller method.
Your show view doesn't work because it uses plant but does not define it anywhere. Since you only want to show a single plant, what you want to do is to create a #plant variable in the show controller method and use it in the code instead of plant. So your controller should look something like this(didn't test it):
class DisplayController < ApplicationController
def index
#plants = Plant.order(:botanical_name)
end
def show
#plant = Plant.find(params[:id])
end
end
and your view:
<p><%= #plant.botanical_name %></p>
Also, in the index view, you will want to change
<%= link_to display_show_path do %>
to
<%= link_to display_show_path(plant) do %>
so it will link to the currently iterated plant.

Dynamic data in rails partial view

I've just started to use Partials in my rails application, at the moment i have the following code in my application.html.erb
<%= render 'categories/categorieslist' %>
This links to _categorieslist.html.erb in my views/categories/ folder
At the moment this partial contains hard coded hyperlinks
<ul class="unstyled">
<li style="padding-bottom:5px">Item A»</li>
<li style="padding-bottom:5px">Item B»</li>
</ul>
My aim is to have these categories coming from the database, e.g
<ul class="unstyled">
<% #categories.each do |category| %>
<li style="padding-bottom:5px"><%= category.name %> » </li>
<% end %>
</ul>
I have tried adding a categorieslist method in the categories controller e.g
def categorieslist
#categories = Category.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #categories }
end
end
but this is not being called by the partial (and i don't feel this is even the correct way to do it), and is showing the error
NoMethodError in Store#index
on the line <% #categories.each do |category| %>
My question is how do i pass into the partial in the application.html.erb file, the categories object that usually would come from a controller method in the categories controller?
Any help would be great.
You can send locales with your partial call in your view and pass variables to that partial.
For example (this is a partial shortcut):
Your view from which you call the partial
<%= render 'categories/categorieslist', :all_categories => #categories %>
Your partial categories/_categorieslist.html.erb (note there is no # with the variable)
<ul class="unstyled">
<% all_categories.each do |category| %>
<li style="padding-bottom:5px"><%= category.name %> » </li>
<% end %>
</ul>
For further information (and the long version), see 3.4.4 Passing Local Variables in the Rails Guides.
I'd use a collection for this:
<%= render 'categories/categorieslist', :collection => #categories, :as => :category %>
This renders a collection of items. In this case, all the categories. You can also pass it a custom name with the :as => .
Then in your partial you only include the stuff you want the items in the collection to render:
<li style="padding-bottom:5px"><%= category.name %> » </li>
The -ul- isn't included as it would be rendered multiple times. You'll need to wrap it around your render tag.
The result is the same as the suggestion #timbrandes outlined, (check out docs he linked to).
I've heard :collection gives you performance improvements.
http://rails-bestpractices.com/posts/38-use-render-collection-rails-3-when-possible
That's not the right way to do it, and your question is rather confusing.
I'd say that you still have to read a rails book. You seem to be still a bit too fresh
Anyway, controller methods usually represent http requests. And they are invoked accordingly to what is defined in the config/routes file. Views (*.erb) do not usually invoke controller methods. If they do so, they do it through an ajax request.
Data is passed from actions to the views through controllers instance variables.
If you want to invoke any methods within the views, they should be defined in helpers. Still, the only data they will manipulate is the one passed from controllers as instance variables.

is it possible to access value from a model databasetable in the application.html.erb?

im trying to make a app
with users
this users can join multiple groups - every group has the same menu on the page
their group page is accessable about group/1 or group/2
so i wanted to put the the menu in the application.html.erb, with lnks depending on the group.id - but i dont know how to acces this id in the application.html.erb
This is often done using content_for in the layout. Let's say you want your menu in a certain div in application.html.erb:
# application.html.erb
<div id="menu_div>
<ul>
... etc ...
</ul>
</div>
Replace the inner content with a yield statement:
<div id="menu_div>
<%= yield :group_menu %>
</div>
Then in the view template add the content_for block:
# page
<% content_for :group_menu do %>
<ul>
... etc ...
</ul>
<% end %>
Each page template can then define its own menu code in a content_for block. This can be further generalized by using a helper method in the block and passing in instance variables.
EDIT
Assuming #group is assigned in the controller, you might do something like:
<% content_for :group_menu do %>
<%= show_me_the_menu(#group) %>
<% end %>
and in the helper (obviously contrived example):
def show_me_the_menu(group)
content_tag :ul do
group.users.collect do |user|
concat(content_tag(:li, user.some_method))
end
end
end
The correct approach would be to set this in ApplicationController via before_filter and just use it as an instance variable in views.
So in controller set something like #links = some logic where you calculate your links based on current user.
In view you do something like:
<ul>
<%- for link in #links -%>
<li><%= link.title =>
<%- end -%.
</ul>
Of course, you set your #links in ApplicationController only if you want your links to be available to all your controllers/views, which I think you do.
Rails Cells could also be used here http://cells.rubyforge.org/
i solved my problem in a different way now. i created in the group model a "menu" and this i render partial in the application.html.erb

Resources