undefined method `premails_path' for #<#<Class:0x4fa8530>:0x52c1ec8> - ruby-on-rails

I am trying to add a pre-launch sign-up email form on my pages index view. I made a form on my view, then created a controller, then made the model and table and ran the migration. Is this the right way to do it?
I am getting the following error:
NoMethodError in Pages#index
undefined method `premails_path' for #<#<Class:0x4fa8530>:0x52c1ec8>
on line:
<%= form_for(#premail) do |f| %>
from
<%= form_for(#premail) do |f| %>
<% if #premail.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#premail.errors.count, "error") %> prohibited this link from being saved:</h2>
My pages controller has the following:
class PagesController < ApplicationController
def index
#premail = Premail.new
end
end
My pages index view has the following:
<%= form_for(#premail) do |f| %>
<% if #premail.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#premail.errors.count, "error") %> prohibited this link from being saved:</h2>
<ul>
<% #premail.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Email %><br />
<%= f.text_field :Email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I generated the following model:
class Premail < ActiveRecord::Base
end
and the following db migrate table:
class CreatePremails < ActiveRecord::Migration
def change
create_table :premails do |t|
t.text :email
t.timestamps
end
end
end
What can I do differently to make this work?

Because you're loading this form on Pages#index, you'll benefit from using the url: argument like this:
<%= form_for #premail, url: pages_index_path do |f| %>
Update
From the Rails guide:
Resource-oriented style
In the examples just shown, although not indicated explicitly, we
still need to use the :url option in order to specify where the form
is going to be sent. However, further simplification is possible if
the record passed to form_for is a resource, i.e. it corresponds to a
set of RESTful routes, e.g. defined using the resources method in
config/routes.rb. In this case Rails will simply infer the appropriate
URL from the record itself. For example,
<%= form_for #post do |f| %> ... <% end %> is then equivalent to
something like:
<%= form_for #post, as: :post, url: post_path(#post), method: :patch,
html: { class: "edit_post", id: "edit_post_45" } do |f| %> ... <%
end %>
As you're using #premails instance var (which is an instance of the Premail class), your form_for helper will be trying to use a premails path. To use a pages path (as per your question), you'll need to manually set the url option

Related

Instance variable nil in one view, not in another

I'm working on a project in Ruby on Rails (Ruby v.2.2.8, Rails 5.1.4) and have encountered a very strange issue.
For my show method in the controller, I have:
def show
#county = County.find(params[:id])
end
And it works. For update, I have.
def update
#county = County.find(params[:id])
if #county.update(county_params)
redirect_to #county
else
render 'edit'
end
end
In my 'edit', I consistently get an error that #county is nil. The error page indicates that the parameters are being passed as:
{'id'=>4}
as an example. When I use find_by from the rails console, the item is found.
Is there something here I'm missing?
ETA: View Code
<%= form_with model: #county, local: true do |form| %>
<% if #county.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#county.errors.count, "error") %> prohibited
this county from being saved:
</h2>
<ul>
<% #county.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.label :shortname %><br>
<%= form.text_field :shortname %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
ETA Routes for Counties:
counties GET /counties(.:format) counties#index
POST /counties(.:format) counties#create
new_county GET /counties/new(.:format) counties#new
edit_county GET /counties/:id/edit(.:format) counties#edit
county GET /counties/:id(.:format) counties#show
PATCH /counties/:id(.:format) counties#update
PUT /counties/:id(.:format) counties#update
DELETE /counties/:id(.:format) counties#destroy
The error occurs at /counties/:id/edit
How is your edit action in your controller?
You should define #county as well
def edit
#county = County.find(params[:id])
end

Rendering a form that creates an object that is Nested under two other models.

I'm building a rails app that has a an object that is created /nested underneath two objects.
Routes.rb
resources :pages do
resources :referralpages do
resources :rewards do
end
end
end
I've just added the rewards resource and have this for my form for creating a new reward
<%= form_for ([#referralpage, #reward]) do |f| %>
<% if #reward.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reward.errors.count, "error") %> prohibited this reward from being saved:</h2>
<ul>
<% #reward.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :name %><br>
<%= f.text_field :name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :level %><br>
<%= f.text_field :level, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :dscount %><br>
<%= f.text_field :discount, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
I need help getting the form_for ([#referralpage, #reward]) portion working.
Here's the error message I'm getting when clicking the new reward button:
undefined method `referralpage_rewards_path'
<%= form_for ([#referralpage, #reward]) do |f| %>
my guess is that it's routing to the incorrect path. What's the proper syntax to get this to work?
I think it should render this path
new_page_referralpage_reward
The point of this feature is to render rewards in the referral/show.html.erb page
I have created an index partial in my rewards view file and am rendering it in the show action of the referralpages/show.html.erb file.
I think you cannot put more than one resource path in form_for which cause invalid path.
Why you want to put 2 resource path in form?
Do you plan to save the same data for referral & rewards Model?
If, yes use just one path and make a create method in your controller to save to other model.
From this point of view:
The point of this feature is to render rewards in the
referral/show.html.erb page
If you only plan to render the data of rewards to referral/show.html.erb,
in your referral controller
def show
#rewards = Reward.all #example
end
Unless, you have model relationships like:
#Reward Model
belongs_to :refferal
#Referral Model
has_many :rewards or has_one :reward
With model realtionship:
def show
#referal = Referral.all #example
end
show.html.erb View # iterate it:
<%for referral in #referral%>
<% referral.rewards %> # need to iterate if has many
or
<%= referral.reward... %>
<%end%>

Submit a form to a model from my homepage

I have a links model which has all the generic scaffold created for it, however, rather than go to the link#new page, I'd like to submit a form from my homepage that populates a new record.
I only have one text field, but im not sure how to construct the form. I read somewhere you have to specify the controller in the form field but this doesn't appear to be working.
<%= form_for(:link, #link) do |f| %>
<% if #link.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#link.errors.count, "error") %> prohibited this link from being saved:</h2>
<ul>
<% #link.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :url %><br />
<%= f.text_field :url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You don't need to specify anything if you are using default routes.
If the #link is an object that doesn't exist in database, Rails will automatically think this is a form for #new. So the form action will be /links, and method is post, which is the default resource to #create
In your case, you don't need to do anything, just revise the form code to:
<%= form_for(#link) do |f| %>
....
Besides, you need to prepare #link object in home controller, something like
#link = Link.new
All you have to do is add a url parameter to the form_for helper
<%= form_for :link, url: your_home_path do |f| %>

why does this form not take data from a model?

I would like to capture email addresses with this form:
I have decided to create a model only for this and use the views and controller for a different model that is serving only static assets (think: newsletter sign-up).
<%= form_for (#signup) do |f| %>
<% if #signup.errors.any? %>
<div id="error_explanation">
<p><%= pluralize(#signup.errors.count, "error") %> prohibited this post from being saved:</p>
<ul>
<% #signup.errors.full_messages.each do |user| %>
<li><%= user %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email_address %><br />
<%= f.email_field_tag :email_address %>
</div>
<div class="actions">
<%= f.submit %>
</div>
How do I get this form to work? I get undefined method signups_path for #<#<Class:0x00000004f1feb0>:0x00000004f09a98> exception, which is understandable (its looking for a SignupsController by convention).
But I want the form to display in a separate controller I call PagesController and send it to the Signup model.
Additional Info:
I tried passing url: pages_path in the form and get the same exception.
# view inside PagesController
<div class="four columns">
<%= render 'form' %>
</div>
#stub of model
class PagesController < ApplicationController
def index
#signup = Signup.new
end
def create
#signup = Signup.new(params[:signup])
end
end
try:
<%= form_for #sighup, :url => {:controller => :pages, :action => :index} do |f| %>
and I hope you didn't forget the
<% end %>

Render form partial in a different controller (not nested)

I have two models generated with generate scaffolding, one is a LogBook the other is LogEntry. I want to render the form partial for LogEntry on the LogBook show page. When I call render on the partial I get this error:
undefined method `model_name' for NilClass:Class
I assume it is because the default _form uses an instance variable which isn't present when called from a separate controller. So I tried converting the LogEntry _form.html.erb to use local variables and passed them in via the render call. After this here is the error:
Model LogEntry does not respond to Text
How can I include this partial into the show page form a different controller?
Models:
class LogBook < ActiveRecord::Base
belongs_to :User
has_many :LogEntries, :dependent => :destroy
end
class LogEntry < ActiveRecord::Base
belongs_to :LogBook, :class_name => "log_book", :foreign_key => "log_book_id"
end
LogEntry _form.html.erb (using local variable):
<%= form_for(log_entry) do |f| %>
<% if log_entry.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(log_entry.errors.count, "error") %> prohibited this log_entry from being saved:</h2>
<ul>
<% log_entry.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Text %><br />
<%= f.text_field :Text %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
LogBook show.html.erb:
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #log_book.name %>
</p>
<%= render 'log_entries/form', :log_entry => #log_book.LogEntries.new %>
<%= link_to 'Edit', edit_log_book_path(#log_book) %> |
<%= link_to 'Back', log_books_path %>
You can render whatever partial you want as long as you give it's path from the view folder:
<%= render :partial => '/log_entries/form', :log_entry => #log_book.log_entries.build %>
Your path must begin with a / to let Rails
know you're relative to the view folder.
Otherwise it's assumed to be relative to your current folder.
As a sidenote, it's good practive to avoid using instance variables in partial, you did it right then.
Just seen you have an error in your partial's form:
:Text
Should not be a valid column name of your model. Try :text
Try switching the render method as follows:
<%= render :partial => 'log_entries/form', :log_entry => #log_book.LogEntries.new %>
Using just render works when passing an instance variable of the object. However, since you're specifying a file, it's best to use the option.

Resources