undefined method from show.html.erb in rails cocoon nested form - ruby-on-rails

I have created a nested form via the cocoon gem, and all is working nicely; however, after filling out the nested form, I can't figure out how to display the nested form data after updating the form in the show.html.erb.
My code:
developments_controller.rb
class DevelopmentsController < ApplicationController
before_action :set_development, only: %i[ show edit update destroy ]
# GET /developments or /developments.json
def index
#developments = Development.all
end
# GET /developments/1 or /developments/1.json
def show
end
# GET /developments/new
def new
#development = Development.new
end
# GET /developments/1/edit
def edit
end
# POST /developments or /developments.json
def create
#development = Development.new(development_params)
respond_to do |format|
if #development.save
format.html { redirect_to #development, notice: "Development was successfully created." }
format.json { render :show, status: :created, location: #development }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #development.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /developments/1 or /developments/1.json
def update
respond_to do |format|
if #development.update(development_params)
format.html { redirect_to #development, notice: "Development was successfully updated." }
format.json { render :show, status: :ok, location: #development }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #development.errors, status: :unprocessable_entity }
end
end
end
# DELETE /developments/1 or /developments/1.json
def destroy
#development.destroy
respond_to do |format|
format.html { redirect_to developments_url, notice: "Development was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_development
#development = Development.find(params[:id])
end
# Only allow a list of trusted parameters through.
def development_params
params.require(:development).permit(:name, :dev_type, :address, :description, :completion, :body_corp, listings_attributes: [:id, :status, :lot_number, :price, :listing_type, :bed, :bath, :car, :land_size, :house_size, :rent, :done, :_destroy])
end
end
development.rb (parent model)
class Development < ApplicationRecord
has_many :listings, inverse_of: :development
accepts_nested_attributes_for :listings, reject_if: :all_blank, allow_destroy: :true
end
listing.rb (child model)
class Listing < ApplicationRecord
belongs_to :development
end
_form.html.erb
<%= form_for #development do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :dev_type %>
<br/>
<%= f.text_field :dev_type %>
</div>
<div class="field">
<%= f.label :address %>
<br/>
<%= f.text_field :address %>
</div>
<div class="field">
<%= f.label :description %>
<br/>
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :completion %>
<br/>
<%= f.text_field :completion %>
</div>
<div class="field">
<%= f.label :body_corp %>
<br/>
<%= f.text_field :body_corp %>
</div>
<h3>Tasks</h3>
<div id="listings">
<%= f.fields_for :listings do |listing| %>
<%= render 'listing_fields', f: listing %>
<% end %>
<div class="links">
<%= link_to_add_association 'add listing', f, :listings %>
</div>
</div>
<%= f.submit %>
<% end %>
_listing_fields.html.erb
<%= form_for #listing do |f| %>
<h3>New Listing</h3>
<div class="nested-fields">
<div class="field">
<%= f.label :status %>
<br/>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.label :lot_number %>
<br/>
<%= f.text_field :lot_number %>
</div>
<div class="field">
<%= f.label :price %>
<br/>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :listing_type %>
<br/>
<%= f.text_field :listing_type %>
</div>
<div class="field">
<%= f.label :bed %>
<br/>
<%= f.text_field :bed %>
</div>
<div class="field">
<%= f.label :bath %>
<br/>
<%= f.text_field :bath %>
</div>
<div class="field">
<%= f.label :car %>
<br/>
<%= f.text_field :car %>
</div>
<div class="field">
<%= f.label :land_size %>
<br/>
<%= f.text_field :land_size %>
</div>
<div class="field">
<%= f.label :house_size %>
<br/>
<%= f.text_field :house_size %>
</div>
<div class="field">
<%= f.label :rent %>
<br/>
<%= f.text_field :rent %>
</div>
<%= link_to_remove_association "remove listing", f %>
</div>
<%= f.submit %>
<% end %>
show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #development.name %>
</p>
<p>
<strong>Dev type:</strong>
<%= #development.dev_type %>
</p>
<p>
<strong>Address:</strong>
<%= #development.address %>
</p>
<p>
<strong>Description:</strong>
<%= #development.description %>
</p>
<p>
<strong>Completion:</strong>
<%= #development.completion %>
</p>
<p>
<strong>Body corp:</strong>
<%= #development.body_corp %>
</p>
<%= link_to 'Edit', edit_development_path(#development) %> |
<%= link_to 'Back', developments_path %>
I've tried calling on a few variations of the code on what's already in show.html.erb, such as #development.listings, #listings and #development.listings_attributes, but whenever I call on a listings_attribute: such as :price, :status etc. from the params in the developments_controller.rb I continually get an error undefined method error. I can't figure out where I'm going wrong, but I know the data is being stored, as it's present when I go to the /edit page on my localhost. I've been following the setup tutorial on https://github.com/nathanvda/cocoon and from this YouTube video: https://www.youtube.com/watch?v=R2iw5BAKBNA which have been great up until displaying the nested form data! The parent data displays no problems at all.
Any help is greatly appreciated!

You can't call the status method on #development.listings, a collection. You should iterate over the collection and call the method on the Listing instance instead.
<% #development.listings.each do |listing| %>
<%= listing.status %>
<% end %>

Related

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

NoMethodError in PostsController#create undefined method `body'

Whenever I try to save the post, this error is showing up.
Here's my new.html.erb file.
<div id="page_wrapper">
<h1>New Post</h1>
<%= form_for :post, url: posts_path do |f| %>
<% if #post.errors.any? %>
<div id="errors">
<h2><%= pluralize(#post.errors.count, "error") %> prevented this post from saving:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %><br>
</p>
<p>
<%= f.label :date %><br>
<%= f.text_field :date %><br>
</p>
<p>
<%= f.label :time %><br>
<%= f.text_field :time %><br>
</p>
<p>
<%= f.label :location %><br>
<%= f.text_field :location %><br>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
</div>
Here's my show.html.erb file.
<div id="page_wrapper">
<h1 class="title">
<%= #post.title %>
</h1>
<p class="date">
Submitted <%= time_ago_in_words(#post.created_at) %> Ago
</p>
<p class="time">
<%= #post.time %>
</p>
<p class="location">
<%= #post.location %>
</p>
</div>
Here's my posts_controller.rb file.
class PostsController < ApplicationController
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :body, :location)
end
end
Hers's my routes.rb file
Rails.application.routes.draw do
resources :posts
root "posts#index"
end
You have added a validation for body in your post.rb. But you don't have the field body in your posts table.
So, when #post.create is invoked, all the validations defined in post.rb are run and since you don't have a body field, you were getting an Undefined method 'body' for Post error.
To solve it, remove the validation for body in post.rb
Remove the following line
validates :body, presence: true
And you should be good to go.
params.require(:post).permit(:title, :body, :location)
You required :body but in your form you have title, date, time and location.
Remove it and make sure you have this attributes in your strong params like this:
params.require(:post).permit(:title, :date, :time, :location)

Validation errors not showing up - Rails 4

For some reason validation errors are not showing up.
my form
<%= form_for [#question.category, #question] do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field panel">
<%= f.label :question_type %><br>
<%= f.select :question_type, [ ["single","single"],["multiple","multiple"] ], selected: f.object.question_type %>
</div>
<div class="field panel">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div class="field panel">
<%= f.label :image %><br>
<% if #question.image? %>
<div class="explanation-image text-center">
<%= image_tag #question.image_url(:resized) %>
<p>
<label>
<%= f.check_box :remove_image %>
Remove image
</label>
</p>
</div>
<% end %>
<%= f.file_field :image %>
<%= f.hidden_field :image_cache %>
</div>
<div class="field panel">
<%= f.label :explanation %><br>
<%= f.text_area :explanation, size: "30x10" %>
</div>
<div class="field panel">
<%= f.label :link_name %><br>
<%= f.text_field :link_name %>
</div>
<div class="field panel">
<%= f.label :link_url %><br>
<%= f.text_area :link %>
</div>
<div class="field panel">
<%= f.label :video_url %><br>
<%= f.text_area :video_url %>
</div>
<div class="field panel">
<%= f.label :category_id %><br><%= #category.title %>
<%= f.hidden_field :category_id %>
</div>
<div class="actions">
<br>
<%= f.submit 'Submit', class:"button round success" %> <%= link_to 'Back', category_questions_path, class: "button round alert" %>
</div>
<% end %>
this is the model
class Question < ActiveRecord::Base
belongs_to :category
has_many :choices
mount_uploader :image, ImageUploader
validates :description, length: {
minimum: 6
}
validates :link, presence: true
end
and parts of the controller
def edit
#category = Category.find(params[:category_id])
#question = #category.questions.find_by(id: params[:id])
end
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to category_question_url(#question.category, #question), notice: 'Question was successfully updated.' }
format.json { render :show, status: :ok, location: #question }
else
format.html {
#category = Category.find(params[:category_id])
#question = #category.questions.find_by(id: params[:id])
render action: :edit
}
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
the error messages code is directly from the scaffolding. i haven't touched it. if i try to edit a question and save it while lets say link field is empty it will reload the edit action correctly but no error message will pop up.
Any clues?
If it fails to save, you redefine the #question variable, before rendering out the page.
#question = #category.questions.find_by(id: params[:id])
this will delete the object which failed to save and was holding the validation errors, and replace it with the one loaded out of the database. Don't do this. I think if you just delete this line it might work ok.

Upload picture NO plugin NO activerecord

i want to create a function into my controller to save a picture uploaded by an admin. I don't want to use plugin or Activerecord, just a function to write the bytes of the picture into the directory app/assets/images/ .
So , when the admin create a new product he puts the picture of the product into the app.
I want to use this function in the action create of the Product Controller.
In this way , before to save in the db the new product , the picture will be saved into the app (not in the db, i want just to write bytes).
I searched on internet and i founded a function to save picture.
I have a strange error : undefined methodread' for "picture.png":String`
Here all my things:
edit.html.erb
<h1>Editing product</h1>
<%= render 'form' ,:multipart => true%>
<%= link_to 'Show', #product %> |
<%= link_to 'Back', products_path %>
_form.html.erb
<%= form_for(#product) do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :image_url %><br>
<%= f.text_field :image_url %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :upload %><br>
<%= file_field :upload, :datafile %></p>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
product_controller.rb
def create
name = params[:upload][:datafile]
directory = Rails.root.join('app', 'assets','images')
# create the file path
path = File.join(directory, name)
# write the file
File.open(path, "wb") { |f| f.write(params[:upload][:datafile].read) }
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
thank you for the help.
EDIT: new error
Since you're using form_for, the actual temp file will be in params[:product][:upload]. Try this
Within the _form.html.erb partial, change the file_field line to
<%= file_field :upload %>
Then, within your create action
name = params[:product][:upload].original_filename
directory = Rails.root.join('app', 'assets','images')
# create the file path
path = File.join(directory, name)
# write the file
File.open(path, "wb") { |f| f.write(params[:product][:upload].read) }

NoMethodError in Pages#contact

I got this error I Created pages model and for pages controller i created a contact, thank you and _form page. but I getting the error "NoMethodError in Pages#contact"
`Showing /home/rohit/Desktop/inertiiaproject/inertiiatwo/app/views/pages/_form.html.erb where line #1 raised:
undefined method model_name' for NilClass:Class
pages_controller.rb file
class PagesController < ApplicationController
def new
#pages = pages.new
end
def create
#pages = pages.new(params[:pages])
if #pages.deliver
render :thank_you
else
render :new
end
end
end
contact.html.erb
<h1>Want to get in touch?</h1>
<p>Please fill out the form below and we'll get back to you as soon as possible.</p>
<%= render 'form', :pages => #pages %>
_form.html.erb
<%= form_for pages do |f| %>
<% if pages.errors.any? %>
<ul>
<% pages.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<div style="display: none;">
<%= f.label :nickname %><br/>
<%= f.text_field :nickname %>
</div>
<div>
<%= f.label :name %><br/>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :email %><br/>
<%= f.text_field :email %>
</div>
<div>
<%= f.label :message %><br/>
<%= f.text_area :message %>
</div>
<div>
<%= f.submit "Send" %>
</div>
<% end %>

Resources