How to solve undefined method in rails 5 - ruby-on-rails

First, sorry for my english,
I'm make a forum from scratch and I'm currently having an issue when I generate the post form
Showing D:/Lab/Rails/Forum/app/views/forumposts/_form.html.erb
undefined method `forumposts' for nil:NilClass
Model forumtopic.rb
belongs_to :forumforum
has_many :forumposts, :dependent => :destroy
belongs_to :user
Model forumpost.rb
belongs_to :forumtopic
belongs_to :user
forumposts_controller.rb
def create
#topic = Forumtopic.friendly.find(params[:forumtopic_id])
#forumpost = #topic.forumposts.create(params.require('forumpost').permit(:content))
if #forumpost.save
redirect_to forumtopic_path(#topic)
else
render 'new'
end
end
Views/forumposts/_form.html.erb
<% if signed_in? %>
<div class="wrapper">
<div class="post_form">
<%= simple_form_for([#topic, #topic.forumposts.build]) do |f| %>
<div>
<%= f.text_area :content, class: "post-textarea", placeholder: "Message", cols: 50, rows: 4 %>
</div>
<div>
<%= f.submit "Save ", class: "post-button" %>
</div>
<% end %>
</div>
</div>
<% end %>
views/forumtopics/show.html.erb
<div class="row">
<div class="col-md-12">
<div class="answer"> <%= #forum_topic.forumposts.count %> answers </div> **OK**
</div>
</div>
<%= render #forum_topic.forumposts %> **OK**
<% render 'forumposts/form' %> **Problem**
When I do that in console, I get all the topic's post:
#topic = Forumtopic.first
#topic.forumposts
Please help
thank you

In forumposts_controller.rb you should have action new with tne next code:
def new
#topic = Forumtopic.friendly.find(params[:forumtopic_id])
end

Related

Params problems

I'm doing my first web api on Ruby on Rails (It's a Sale Point). The think here It's makes 'n' sales. So I used the nested_form for doing that, but when I 'confirm' the sale I'm having this problem:
ActionController::ParameterMissing in SalesController#create
param is missing or the value is empty: sale
private
def sale_params
params.require(:sale).permit(:fecha_venta, :id_usuario, carts_attributes: [:id ,:id_producto, :cantidad])
end
whith the strong params.This is controller for 'sale'
class SalesController < ApplicationController
def new
#venta = Sale.new
end
def create
#venta = Sale.new(sale_params)
#venta.id_usuario= current_user.id
#venta.fecha_venta = DateTime.now
if #venta.save
flash[:succes] = "Se ha realizado la venta"
redirect_to sales_index_path
else
flash[:danger] = "Ha ocurrido un error"
render new_sale_path
end
end
private
def sale_params
params.require(:sale).permit(:fecha_venta, :id_usuario, carts_attributes: [:id ,:id_producto, :cantidad])
end
end
I'm using nested_form in the model (and I've already installed the gem "nested_form"). Here is the sale and the cart model:
class Sale < ApplicationRecord
has_many :carts
accepts_nested_attributes_for :carts
end
class Cart < ApplicationRecord
belongs_to :sale
end
And finaly this is the partial form that I'm using
<%= nested_form_for(#venta) do |f| %>
<div class="form-group col-md-12">
<label class="form-control">Vendedor: <%= current_user.nombre_trabajador%></label>
</div>
<%= f.fields_for :carts do |carro| %>
<form class="form-horizontal">
<div class="card-body">
<div class="form-row">
<div class="form-group col-md-5">
<%= carro.collection_select :id_producto, Product.select("products.nombre_producto, products.stock, products.id").where("products.stock > ?", 0), :id, :nombre_producto, {:include_blank => true}, {:class => 'form-control btn btn-secondary dropdown-toggle'} %>
</div>
<div class="form-group col-md-5">
<%= carro.text_field :cantidad, class: "form-control", type: 'number' %>
</div>
<div class="form-group col-md-2">
<%= carro.link_to_remove "Eliminar", :class=> 'btn btn-danger btn-sm' %>
</div>
</div>
</div>
</form>
<% end %>
<div class="row">
<div class="form-actions">
<%= f.link_to_add "Agregar Producto", :carts , :class=> 'btn btn-default btn-sm'%>
</div>
</div>
<br>
<div class="form-actions">
<%= f.submit "Enviar" , :class=> 'btn btn-primary'%>
<%= link_to 'Cancelar', sales_index_path ,:class=> 'btn btn-danger' %>
</div>
<% end %>
I've benn traying to makea solution all day, but nothing.

Prevent creating blank associations in nested attributes forms

I have a form with nested attributes that is sending to the Appointments controller which is creating instances of associated models called Prescriptions, Illnesses, Allergies, and Immunizations. The idea is that a doctor can fill out the form and can add information where needed, but isn't required to fill out everything (not every appointment requires a prescription).
Currently, the form sends out and creates new instances of all the associations with all the attributes blank or nil. I tried adding a validation requiring the presence of the attributes to save, but that creates an error and then nothing can save.
How can I submit one form and prevent it from creating instances of associated models if the fields for that model were empty?
Appointments Controller
def create
#appointment = current_user.appointments.new(appointment_params)
set_associations(#appointment, #patient)
if #appointment.save
Notification.create_appointment_notifications(#appointment, #health_profile)
flash[:notice] = "Your appointment has been saved."
redirect_to patient_health_profile_path(#patient, #health_profile)
else
flash[:notice] = "There was a problem saving your appointment, please try again."
redirect_to patient_health_profile_path(#patient, #health_profile)
end
end
private
def appointment_params
symptoms = params[:appointment][:symptoms].split(",")
#patient = Patient.find(params[:patient_id])
params.require(:appointment).permit(
:diagnosis, :referrals, :notes, :symptoms,
immunizations_attributes: [:name, :expiration_date],
illnesses_attributes: [:name, :status],
allergies_attributes: [:name, :status, :severity],
prescriptions_attributes: [:medicine, :dosage, :refills, :expiration_date]
).merge(symptoms: symptoms,
patient: #patient
)
end
def set_associations(appointment, patient)
appointment.illnesses.each do |illness|
illness.patient = patient
end
appointment.allergies.each do |allergy|
allergy.patient = patient
end
appointment.immunizations.each do |immunization|
immunization.patient = patient
end
appointment.prescriptions.each do |prescription|
prescription.patient = patient
prescription.doctor = current_user
end
end
def set_information
#patient = Patient.find(params[:patient_id])
#health_profile = HealthProfile.find(params[:id])
end
Nested Form
<%= form_for #appointment do |f| %>
<div>
<h4>Appointment</h4>
<div>
<%= f.label :Symptoms %>
<%= f.text_field :symptoms, id: "symptoms-input" %>
</div>
<div>
<%= f.label :Notes %>
<%= f.text_area :notes %>
</div>
<div>
<%= f.label :Diagnosis %>
<%= f.text_field :diagnosis %>
</div>
<div>
<%= f.label :Referrals %>
<%= f.text_area :referrals, id: "referrals-input" %>
</div>
</div>
<div>
<h4>Illnesses</h4>
<div>
<%= f.fields_for :illnesses do |illness| %>
<%= render "appointments/illness_fields", f: illness %>
<% end %>
</div>
<div>
<%= link_to_add_association '+ Illness', f, :illnesses, partial: "appointments/illness_fields" %>
</div>
</div>
<br>
<div>
<h4>Allergies</h4>
<div>
<%= f.fields_for :allergies do |allergy| %>
<%= render "appointments/allergy_fields", f: allergy %>
<% end %>
</div>
<div>
<%= link_to_add_association '+ Allergy', f, :allergies, partial: "appointments/allergy_fields" %>
</div>
</div>
<br>
<div>
<h4>Immunizations</h4>
<div>
<div>
<%= f.fields_for :immunizations do |immunization| %>
<%= render "appointments/immunization_fields", f: immunization %>
<% end%>
</div>
<div>
<%= link_to_add_association '+ Immunization', f, :immunizations, partial: "appointments/immunization_fields" %>
</div>
</div>
</div>
<br>
<div>
<h4>Prescriptions</h4>
<div>
<%= f.fields_for :prescriptions do |prescription| %>
<%= render "appointments/prescription_fields", f: prescription %>
<% end %>
</div>
<div>
<%= link_to_add_association '+ Prescription', f, :prescriptions, partial: "appointments/prescription_fields" %>
</div>
</div>
<%= hidden_field_tag(:patient_id, params[:patient_id]) %>
<%= hidden_field_tag(:id, params[:id]) %>
<div>
<%= f.submit :Submit %>
</div>
<% end %>
In your Appointments Model, add this line:
accepts_nested_attributes_for :illnesses, reject_if: :all_blank, allow_destroy: true

unable to do validations in rails

I have a contact us page
class ContactPagesController < ApplicationController
def new
#contact_page = ContactPage.new
end
def create
#contact_page = ContactPage.new(contact_page_params)
if #contact_page.save
flash[:notice]="details saved successfully"
redirect_to contact_pages_path
else
flash[:notice]="details not saved"
redirect_to contact_pages_path
end
# if #contact_page.errors.any?
# flash[:notice]="there are errors"
# end
end
private
def contact_page_params
params.require(:contact_page).permit( :first_name, :last_name, :email, :phone, :do_you_have_land, :moving_time_frame, :financing, :to$
end
end
and my model
class ContactPage < ApplicationRecord
validates :email, presence: true
end
and the view
new.html.erb
<%= form_for #contact_page, :html => { :class => 'form-horizontal', multipart: true } do |f| %>
<% if #contact_page.errors.any? %>
<div id="error_explanation">
<h3>
<%= pluralize(#contact_page.errors.count, "error") %>
prohibited this employee from being saved:
</h3>
<ul>
<% #contact_page.errors.full_messages.each do |message| %>
<li>
<%= message %>
</li>
<% end %>
</ul>
</div>
<% end %>
<div class="control-group">
<%= f.label :First_Name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :first_name, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :Email, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :email, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :How_can_we_assist_you, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :assist_you, :class => 'text_field' %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
</div>
<% end %>
If all the fields are filled the data is being saved into the database.If email is left blank data is also not being saved inside the database(due to validation), but the error message is also not rendering . The #contact_page.errors.any? inside the view page is being ignored for some reason.I am expecting an error "email can't be blank" on the top of the form.
why the save action is not triggering the validation errors?
my routes for contact page
get 'contact_pages' => 'contact_pages#new', :as => 'contact_pages'
post 'contact_pages' => 'contact_pages#create'
Need help in what I have gone wrong.Any help is highly appreciated.Thanks in advance.
class SaveController < ApplicationController
def new
#contact_page = ContactPage.new
end
def create
if
#contact_page.save
flash[:notice]="Successfuly stored"
redirect_to contact_pages_path
else
flash[:notice]="please check your inputs"
render :new
end
end
end
In View: -
<% if notice %>
<div class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<%= notice %>
</div>
<% end %>
you should user render on error not redirect
def create
#contact_page = ContactPage.new(contact_page_params)
if
#contact_page.save
flash[:notice]="details saved successfully"
redirect_to contact_pages_path
else
flash[:notice]="details not saved"
render :new
end
end

Nested form not displaying submitted content on show page

I am trying to add a polling feature to the app from Hartl's Rails Tutorial. Started off by following #196 Nested Model Form and Nested forms with Rails 4.2 Strong Parameters. After submitting the form, the content saves properly to the database, however, I am unable to see the results in the show page and cannot figure out why.
Models-
class Micropost < ActiveRecord::Base
has_many :polls, dependent: :destroy
accepts_nested_attributes_for :polls, :reject_if => lambda {|a| a[:content].blank? }
def questions_for_form
collection = polls.where(micropost_id: id)
collection.any? ? collection : polls.build
end
end
class Poll < ActiveRecord::Base
belongs_to :micropost
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :answers, :reject_if => lambda {|a| a[:content].blank? }
def answers_for_form
collection = answers.where(micropost_id: id)
collection.any? ? collection : answers.build
end
end
class Answer < ActiveRecord::Base
belongs_to :poll
end
Controllers-
class StaticPagesController < ApplicationController
def home
if logged_in?
#micropost = current_user.microposts.build
#poll = #micropost.polls.build
3.times {#poll.answers.build}
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
end
class MicropostsController < ApplicationController
def create
#micropost = current_user.microposts.build(micropost_params)
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
private
def micropost_params
params.require(:micropost).permit(:content, polls_attributes: [:content, :id, :micropost_id, answers_attributes: [:content, :id, :poll_id]])
end
end
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
end
end
Routes-
Rails.application.routes.draw do
resources :microposts, only: [:create, :destroy]
resources :polls
resources :answers
end
Views-
_micropost_form.html.erb
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new post..." %>
</div>
<button type="button" class="btn btn-default btn-xs" data-toggle="collapse" data-target="#pollcollapse" id="pollbtn">Poll</button>
<div id="pollcollapse" class="collapse">
<%= f.fields_for :polls do |questions_for_form| %>
<%= render 'shared/poll_fields', :f => questions_for_form %>
<% end %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
_poll_fields.html.erb
<div class="field">
<%= f.text_field :content, placeholder: "Poll question..." %>
</div>
<%= f.fields_for :answers do |answers_for_form| %>
<%= render 'shared/answer_fields', :f => answers_for_form %>
<% end %>
_answer_fields.html.erb
<div>
<%= f.text_field :content, placeholder: "Answer" %>
</div>
show.html.erb
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
</h1>
</section>
</aside>
<div class="col-md-8">
<% if #user.microposts.any? %>
<h3>Posts (<%= #user.microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
</div>
_micropost.html.erb
<li id="micropost-<%= micropost.id %>">
<span class="content"><%= micropost.content %></span>
<span>
<% for poll in #micropost.polls %> //Poll & answer content do not appear.
<%= poll.content %>
<% for answer in poll.answers %>
<%= answer.content %>
<% end %>
<% end %>
</span>
</li>
I think this should be all of the relevant information, but please let me know if I am missing anything. Thank you very much for any help at all!
In your _micropost.html.erb partial, you reference #micropost which doesn't appear to be defined anywhere. Try changing that from an instance variable to tbe local variable micropost (learn about the difference between #micropost and micropost here). Also, in Ruby it's recommended by people smarter than me (at least I've read it multiple times) that you should use .each instead of for. The updated code in your partial:
<li id="micropost-<%= micropost.id %>">
<span class="content"><%= micropost.content %></span>
<span>
<% micropost.polls.each do |poll| %>
<%= poll.content %>
<% poll.answers.each do |answer| %>
<%= answer.content %>
<% end %>
<% end %>
</span>
</li>
Also, since you define #microposts in your show action, you can refactor your code in the show view like so:
<div class="col-md-8">
<% if #microposts.any? %>
<h3>Posts (<%= #microposts.count %>)</h3>
<ol class="microposts">
<%= render #microposts %>
</ol>
<%= will_paginate #microposts %>
<% end %>
</div>
Yes instance vs. Local variables issue. I'd say it might be easier to use a gen, but if you are learning rails and you have the time, my opinion is its better to do it yourself the first time. It helps you learn the framework and better able to solve problems when you run into something for which there is no gem. After learning yourself, go with a gem if you find it really serves your purpose... Or make your own gem! Cheers.

Rails - Show associated data on Index view

I'm struggling to have a belongs_to model iterate correctly inside a partial in an index page.
Classes:
class Chapter < ActiveRecord::Base
attr_accessible :name, :chapter_num,
belongs_to :chapter
#fields: :id, :name, :chapter_num
end
class County < ActiveRecord::Base
attr_accessible :name, :county_num, :chapter_id
has_many :counties
#fields: :id, :name, :county_num, :chapter_id
end
class ChaptersController < ApplicationController
def index
#chapters = Chapter.all
#counties = County.all(:joins => :chapter, :select => "counties.*, chapters.id")
end
end
app/views/chapters/index.html.erb:
<h1>Chapter Index</h1>
<%= render #chapters %>
<br />
<%= link_to "Add a new Chapter", new_chapter_path, class: "btn btn-large btn-primary" %>
app/views/chapters/_chapter.html.erb:
<div class="row">
<div class="span5 offset1"><h4><%= link_to chapter.name, edit_chapter_path(chapter.id) %></h4></div>
<div class="span2"><h4><%= chapter.chapter_num %></h4></div>
</div>
<!-- here's where the problem starts -->
<% #counties.each do |county| %>
<div class="row">
<div class="span4 offset1"><%= county.name %></div>
<div class="span4 offset1"><%= county.county_num %></div>
<div class="span2"><%= link_to 'edit', '#' %></div>
</div>
<% end %>
<%= link_to "New county", new_county_path %>
<hr>
The current code shows the screenshot below. The problem is it's iterating through all the counties, not just the counties associated with a given chapter.
How do I add a chapter specific variable within the partial that will cause the counties to iterate based upon the :chapter_id field since I'm in the index view, not the show view?
class ChaptersController < ApplicationController
def index
#chapters = Chapter.all
# #counties = County.all(:joins => :chapter, :select => "counties.*, chapters.id")
end
end
View:
<% chapter.counties.each do |county| %>
I think something like this would work for you:
<%= #chapters.each do |chapter| %>
<div class="row">
<div class="span5 offset1"><h4><%= link_to chapter.name, edit_chapter_path(chapter.id) %></h4></div>
<div class="span2"><h4><%= chapter.chapter_num %></h4></div>
</div
<% chapter.counties.each do |county| %>
<div class="row">
<div class="span4 offset1"><%= county.name %></div>
<div class="span4 offset1"><%= county.county_num %></div>
<div class="span2"><%= link_to 'edit', '#' %></div>
</div>
<% end %>
<%= link_to "New county", new_chapter_county_path(chapter) %>
<% end %>
Note that the key is to understand that because each chapter has many counties, you should iterate through the counties of each chapter via chapter.counties.each which will give you only the counties that belong to that particular chapter.
Also note the different link_to path for creating a new county. If you have your routes set up such that counties are nested under chapters, you should be able to do new_chapter_county_path(chapter)

Resources