NameError in ruby on rails - ruby-on-rails

So I am making an app to manage projects and its task,
using a tutorial I have made some basic stuff.
Now I want to add a timeline to my page, so I wrote this in my pr_list.rb (model file)
def timeline
#pr_lists.each do |pr_list|
pr_list.pr_items.each do |pr_item|
if pr_item.completed?
#timeline = "#{pr_item.descrpition}: {#{pr_item.completed_at}}"
end
end
end
end
And i called it in my pr_list/views/index page.
<h1><%= pr_list.timeline %></h1>
but I get
NameError (undefined local variable or method `pr_list' for #<ActionView::Base:0x00000000029fb8>
Did you mean? #pr_lists")
At this point even if I just code it like to output a string, it just does not work.
if I try any other things, it gives me a NoMethodError
while the rest of the methods work.
and the above code also works if I write it in HTML.ERB index file as an embedded ruby.
I am new to Ruby on Rails.

pr_list is local to the block defined in the controller so it is not accessible from the template.
You could iterate on #pr_lists from within the view file (see this question for reference):
<% #pr_lists.each do |pr_list| %>
<% pr_list.pr_item.each do |pr_item| %>
<% if pr_item.completed? %>
<h2><%= pr_item.description %>: <%= pr_item.completed_at %></h2>
<% end %>
<% end %>
<% end %>

Related

Problem with 'do' method in old version of Rails

Currently working with Rails 5.0.7.2 and ruby 2.4.10p364 for learning purposes.
I'm still a newbie. I have an embedded index.html file using Postgres. It seems to me that it's just a typing error in the script itself, but I can't confirm. Everything I try to do, It keeps returning me the "undefined method `each' for nil:NilClass" error.
So far, I've tried to modify the embedding style, but it keeps giving the me Exception in Action Controller error thing just right after the header.
<h1>Portfolio Items</h1>
<% #porfolio_items.each do |portfolio_item| %>
<p><%= portfolio_item.title %></p>
<p><%= portfolio_item.subtitle %></p>
<p><%= portfolio_item.body %></p>
<%= image_tag portfolio_item.thumb_image %>
<% end %>
This is the controller.
class PortfoliosController < ApplicationController
def index
#portfolio_items = Portfolio.all
end
end
I've even tried to add a "<% if #portfolio_items %>" separate line of code, but to no avail.
Any help would be appreciated. Is this a version thing or is there something I'm not looking at?
That's because #porfolio_items is nil. You have a typo there, a missing "T", it's not the same the instance variable from the index action.

Rails - how to write an index view?

I'm having trouble figuring out how to display an index.
In my organisation requests view folder, I have a file called index.html.erb.
In that file, I'm trying to list each organisation request. I've tried each of the following formulations:
<% OrganisationRequest.each do |OrgReq| %>
<% organisation_request.each do |OrgReq| %>
<% #organisation_request.each do |OrgReq| %>
<% #organisation_requests.each do |OrgReq| %>
In each case, I get an error that says:
formal argument cannot be a constant
I thought a constant meant something beginning with a capital letter. 3 of the above attempts don't begin with a capital letter.
It's also confusing to me since in my user index, I have <% User.each %> and I don't get an error message.
Can anyone see what's gone wrong? How do I ask for a list of objects?
If you have your data and view right, you should be able to fix with:
<% #organisation_requests.each do |org_req| %>
...
<% end %>
If we stick Rails conventions, we'd say that, you have a OrganisationRequests controller, has such content.
class OrganisationRequestsController < ApplicationController
...
def index
#your_local_variable = OrganisationRequest.find(...)
end
...
end
That is to say, you need to use, #your_local_variable inside view file.
<% #your_local_variable.each do |o| %>
....
<% end %>
If the variable inside index action is #organisation_requests, use that.

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

Rails if object can't be found move on in view

I have the following statement in an erb template:
<% if #serial.hacks.find(#serial.id) %>
<h1><%= #serial.hacks.find(#serial.id).hack_name %><h1>
<% end %>
I'm trying to display the hack_name if it exists, however, prevent an error if it doesn't exist. The Serial and Hack models share a has many through relationship.
When I load a page that doesn't have an association between Serial and Hack I get the following error which I'm trying to prevent:
Couldn't find Hack with id=2 [WHERE "hacktions"."serial_id" = 2]
<% if hack = #serial.hacks.find_by_id(#serial.id) %>
<h1><%= hack.hack_name %><h1>
<% end %>
But you should use presenters.
BTW, it's really weird to have a serial having hacks with it's id. What do you really want?
Edit I guess you're looking for:
<% #serial.hacks.each do |hack| %>
<h1><%= hack.hack_name %><h1>
<% end %>

Rails check if yield :area is defined in content_for

I want to do a conditional rendering at the layout level based on the actual template has defined content_for(:an__area), any idea how to get this done?
#content_for_whatever is deprecated.
Use content_for? instead, like this:
<% if content_for?(:whatever) %>
<div><%= yield(:whatever) %></div>
<% end %>
not really necessary to create a helper method:
<% if #content_for_sidebar %>
<div id="sidebar">
<%= yield :sidebar %>
</div>
<% end %>
then of course in your view:
<% content_for :sidebar do %>
...
<% end %>
I use this all the time to conditionally go between a one column and two column layout
<%if content_for?(:content)%>
<%= yield(:content) %>
<%end%>
Can create a helper:
def content_defined?(var)
content_var_name="#content_for_#{var}"
!instance_variable_get(content_var_name).nil?
end
And use this in your layout:
<% if content_defined?(:an__area) %>
<h1>An area is defined: <%= yield :an__area %></h1>
<% end %>
Ok I am going to shamelessly do a self reply as no one has answered and I have already found the answer :)
Define this as a helper method either in application_helper.rb or anywhere you found convenient.
def content_defined?(symbol)
content_var_name="#content_for_" +
if symbol.kind_of? Symbol
symbol.to_s
elsif symbol.kind_of? String
symbol
else
raise "Parameter symbol must be string or symbol"
end
!instance_variable_get(content_var_name).nil?
end
I'm not sure of the performance implications of calling yield twice, but this will do regardless of the internal implementation of yield (#content_for_xyz is deprecated) and without any extra code or helper methods:
<% if yield :sidebar %>
<div id="sidebar">
<%= yield :sidebar %>
</div>
<% end %>
I use #view_flow and value of the content method before checking if the content is present in the view like this:
#view_flow.content[:header_left_or_whatever_the_name_of_your_block_is].present?
Recently stumbled upon it when showing all local, global and instance variables of self in the console with byebug. I’m a fan using this because it’s straight from Rails, won’t throw an error, won’t hide anything w “Rails magic”, returns a definite true or false, + only checks the content in the current context of the view being rendered.
#view_flow is an instance attribute of ActionView::Context and because Action View contexts are supplied to Action Controller to render a template it will be available to any view that has been rendered by Rails. Although it checks for content, the content_for block will not be yielded if it isn’t there. So it’s been my perfect solution in similar situations.

Resources