Undefined method 'model_name' - ruby-on-rails

I keep getting a undefined method `model_name' for NilClass:Class.
In the layout file: [application.html.erb]
<section id="featured">
<%= render 'subscribers/new' %>
</section>
In the form partial: [views > subscribers > _new.html.erb]
<%= form_for #subscriber, :url => subscribe_path do |f| %> [THIS LINE PRODUCES THE ERROR]
<div class="field">
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit 'Add me to the list' %>
</div>
<% end %>
In the subscribers controller: [controllers > subscribers_controller.rb]
def new
#subscriber = Subscriber.new
end
I'm a beginner at ROR, and I've looked around StackOverflow, but can't find any answers for my specific case.

What path are you hitting when you are seeing this error?
If you are navigating to any path other than /subscribers/new then #subscriber will be nil and the form will throw the error that you are seeing. You are rendering a form via a partial in your view layout, that layout is rendered (presumably) throughout the app. Thus #subsriber won't always be set.

The problem is, that you are rendering the subscribers/new template directly in the layout, but only initializing a Subscriber in the subscriber controller.
You need to create a subscribers/new.html.erb file (without the leading underscore, so it is not a partial)
Somewhere in your layout file you should have a yield call.
When you access /subscribers/new rails renders the new.html.erb template file, and stuffs it in where yield is called in the layout.
If you really need this form on every page, you will need to initialize a new subscriber on every page. You could do this with a before filter in the application controller. But then you would not need the new action in the subscriber controller.

Related

RoR Rails 7 using Turbo to Update a partial on button click

Help! I'm relatively new to Ruby on Rails and now I'm attempting to use Rails 7 with Turbo and Stimulus to update a partial on my web page.
I have buttons on a page within a partial (call it _home.html.erb). When clicked I'd like them to replace _home.html.erb with a different partial.
Let me show you what I've done so far:
view:
index.html.erb
<%= turbo_frame_tag "main-speaker-div" do %>
<%= render partial: 'home' %>
<% end %>```
_home.html.erb
<div class="row">
<div class="col-5">
<%= button_to "Settings", rendersettings_path(), remote: true, class: "reader-general-button"%>
</div>
</div>
controller:
def rendersettings
broadcast_replace_to "main-speaker-div", partial: 'settings'
end
This code is throwing the following error:
POST 500 http://localhost:3000/rendersettings (Internal Server Error)
Response has no matching element
Server console error:
NoMethodError (undefined method `broadcast_replace_to' for #HreaderController:0x0000000002be30):
Thanks in advance for your help!
method broadcast_replace_to is supposed to be called on an object of Model. I guess in your case you must have an Object of header, and this method would be called as #header.broadcast_replace_to
I actually ended up doing the following to with my view to fix this issue:
<%= turbo_stream_from "main-speaker-div" %>
<%= turbo_frame_tag "main-speaker-div" do %>
<turbo-frame id="main-speaker-div">
<%= render partial: 'homefull' %>
</turbo-frame>
<% end %>
It seems like if I am broadcasting I would need to have the turbo_stream_from tag added as a listener. Please point out any issues you see with this! I'm basically doing trial and error since this is so new to RoR

error - First argument in form cannot contain nil or be empty

to start out preemptively, I've already looked at various similar articles dealing with this, but I still get the error.
I'm starting out on rails and attempting to create a GPA calculator and tracker application for fun (and spent a lot of time searching through documentation); I have a singular controller and view since redirecting to an entire different page for calculating or saving a new GPA every time would look ugly.
Rails will display everything without error up until I add the form, no other erb is written currently, and the form is meant to submit letter grade values from the "f.selection" tag.
The culprit is #cgpa in <%= form_for #cgpa do |f| %>.
My form from main\index view:
<%= form_for #cgpa do |f| %>
<div class="field">
(...)
</div>
<div class="actions">
<%= f.submit 'Calculate' %>
</div>
<% end %>
My controller:
class MainController < ApplicationController
def index
##cgpa = CurrentGpa.all #currently calls a key_to error while form exists, otherwise no error is raised
#pgpa = PastGpa.all
#csem = CurrentSemester.all
#psem = PastSemester.all
end
def new
#cgpa = CurrentGpa.new
end
def create
(...)
end
end
The routes are simply Rails.application.routes.draw { root 'main#index'; resources :main }
If any other information is needed, just let me know to add >.>
When you use: <%= form_for #cgpa do |f| %> this automatically tries to submit the form to the CurrentGpasController create action and for doing so it sends a request to current_gpas_path. So you don't have this path in routes that is why it throwing error. Either you can add routes for CurrentGpa like:
resources :current_gpas
or you can specify a path in the form_for:
<%= form_for #cgpa, url: any_path do |f| %>
So this will submit your form to that url specified.
If you add the current_gpas routes then do create the controller and action to process your input.
And as mentioned in comments do add the #cgpa = CurrentGpa.new this in index action. The above will solve your error you are getting after that.
Hope this helps.

Edit specific object

I have an edit view. In this view I got a dropdown and a render partial to a form. Like this:
<ul class="dropdown-menu dropdown-user installations">
<% #installations.each do |i| %>
<li>Installation<%= i.installation_id%></li>
<% end %>
</ul>
<div class="ibox-content form-installations">
<%= render :partial => 'installations/test'%>
<%= render 'form_data' %>
</div>
The view to edit the form:
<%= simple_form_for #installation, class: 'form-horizontal' do |f| %>
<%= f.error_notification %>
...
<%end%>
Controller:
def edit
#installations = current_user.installations
#installation = current_user.installations[0]
end
So in this point I can see in dropdown all installations but only can edit the first "current_user.installations[0]". So my objective is to select the installation in dropdown-menu and edit the selected installation. How I can do this?
The simplest way to do this will be to pass the relevant installation to the dropdown:
#app/controllers/installations_controller.rb
class InstallationsController < ApplicationController
def index
#installations = current_user.installations
end
end
#app/views/installations/index.html.erb
<%= render #installations %>
#app/views/installations/_installation.html.erb
<%= simple_form_for installation do |f| %>
...
<% end %>
I think there are some major issues with the structure of your code - which is why you're seeing these problems.
1. Edit
By definition edit is a member route...
This means that Rails expects a single resource to be loaded through that route (hence why you get url.com/:id/edit as the path).
The reason for this is quite simple -- Rails/Ruby are object orientated. This means that each time you create/read/update/destroy (CRUD), you're doing it to an object.
Objects are invoked by using #installation = Installation.new etc... meaning if you want to edit "all" of your installations, you'll basically need to use one of the collection routes for your Installations resource, sending any fields to the update path:
#app/views/installations/_installation.html.erb
<%= simple_form_for installation, method: :patch do |f| %>
...
<% end %>
This should send the updates to the installations#update path of your app, making it work properly.
--
2. Partials
Partials are just views which can have multiple uses; you should only use "local" variables in them.
There are two ways to invoke local scope variables into partials:
passing them in the locals: {} hash
passing them as in the as: :__ switch
In both instances, you're setting the "local" variables inside the partial to have data that was only available outside of it.
For example, you're calling:
<%= simple_form_for #installation
... inside a partial. This is bad because you're relying on #installation -- you're better using installation and populating it as you invoke the partial (as I have done in the code above).

I created a file in my new rails app and when I run the http://localhost page I get a Missing Template error message

This is the error I'm getting:
ActionView::MissingTemplate in Posts#index
Missing partial text_posts/_text_post with {:locale=>[:en], :formats=>[:html],...
Extracted source (around line #5):
3 </div>
4
5 <%= render #posts %>
Here's the code in the file app/views/posts/index.html.erb
<div class="page-header">
<h1>Home</h1>
</div>
<%= render #posts %>
I'm following along the 'Rails Crash Course' book and this is one of the steps to create a social network. I don't know the reason for the error.
I am assuming that in your posts_controller.rb file you have specified the following:
def index
#posts = Post.all
end
The reason why you are getting this error is because Rails is trying to display a partial for the variable #posts. What is implicit here, is that Rails is looking for a file named _post.html.erb in the folder app/views/posts/ and not finding anything. To fix this, you will have to manually create the file in that directory (Note that all partials begin with an underscore).
Now, if you are wondering what you should put in this partial, first you should know what <%= render #posts %> is doing. When it goes to the partial, it is iterating over all your posts and for each of them, it is going to do something. So your partial may look something like this:
<p>
<%= link_to post.title, post_path(post.id) %>
</p>
<p>
<%= link_to "Edit", edit_post_path %>
</p>
<p>
<%= link_to "Delete", post_path(post.id), method: :delete %>
</p>
Just know that what is implicit here, is that we already have a #posts.each do |post| given for us, so you only have to define whatever content you wish to display for each individual post.
Hope this helps!!
As you're using <%= render #posts %>, i'm am sure this will call the partial file with leading _ symbol on same directory. Please ensure you have already file with the name _posts.html.erb. IF you want to pass the value into partial, here i give you simple illustration :
Assume you have this in customer_controller :
def show
#customer= Customer.find(params[:id])
end
Then it instance will available on show.html.erb :
<p>Item: <%= #customer.name%></p>
These instance variables are available in layouts and partials as well, instead pass variables to partials as locals like:
// here is the same concept with your problem
// render "cust_name" find the filename leading with underscore
<%= render "cust_name", name: #customer.name%>
Above line of code will call the file with name _cust_name.html.erb that contains :
<h1><%= name %></h1>
Hope this helped.

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

Resources