Render form partial in a different controller (not nested) - ruby-on-rails

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.

Related

Rails: Add form from different model

In my rails app, i have a project model which can have many project messages.
project has_many project_messages
In projects/show.html.erb, I would like to display all project messages for that project but also create new project messages from this view.
Currently, I am not able to create new project messages from this view.
I have reviewed a number of links but none work for me
Adding Form For Different Model In Same View,
Rails: Show form from different model in a view
My projects/show.html.erb file references as follows:
<div>
<% render partial: 'project_messages/form', :object => #project_message %>
</div>
In the projects_controller.rb file I have included the following:
def show
#project_message = ProjectMessage.new
end
&
def project_params
params.require(:project).permit(:title, :description, :phase_id, :RAGStatus, :currentpphase_id, :project_messages_attributes => [:pMessage, :user_id, :project_id])
end
And in the project.rb file I have the following code also:
accepts_nested_attributes_for :project_messages
project_messages/_form.html.erb
<%= form_with(model: project_message, local: true) do |form| %>
<% if project_message.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(project_message.errors.count, "error") %> prohibited this project_message from being saved:</h2>
<ul>
<% project_message.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form.label :pMessage %>
<%= form.text_field :pMessage, id: :project_message_pMessage, :class => 'au-input au-input--full au-input--h65', placeholder: 'Type a message' %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
The project_messages form partial does not render so I cannot add a new message from this view.
Error:
undefined local variable or method `project_message' for #<#<Class:0x007f5455ced910>:0x007f5459ef8a30>
Did you mean? #project_message
When I add #project_message to the partial, it does not render.
Normally, when rendering a partial like:
<% render partial: 'form', object: #project_message %>
Because you are passing the #project_message as the specially-named object parameter, this creates a special variable with the name of the partial - in this case, form.
Therefore in the partial, you could reference this variable:
<%= form_with(model: form, local: true) do |form| %>
...However, in this case, it doesn't really make sense to call the local variable form! So I would be inclined to use whatever name you're passing it in as - for example, you could do:
<% render partial: 'form', project_message: #project_message %>
And then in the partial:
<%= form_with(model: project_message, local: true) do |form| %>
For more info, see: http://guides.rubyonrails.org/layouts_and_rendering.html#passing-local-variables
In project_messages/_form.html.erb, this line:
<%= form_with(model: project_message, local: true) do |form| %>
Should be changed to this:
<%= form_with(model: object, local: true) do |form| %>
You assigned a local variable object to a partial, so you should use it.
Also, partials may also be called this way:
<% render partial: 'form', object: #project_message %>

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%>

undefined method `premails_path' for #<#<Class:0x4fa8530>:0x52c1ec8>

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

Rails partial locals not working

I got
Class Question < ActiveRecord::Base
has_many :answers
end
and
class Answer < ActiveRecord::Base
belongs_to :question
end
My index action of question list all the questions and the basic CRUD actions.
<% #questions.each do |question| %>
And inside this loop I have another to show all answers to that question
<% question.answers.each do |answer| %>
After the action buttons I rendered the answer form partial
<%= render partial: 'answers/form' , question_id: question.id%>
But when them partial is rendered the question_id to the answer is aways 1.
I also tried
<%= render partial: 'answers/form', :locals => {:question_id => question.id} %>
Still no success.
This is the full index and form codes.
https://gist.github.com/CassioGodinho/7412866
(Please ignore the data-toggle on the Index, its also not working yet)
Its not a good practice to pass new instance variable as local to a partial
you can build the answer and then pass it as locals
<%= render partial: 'answers/form', :locals => {:answer => question.answers.build} %>
and in partial
<div class="answer_form">
<%= form_for(answer) do |f| %>
<% if answer.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(answer.errors.count, "error") %> prohibited this answer from being saved:</h2>
<ul>
<% answer.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :content %><br>
<%= f.text_area :content %>
</div>
<div>
<%= f.label :question %>
<%= f.collection_select(:question_id, #questions, :id, :title) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</div>
As Thomas Klemm showed it was easier to pass the #answer to the partial.
<%= render partial: 'answers/form', :locals => {:#answer => question.answers.build} %>

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 %>

Resources