undefined local variable or method when rendering in show.html.erb - ruby-on-rails

I'm trying to create a comment like system where the user can add a 'outcome' to a 'decision'.
Now i've rendered the form and the outcomes in the show.html.erb of 'decisions' but the outcomes give the following error: undefined local variable or method `outcomes' for #<#:0x007fc6046099e8>
My code:
controllers/outcomes_controller.rb
class OutcomesController < ApplicationController
def create
#decision = Decision.find(params[:decision_id])
#outcome = #decision.outcomes.create(params[:outcome].permit(:actual, :strength, :weakness))
redirect_to decision_path(#decision)
end
end
models/outcome.rb
class Outcome < ActiveRecord::Base
belongs_to :decision
end
models/decision.rb
class Decision < ActiveRecord::Base
has_many :outcomes
end
decisions/show.html.erb
<h1>Decision showpage</h1>
<h2><%= #decision.title %></h2>
<p><%= #decision.created_at %></p>
<p><%= #decision.forecast %></p>
<p><%= #decision.review_date %></p>
<%= render #decision.outcomes %>
<%= link_to "Delete Decision", decision_path(#decision), method: :delete, data: { confirm: "Are you sure?" } %>
<%= render "outcomes/form" %>
<%= render "outcomes/outcome" %>
outcomes/_form.html.erb
<%= form_for([#decision, #decision.outcomes.build]) do |f| %>
<%= f.label :actual %>:
<%= f.text_field :actual %> <br/>
<%= f.label :strength %>:
<%= f.text_area :strength %> <br/>
<%= f.label :weakness %>:
<%= f.text_area :weakness %> <br/>
<%= f.submit %>
<% end %>
outcomes/_outcome.html.erb
<%= outcomes.actual %>
<%= outcomes.strength %>
<%= outcomes.weakness %>
Can anyone help me by explaining why this error occurs and what i could do to make it work?

It sounds like you might need to pass your variables as arguments to your partial. When you try to call outcomes.actual, it doesn't know what outcomes is. You either need to pass it as a local variable:
<%= render "outcomes/outcome", locals: {outcomes: #decision.outcomes} %>
or simply get it from your #decision instance variable:
outcomes/_outcome.html.erb
<%= #decision.outcomes.actual %>.

Related

Rails - Couldn't find Student with 'id'=

I'm getting the error above when I try to create a a 'mark' for a 'student'. I can't figure out how to pass the :student_id when I create a new mark.
Routes
Rails.application.routes.draw do
resources :students do
resources :marks
end
resources :marks
root 'students#index'
Marks Controller
class MarksController < ApplicationController
def create
#student = Student.find(params[:student_id])
#mark = #student.marks.create(params[:input1, :input2, :input3, :weight1, :weight2, :weight3, :mark1, :mark2, :mark3, :final_mark].permit(:input1, :input2, :input3, :weight1, :weight2, :weight3, :mark1, :mark2, :mark3, :final_mark))
#mark.save
if #mark.save
redirect_to student_path(#student)
else
render 'new'
end
end
def new
#mark = Mark.new
end
private
def set_mark
#mark = Mark.find(params[:id])
end
end
Students Show View
<p id="notice"><%= notice %></p>
<p>
<strong>Student Number</strong>
<%= #student.StudentNumber %>
</p>
<p>
<strong>Project Title</strong>
<%= #student.ProjectTitle %>
</p>
<p>
<strong>Project PDF</strong>
<%= #student.ProjectTitle %>
</p>
<p>
<strong>Reader 1</strong>
<%= #student.Reader1 %>
</p>
<p>
<strong>Reader 2</strong>
<%= #student.Reader2 %>
</p>
<h3> <%= link_to 'Add Mark', new_student_mark_path(#student), class:"btn btn-warning"%> </h3>
<p>
<strong>Reader 3</strong>
<%= #student.Reader3 %>
</p>
<%= link_to 'Edit', edit_student_path(#student) %> |
<%= link_to 'Back', students_path %>
Marks Form
<%= form_for #mark, html: {multipart: true} do |f| %>
<% if #mark.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#mark.errors.count, "error") %> prohibited this grading from being saved:</h2>
<ul>
<% #mark.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label 'Introduction' %><br>
<%= f.text_area :input1 %>
<%= f.number_field :weight1 %>
<%= f.number_field :mark1 %>
</div>
<div class="field">
<%= f.label 'Main' %><br>
<%= f.text_area :input2 %>
<%= f.number_field :weight2 %>
<%= f.number_field :mark2 %>
</div>
<div class="field">
<%= f.label 'Conclusion' %><br>
<%= f.text_area :input3 %>
<%= f.number_field :weight3 %>
<%= f.number_field :mark3 %>
</div>
<div class="actions">
<%= f.submit class:"btn-xs btn-success"%>
</div>
<% end %>
Mark model
class Mark < ActiveRecord::Base
belongs_to :student
end
Student Model
class Student < ActiveRecord::Base
has_many :marks
has_attached_file :document
validates_attachment :document, :content_type => { :content_type => %w(application/pdf) }
end
It's probably something really stupid but if anyone could explain the problem I'd be really grateful.
Thanks
I don't suggest you using hidden fields for this purpose.
You should pass student together with mark into form_for helper and rails will generate proper url for you which will look like: /students/:student_id/marks
In this case it will be possible to extract student_id from params in your action later.
form_for [#student, #mark], html: {multipart: true} do |f|
More information about nested resources:
http://guides.rubyonrails.org/routing.html#nested-resources
http://www.informit.com/articles/article.aspx?p=1671632&seqNum=7
https://gist.github.com/jhjguxin/3074080
UPDATE:
Forgot to mention that in order to make this work you need to pass student instance into your template at new action:
def new
#student = Student.find(params[:student_id])
#mark = #student.marks.build
end

Gem dragonfly. How to make the list of current files on edit view?

I have model Project and in model have field documents(files). I am using gem dragonfly. When editing a project, how to make the list of current files? At this time on the edit page the list of files fields show: "The file is not selected". I do next: ​
projects_controller:
def edit
end
def update
if #project.update(project_params)
redirect_to #project
else
render :edit
end
end
private
def set_project
#project = Project.find(params[:id])
end
def set_payment_types
#payment_types = PaymentOption.all
end
def project_params
params.require(:project).permit(:title, :description, :price, :location,
:anonymity, :price_category, :category_id, :skill_list, documents_attributes: [:attachment], payment_option_ids: [])
end
edit.html.erb:
<%= form_for #project do |f| %>
<p>
<%= f.label 'Name' %>
<%= f.text_field :title %>
</p>
<P>
<%= f.label 'Budget' %>
<%= f.text_field :price %>
für
<%= f.select :price_category, Project::PRICE_CATEGORIES %>
</P>
<p>
<%= f.label 'Description' %>
<%= f.text_area :description %>
</p>
<p>
<%= f.label 'Category' %>
<%= f.collection_select :category_id, Category.all, :id, :name %>
</p>
<p>
<%= f.label 'Skills Freelancer (15 pieces) *' %>
<%= f.text_field :skill_list %>
</p>
<p>
<%= f.label 'Location' %>
<%= f.text_field :location %>
</p>
<ul>
<% #payment_types.each do |type| %>
<li><%= check_box_tag 'project[payment_option_ids][]', type.id %>
<%= type.name %>
</li>
<% end %>
</ul>
<p>
<b>Anonymity order</b>
</p>
Setup allows for players to remain anonymous. Note that this may reduce the number of responses.
<p>
<%= f.label 'Place Order anonymously' %>
<%= f.check_box :anonymity %>
</p>
<p>
<%= f.fields_for :documents do |d| %>
<%= render 'document_fields', f: d %>
<% end %>
<div class="links">
<%= link_to_add_association 'add file', f, :documents %>
</div>
</p>
<P>
<%= f.submit 'Edit' %>
</P>
<% end %>
​_document_fields.html.erb:
<div class="nested-fields">
<%= f.label :attachment %>
<%= f.file_field :attachment %>
<%= link_to_remove_association "remove file", f %>
</div>
document.rb
class Document < ApplicationRecord
belongs_to :project
dragonfly_accessor :attachment
end
On the edit page the list of files fields show: "The file is not selected", but must be specified ​current files.
file_field is for uploading new files only, not for displaying what is already in the database. For displaying a list of uploaded files, you should just display the name of the file and/or an image tag with the thumbnail and provide a destroy link.
You can also provide a link to create a new attachment.
edit.html.erb
<div>
<ul>
<%= #project.documents.each do |document| %>
<li>
<%= document.attachment.name %>
<%= link_to "Delete", document_path(document), method: :delete, data: { confirm: 'Are you sure you want to delete this?' } %>
</li>
<% end %>
</ul>
<div class="links">
<%= link_to_add_association 'add file', f, :documents %>
</div>
</div>

How to edit model on show view of other model

I have the model Customer, and binded by has_many model Location. This is customer and his locations (adresses). After creating a new customer application redirects on show view of Customer model (shows all data just entered). On show view I have form for location add. There are already entered locations shows on this view and each of them has the link to edit each separate location. I need, when user click on location edit link, he redirects to show view of Customer model, but the form already contains the data of clicked location. Show view code of Customer model:
<p>Customer info:<br>
<strong><%= #customer.name %></strong><br />
<%= #customer.kind.name %><br />
<%= #customer.adres %><br />
<%= #customer.phone %><br />
<%= #customer.comment %><br />
</p>
<h3>Delivery location:</h3>
<% if #locations %>
<ul>
<% #locations.each do |loc| %>
<li>
<%= loc.adres %>
<%= loc.phone %>
<%= loc.comment %>
</li>
<% end %>
</ul>
<% end %>
<%= form_for Location.new do |l| %>
<%= l.text_field :adres %><br>
<%= l.text_field :phone %><br>
<%= l.text_field :comment %><br>
<%= l.text_field :customer_id, type: "hidden", value: #customer.id %><br>
<%= l.submit "Add" %>
<% end %>
<%= link_to "Home", root_path %>
You'd just set #location depending on whether specific params have been sent:
#app/controllers/customers_controller.rb
class CustomersController < ApplicationController
def show
#customer = Customer.find params[:id]
#location = params[:location_id] ? #customer.locations.find(params[:location_id]) : #customer.locations.new
end
end
This would allow you to populate the form as follows:
#app/views/customers/show.html.erb
Customer info:<br>
<%= content_tag :strong, #customer.name %>
<%= #customer.kind.name %>
<%= #customer.adres %>
<%= #customer.phone %>
<%= #customer.comment %>
<h3>Delivery location:</h3>
<% if #customer.locations %>
<ul>
<% #customer.locations.each do |loc| %>
<%= content_tag :li do %>
<%= loc.adres %>
<%= loc.phone %>
<%= loc.comment %>
<%= link_to "Edit", customer_path(#customer, location_id: loc.id) %>
<% end %>
<% end %>
</ul>
<% end %>
<%= form_for #location do |l| %>
<%= l.text_field :adres %><br>
<%= l.text_field :phone %><br>
<%= l.text_field :comment %><br>
<%= l.text_field :customer_id, type: "hidden", value: #customer.id %><br>
<%= l.submit %>
<% end %>
--
To manage the routes (to pass location_id), you'll be best creating a custom route:
#config/routes.rb
resources :customers do
get ":location_id", on: :member, action: :show, as: :location #-> url.com/customers/:id/:location_id
end
This will mean you'll have to reference the other link in your view:
<%= link_to "Edit", customer_location_path(#customer, loc.id) %>

Showing nested form text_field as text in index page

I'm totally new to Rails, so I'm sorry for the stupid question:
This is the code to generate my form and its nested form:
<%= form_for #job do |form| %>
<div><%= form.label :department %><%= form.text_field :department %></div>
<div><%= form.label :enabled %><%= form.check_box :enabled %></div>
<!-- job description form -->
<%= form.fields_for :job_descriptions do |subform| %>
<div><%= subform.hidden_field :language %></div>
<div><%= subform.object.language %></div>
<div><%= subform.label "Job Name" %><%= subform.text_field :title %></div>
<div><%= subform.label "Header" %><%= subform.text_field :short_text %></div>
<div><%= subform.label "Content" %><%= subform.text_area :text %></div>
<% end %>
<!-- end of job description form -->
<div><%= form.submit %></div>
<% end %>
While this is part of the index.html.erb where I want to display text_fields from my subform such as :title, :short_text and :text as static text (I'm trying with :title in this particular case):
<% #jobs.each do |job| %>
<li>
<%= job.title %>
<%= job.department %>
<%= job.enabled %>
<%= link_to 'Show', job_path(job) %>
<%= link_to 'Delete', job_path(job), method: :delete, data: { confirm: 'Are you sure?' } %>
</li>
<% end %>
The error I get is:
undefined method `title' for #<Job:0x007fcdde2001a8>
My job.rb file looks like this:
class Job < ActiveRecord::Base
has_many :job_descriptions, :dependent => :destroy
accepts_nested_attributes_for :job_descriptions
def self.languages
[:de, :en]
end
end
Thank you very much in advance for any help.
<%= form_for #job do |form| %>
...
<%= form.fields_for :job_descriptions do |subform| %>
<% if subform.object.active? %>
<%= subform.text_field :title %>
<% end %>
<% end %>
...
<% end %>

Ruby on Rails, instead of update make new entry to model

I made a simple demo site, with an model for the patients name (name:string) and another model with the treatment (content:text). I created this "project" to learn more about the accepts_nested_attribute for tag and the fields_for tag.
Now my problem is that on the patient show page i created an nested formula for the treatment , like you can see here:
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #patient.name %>
</p>
<ol>
<% for treatment in #patient.treatments %>
<li><%= treatment.content %></li>
<% end %>
</ol>
<%= form_for(#patient) do |f| %>
<%= f.fields_for :treatments do |builder| %>
<div class="field">
<%= builder.label :content %><br />
<%= builder.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Edit', edit_patient_path(#patient) %> |
<%= link_to 'Back', patients_path %>
So my problem is that in the builder.text_field :content better called the input shows up the last saved treatment from <%= builder.content %>, but i want that he does not update it instead i want to add new treatments! Hopefully somebody understands me! Thanks
I would create separate controller for creating only the treatment, eg.
# treatments_controller.rb
class TreatmentsController < ApplicationController
def create
#patient = Patient.find(params[:patient_id])
#treatment = #patient.treatments.new(params[:treatment])
if #treatment.save
redirect_to #patient
else
# handle unsuccessful treatment save
end
end
end
# routes.rb:
resources :patients do
resources :treatments, only: :create
end
# form:
<%= form_for #patient, #treatment do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You should also set #treatment variable in the patient#show action, like this:
#treatment = #patient.treatments.new

Resources