Newbie alert! I hope I can explain my situation accurately and understandably.
I have a model called animals. Another model called statuses. Another called sexes.
From animal.rb model:
class Animal < ActiveRecord::Base
belongs_to :status, :class_name => Status, :foreign_key => :status_id
belongs_to :sex, :class_name => Sex, :foreign_key => :sex_id
end
sex.rb model:
class Sex < ActiveRecord::Base
has_many :animals
end
status.rb model:
class Status < ActiveRecord::Base
has_many :animals
end
In my views/animals/index.html.erb I have this:
<% #animals.each do |animal| %>
<tr>
<td><%= animal.name %></td>
<td><%= animal.eartag %></td>
<td><%= animal.sex.sex %></td>
<td><%= animal.status.status %></td>
...
The column in the table displays the sex from the sexes lookup table fine, but the line for status causes the following error:
NoMethodError in Animals#index
undefined method `status' for nil:NilClass
So I guess Rails is thinking animal.status is nil?? I don't know why it would be when animal.sex is not nil.
Also, I have views/animals/show.html.erb. Part of that is:
<dt><strong><%= model_class.human_attribute_name(:sex_id) %>:</strong></dt>
<dd><%= #animal.sex.sex %></dd>
<dt><strong><%= model_class.human_attribute_name(:status_id) %>:</strong></dt>
<dd><%= #animal.status.status %></dd>
And this works fine. I.e. in the columns for Sex and Status, it displays the values from the sex and status columns of the sex and status tables, respectively, as I want the index.html.erb view to do.
I don't know if it makes any difference, but here's animals_controller.rb:
class AnimalsController < ApplicationController
before_action :set_animal, only: [:show, :edit, :update, :destroy]
# GET /animals
# GET /animals.json
def index
#animals = Animal.all
end
# GET /animals/1
# GET /animals/1.json
def show
end
# GET /animals/new
def new
#animal = Animal.new
end
# GET /animals/1/edit
def edit
end
# POST /animals
# POST /animals.json
def create
#animal = Animal.new(animal_params)
respond_to do |format|
if #animal.save
format.html { redirect_to #animal, notice: 'Animal was successfully created.' }
format.json { render action: 'show', status: :created, location: #animal }
else
format.html { render action: 'new' }
format.json { render json: #animal.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /animals/1
# PATCH/PUT /animals/1.json
def update
respond_to do |format|
if #animal.update(animal_params)
format.html { redirect_to #animal, notice: 'Animal was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #animal.errors, status: :unprocessable_entity }
end
end
end
# DELETE /animals/1
# DELETE /animals/1.json
def destroy
#animal.destroy
respond_to do |format|
format.html { redirect_to animals_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_animal
#animal = Animal.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def animal_params
params.require(:animal).permit(:name, :eartag, :reg_num, :sex_id, :date_birth, :date_acquired, :date_removed, :status_id, :num_horns, :sire_id, :dam_id, :source_id, :origin_id, :percent_black, :percent_lilac, :for_sale, :for_sale_status_id, :quality_id, :sale_price, :to_be_culled, :comments, :comments_web, :show_on_website, :core_flock, :birth_id, :rejected_at_birth)
end
end
I hope this makes some kind of sense. Thanks!
Change this line
<%= animal.status.status %>
to
<%= animal.status.status if animal.status %>
This will prevent the error. Will output animal.status.status only if animal.status is present.
Related
I'm currently trying to pass User_id and Event_id as params for Guest:
Right now in the console, I can create a new guest object using:
Guest.new(user_id: #, event_id: #)
After creating a guest object, I can call 'User.assited_events' to get all the events this user is assisting, same with events I can call 'Event.assitances' to gell all the users assisting this event.
I just want to figure out a way to submit the user_id and event_id from events#index.
I'm using a custom method called 'Assist' inside of Events Controller
def assist
#guest = Guest.create(:user_id => User.find(session[:current_user_id]), :event_id => Event.find(params[:id]))
respond_to do |format|
if #guest.save
format.html { redirect_to root_path, notice: 'You are now assiting this event!' }
format.json { head :no_content}
else
format.html { redirect_to root_path, notice: "An error happened you can't assist this event" }
format.json { render json: #guest.errors, status: :unprocessable_entity }
end
end
end
This the current line to link the assist_event_path at events#index
<td><%= link_to 'Assist', assist_event_path(event), method: :put, data: { confirm: 'Do you want to assist to this event?' } %></td>
The result in the server log is passing both ids but the Guest object is not created:
Processing by EventsController#assist as HTML
Parameters: {"authenticity_token"=>"8nddKRZpYcgYDkfJIv/VXK8Os1FmW1oZ+zRIQUnLlE/dhgIA92chq++leqplfaB+bdqIZnCWlB0vPLRfuoHOGw==", "id"=>"1"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]]
↳ app/controllers/events_controller.rb:65:in `assist'
Event Load (0.2ms) SELECT "events".* FROM "events" WHERE "events"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
↳ app/controllers/events_controller.rb:65:in `assist'
User model
class User < ApplicationRecord
has_many :events
has_many :guests
has_many :assisted_events, :through => :guests, :source => :event
end
Event model
class Event < ApplicationRecord
belongs_to :user
has_many :guests
has_many :assistances, :through => :guests, :source => :user
end
Guest model
class Guest < ApplicationRecord
belongs_to :user
belongs_to :event
end
routes file
Rails.application.routes.draw do
resources :events do
member do
patch :assist
put :assist
end
end
resources :users
root 'events#index'
end
EDIT ----
Events Controller
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
# GET /Events
# GET /Events.json
def index
#events = Event.all
end
# GET /Events/1
# GET /Events/1.json
def show
end
# GET /Events/new
def new
#event = User.find(session[:current_user_id]).events.build
end
# GET /Events/1/edit
def edit
end
# POST /Events
# POST /Events.json
def create
#event = User.find(session[:current_user_id]).events.build(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :new }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Events/1
# PATCH/PUT /Events/1.json
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { render :show, status: :ok, location: #event }
else
format.html { render :edit }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# DELETE /Events/1
# DELETE /Events/1.json
def destroy
#event.destroy
respond_to do |format|
format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
format.json { head :no_content }
end
end
def assist
#guest = Guest.create(:user_id => User.find(session[:current_user_id]), :event_id => Event.find(params[:id]))
respond_to do |format|
if #guest.save
format.html { redirect_to root_path, notice: 'You are now assiting this event!' }
format.json { head :no_content}
else
format.html { redirect_to root_path, notice: "An error happened you can't assist this event" }
format.json { render json: #guest.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
# Only allow a list of trusted parameters through.
def event_params
params.require(:event).permit(:title, :body)
end
end
Events#Index file
<p id="notice"><%= notice %></p>
<h1>Events</h1>
<% if session[:current_user_id].is_a? Integer %>
<h3>Current User ID: <%= session[:current_user_id] %></h3>
<% else %>
<%= link_to 'Create a new user', new_user_path %>
<% end %>
<table>
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #events.each do |event| %>
<tr>
<td><%= event.title %></td>
<td><%= event.body %></td>
</tr>
<tr>
<td><%= link_to 'Show', event %></td>
<td><%= link_to 'Edit', edit_event_path(event) %></td>
<td><%= link_to 'Assist', assist_event_path(event), method: :put, data: { confirm: 'Do you want to assist to this event?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New event', new_event_path %>
Well this is kind of a guess since you didn't post any of your form except the link_to. I have no idea what variables you have passed to the events#index because you didn't post your controller code for that. That said you can pass any params you want with link_to.
edit OK, so it looks like user is in session[:current_user_id] so that is where the user id comes from...
latest edit to simplify
Add this route before your other routes to make sure it's at the top:
put '/assist' => 'events#assist'
Then in your form:
<td><%= link_to 'Assist', assist_path(event_id: event, user_id: session[:current_user_id]), method: :put, data: { confirm: 'Do you want to assist to this event?' } %></td>
Make sure your params are permitted in your strong parameters section.
# Only allow a list of trusted parameters through.
def event_params
params.require(:event).permit(:title, :body, :event_id, :user_id)
end
edit cleaning up your controller code:
def assist
#guest = Guest.new(:user_id => session[:current_user_id], :event_id => event_params[:id])
respond_to do |format|
if #guest.save
format.html { redirect_to root_path, notice: 'You are now assiting this event!' }
format.json { head :no_content}
else
format.html { redirect_to root_path, notice: "An error happened you can't assist this event" }
format.json { render json: #guest.errors, status: :unprocessable_entity }
end
end
end
You were passing the actual Event and User objects to create the #guest object. Also you were using the params, which means you weren't going through the event_params action. The purpose of the event_params action is to permit/deny so that someone can't submit params you don't want.
i have a rails app. i have strange problem in saving form
this is my ticket model .
class Ticket < ApplicationRecord
belongs_to :user
has_many :ticketissues , inverse_of: :ticket
accepts_nested_attributes_for :ticketissues, :reject_if => lambda { |a| a[:body].blank? }
end
this is ticketisue model
class Ticketissue < ApplicationRecord
belongs_to :user
belongs_to :ticket
validates :body, presence: true
end
this is ticket controller
class TicketsController < ApplicationController
before_action :set_ticket, only: [:show, :edit, :update, :destroy]
# GET /tickets
# GET /tickets.json
def index
#tickets = Ticket.all
end
# GET /tickets/1
# GET /tickets/1.json
def show
end
# GET /tickets/new
def new
#ticket = Ticket.new
end
# GET /tickets/1/edit
def edit
end
# POST /tickets
# POST /tickets.json
def create
#ticket = Ticket.new(ticket_params)
#ticket.user_id = current_user.id
#ticket.ticketissues.build
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render :show, status: :created, location: #ticket }
else
format.html { render :new }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tickets/1
# PATCH/PUT /tickets/1.json
def update
respond_to do |format|
if #ticket.update(ticket_params)
format.html { redirect_to #ticket, notice: 'Ticket was successfully updated.' }
format.json { render :show, status: :ok, location: #ticket }
else
format.html { render :edit }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tickets/1
# DELETE /tickets/1.json
def destroy
#ticket.destroy
respond_to do |format|
format.html { redirect_to tickets_url, notice: 'Ticket was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_ticket
#ticket = Ticket.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def ticket_params
params.require(:ticket).permit(:subject, :subsubject, :user_id, ticketissues_attributes: [
:body, :id, :_destroy] )
#params.require(:ticket).permit!
end
end
and my view is like this
<%= f.input :subject , collection: [ "تغییر اطلاعات کسب و کار",
"تغییر اطلاعات یک کوپن",
"سایر موارد"] %>
<%= f.input :subsubject %>
<!-- <%= f.association :user %> -->
</div>
<%= f.simple_fields_for :ticketissue do |p| %>
<%= p.input :body %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
but when i want to create a ticket , form will not save to database
and i get this error:
Started POST "/tickets" for 127.0.0.1 at 2017-04-11 23:52:33 +0430
Processing by TicketsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fsl6nTe0PjmBKpeuh16BRFlYOw0MB93LEYDVEAl6TtT/uu/LwGTA0P2q0bRxIxBUqHqZINXHntrZLt7MuCG84Q==", "ticket"=>{"subject"=>"تغییر اطلاعات کسب و کار", "subsubject"=>"lk", "ticketissue"=>{"body"=>"lkjkjkjkjkkjkj"}}, "commit"=>"Create Ticket"}
Unpermitted parameter: ticketissue
but when i use console and this command:
Ticket.create(subject: 'test' , subsubject: 'ticket test' , ticketissues_attributes: [{body: "[some thing" }] )
every things work fines and all data save.
tanks for read and help.
You must use the plural here
= f.simple_fields_for :ticketissues do |p|
I was trying to show the student name on the submission table but I don't know how to do it. If you can please help me!
Form.rb:
class Form < ActiveRecord::Base
belongs_to :user
has_many :submissions, :dependent => :destroy
has_attached_file :image, styles: { medium: "400x600>" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
end
Submission.rb:
class Submission < ActiveRecord::Base
belongs_to :form
has_many :submissionstudent
has_many :students, :through => :submissionstudent
end
Student.rb:
class Student < ActiveRecord::Base
has_many :submissionstudent
has_many :submissions, :through => :submissionstudent
end
Joint Table: Submissionstudent:
class Submissionstudent < ActiveRecord::Base
belongs_to :submission
belongs_to :student
end
Show Table:
<h1><%= #form.title %></h1>
<p>
<%= image_tag #form.image.url(:medium) %>
</p>
<table class="table table-responsive table-hover">
<% if user_signed_in? %>
<% if #submissions.blank? %>
<h4>No submission just yet</h4>
<% else %>
<thead>
<th>Conflict</th>
<th>Computer</th>
<th>Extra time</th>
<th>AM or PM</th>
</thead>
<tbody>
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.conflict %></td>
<td><%= submission.computer %></td>
<td><%= submission.extra_time %>%</td>
<td><%= submission.am_pm %></td>
<!-- Need to add Edit, Delete -->
</tr>
<% end %>
</tbody>
<% end %>
<% end %>
</table>
<%= link_to 'New Submission', new_form_submission_path(#form) %>
<br>
<%= link_to 'Edit', edit_form_path(#form) %> |
<%= link_to 'Back', forms_path(#form) %>
Submission Controller:
class SubmissionsController < ApplicationController
before_action :set_submission, only: [:show, :edit, :update, :destroy]
before_action :set_form
# GET /submissions/new
def new
#submission = Submission.new
#all_students = Student.all
#submission_student = #submission.submissionstudent.build
end
# GET /submissions/1/edit
def edit
end
# POST /submissions
# POST /submissions.json
def create
#submission = Submission.new(submission_params)
#submission.form_id = #form.id
respond_to do |format|
if #submission.save
format.html { redirect_to #form, notice: 'Submission was successfully created.' }
format.json { render :show, status: :created, location: #submission }
else
format.html { render :new }
format.json { render json: #submission.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /submissions/1
# PATCH/PUT /submissions/1.json
def update
respond_to do |format|
if #submission.update(submission_params)
format.html { redirect_to #submission, notice: 'Submission was successfully updated.' }
format.json { render :show, status: :ok, location: #submission }
else
format.html { render :edit }
format.json { render json: #submission.errors, status: :unprocessable_entity }
end
end
end
# DELETE /submissions/1
# DELETE /submissions/1.json
def destroy
#submission.destroy
respond_to do |format|
format.html { redirect_to submissions_url, notice: 'Submission was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_submission
#submission = Submission.find(params[:id])
end
def set_form
#form = Form.find(params[:form_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def submission_params
params.require(:submission).permit(:conflict, :computer, :extra_time, :am_pm)
end
end
Form Controller:
class FormsController < ApplicationController
before_action :set_form, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#forms = Form.all
end
def show
#submissions = Submission.where(form_id: #form.id).order("conflict DESC")
#student = Student.find params[:id]
end
def new
#form = current_user.forms.build
end
def edit
end
def create
#form = current_user.forms.build(form_params)
respond_to do |format|
if #form.save
format.html { redirect_to #form, notice: 'Form was successfully created.' }
format.json { render :show, status: :created, location: #form }
else
format.html { render :new }
format.json { render json: #form.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /forms/1
# PATCH/PUT /forms/1.json
def update
respond_to do |format|
if #form.update(form_params)
format.html { redirect_to #form, notice: 'Form was successfully updated.' }
format.json { render :show, status: :ok, location: #form }
else
format.html { render :edit }
format.json { render json: #form.errors, status: :unprocessable_entity }
end
end
end
# DELETE /forms/1
# DELETE /forms/1.json
def destroy
#form.destroy
respond_to do |format|
format.html { redirect_to forms_url, notice: 'Form was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_form
#form = Form.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def form_params
params.require(:form).permit(:title, :image)
end
end
Student Controller:
class StudentsController < ApplicationController
before_action :set_student, only: [:show, :edit, :update, :destroy]
# GET /students
# GET /students.json
def index
#students = Student.all
end
# GET /students/1
# GET /students/1.json
def show
end
# GET /students/new
def new
#student = Student.new
end
# GET /students/1/edit
def edit
end
# POST /students
# POST /students.json
def create
#student = Student.new(student_params)
respond_to do |format|
if #student.save
format.html { redirect_to #student, notice: 'Student was successfully created.' }
format.json { render :show, status: :created, location: #student }
else
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /students/1
# PATCH/PUT /students/1.json
def update
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
# DELETE /students/1
# DELETE /students/1.json
def destroy
#student.destroy
respond_to do |format|
format.html { redirect_to students_url, notice: 'Student was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_student
#student = Student.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def student_params
params.require(:student).permit(:name)
end
end
If you need something else just comment and I'll provide it
Thanks for your help.
Short answer is:
...
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.conflict %></td>
<td><%= submission.computer %></td>
<td><%= submission.extra_time %>%</td>
<td><%= submission.am_pm %></td>
<td><%= submission.students.first.name %></td>
</tr>
<% end %>
...
Or to not get error if submission do not have a student
<td><%= submission.students.first.try(:name) %></td>
Long answer is to change the assosiation and only add a column to submissions to link a student (student_id) and delete the jointable (submissionstudent) because you always have one student per submission.
EDIT:
to show all student's name you can do some like this
<td><%= submission.students.pluck(:name).join(' - ') %></td>
or if you need more you can iterate over students
<% #submissions.each do |submission| %>
<tr>
<td><%= submission.conflict %></td>
<td><%= submission.computer %></td>
<td><%= submission.extra_time %>%</td>
<td><%= submission.am_pm %></td>
<td>
<% submission.students.each do |ss| %>
<%= ss.name %> - <%= ss.last_name %>
<% end %>
</td>
</tr>
<% end %>
I'm fairly new to rails, building my first app. I'm running rails 4 w/ bootstrap 3. I'm trying to get a complex form to work. I have two models:
class Employee < ActiveRecord::Base
belongs_to :company
belongs_to :user, :through => :company
has_one :position
accepts_nested_attributes_for :position
end
class Position < ActiveRecord::Base
belongs_to :employees
accepts_nested_attributes_for :employees
end
I have a form where the User can create a new job title (Position Model) and select the employees (Employees Model) that position will be applied to. Basically it's a single form that will add fields to 2 different database tables (Position and Employee).
This is my view:
<%= simple_form_for(#position) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :job_title %>
<%= f.input :job_description %>
</div>
<%= f.fields_for :Employee do |f| %>
<%= f.input :employee_title, label: "Apply to:", collection: Employee.all, label_method: :first_name, as: :check_boxes %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Below are the controllers:
class PositionsController < ApplicationController
before_action :set_position, only: [:show, :edit, :update, :destroy]
# GET /positions
# GET /positions.json
def index
#positions = Position.all
end
# GET /positions/1
# GET /positions/1.json
def show
end
# GET /positions/new
def new
#position = Position.new
end
# GET /positions/1/edit
def edit
end
# POST /positions
# POST /positions.json
def create
#position = Position.new(position_params)
respond_to do |format|
if #position.save
format.html { redirect_to #position, notice: 'position was successfully created.' }
format.json { render action: 'show', status: :created, location: #position }
else
format.html { render action: 'new' }
format.json { render json: #position.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /positions/1
# PATCH/PUT /positions/1.json
def update
respond_to do |format|
if #position.update(position_params)
format.html { redirect_to #position, notice: 'position was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #position.errors, status: :unprocessable_entity }
end
end
end
# DELETE /positions/1
# DELETE /positions/1.json
def destroy
#position.destroy
respond_to do |format|
format.html { redirect_to positions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_position
#position = Position.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def position_params
params.require(:position).permit(:position_title, :position_description, :position_create_date)
end
end
class EmployeesController < ApplicationController
# encoding: UTF-8
before_action :set_employee, only: [:show, :edit, :update, :destroy]
# GET /employees
# GET /employees.json
def index
#employees = Employee.all
end
# GET /employees/1
# GET /employees/1.json
def show
end
# GET /employees/new
def new
#employee = Employee.new
end
# GET /employees/1/edit
def edit
end
# POST /employees
# POST /employees.json
def create
#employee = Employee.new(employee_params)
respond_to do |format|
if #employee.save
format.html { redirect_to #employee, notice: 'Employee was successfully created.' }
format.json { render action: 'show', status: :created, location: #employee }
else
format.html { render action: 'new' }
format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /employees/1
# PATCH/PUT /employees/1.json
def update
respond_to do |format|
if #employee.update(employee_params)
format.html { redirect_to #employee, notice: 'Employee was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #employee.errors, status: :unprocessable_entity }
end
end
end
# DELETE /employees/1
# DELETE /employees/1.json
def destroy
#employee.destroy
respond_to do |format|
format.html { redirect_to employees_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_employee
#employee = Employee.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def employee_params
params.require(:employee).permit(:first_name, :last_name, :employee_title)
end
end
The problem I'm facing is I get the form to render perfectly, but when I submit it, only fields that belong to the Position model get recorded. The :employee_title stays blank. Any suggestions what the problem is?
Thank you!!
Too many points to fit in a comment:
belongs_to :employees should be singular: belongs_to :employee
Your fields_for should be like (differentiate the ff from parent form):
<%= f.fields_for :Employee do |ff| %>
<%= ff.input :employee_title, label: "Apply to:", collection: Employee.all,
label_method: :first_name, as: :check_boxes %>
<% end %>
If it doesn't work, supply your controller also and I'll update my answer.
Edit:
After seeing your controllers, it seems most likely to be case of unpermitted params.
In position_controller.rb add employee params to position params
def position_params
params.require(:position).permit(:position_title, :position_description, :position_create_date, employees_attributes: [:first_name, :last_name, :employee_title])
end
I'm struggling to get nested attributes down. Working off of Railscast 196, I tried to setup my own app that does basic nesting. Users can create scavenger hunts. Each hunt consists of a series of tasks (that can belong to any hunt, not just one). I got a little help here and tried to learn from a post with a similar issue, but I'm still stuck. I've been hacking around for hours and I've hit a brick wall.
class HuntsController < ApplicationController
def index
#title = "All Hunts"
#hunts = Hunt.paginate(:page => params[:page])
end
def show
#hunt = Hunt.find(params[:id])
#title = #hunt.name
#tasks = #hunst.tasks.paginate(:page => params[:page])
end
def new
if current_user?(nil) then
redirect_to signin_path
else
#hunt = Hunt.new
#title = "New Hunt"
3.times do
#hunt = #hunt.tasks.build
#hunt = #hunt.hunt_tasks.build
hunt = #hunt.hunt_tasks.build.build_task
end
end
end
def create
#hunt = Hunt.new(params[:hunt])
if #hunt.save
flash[:success] = "Hunt created!"
redirect_to hunts_path
else
#title = "New Hunt"
render 'new'
end
end
....
end
With this code, when I try and create a new hunt, I'm told that there's no method "build_task" (it's undefined). So when I remove that line and use the second bit of code that's commented out above, I get the error below.
NoMethodError in Hunts#new
Showing /Users/bendowney/Sites/MyChi/app/views/shared/_error_messages.html.erb where line #1 raised:
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.errors
Extracted source (around line #1):
1: <% if object.errors.any? %>
2: <div id="error_explanation">
3: <h2><%= pluralize(object.errors.count, "error") %>
4: prohibited this <%= object.class.to_s.underscore.humanize.downcase %>
Trace of template inclusion: app/views/tasks/_fields.html.erb, app/views/hunts/_fields.html.erb, app/views/hunts/new.html.erb
And when I use the first bit of code that's commented out in the hunt controller, then I get an error telling me that my 'new' method has an unintialized constant:
NameError in HuntsController#new
uninitialized constant Hunt::Tasks
I'm at my wit's end. Any suggestions on what exactly I'm doing wrong? Or a strategy Here are my models:
class Hunt < ActiveRecord::Base
has_many :hunt_tasks
has_many :tasks, :through => :hunt_tasks #, :foreign_key => :hunt_id
attr_accessible :name
validates :name, :presence => true,
:length => { :maximum => 50 } ,
:uniqueness => { :case_sensitive => false }
end
class Task < ActiveRecord::Base
has_many :hunt_tasks
has_many :hunts, :through => :hunt_tasks#, :foreign_key => :hunt_id
attr_accessible :name
validates :name, :presence => true,
:length => { :maximum => 50 } ,
:uniqueness => { :case_sensitive => false }
end
class HuntTask < ActiveRecord::Base
belongs_to :hunts # the id for the association is in this table
belongs_to :tasks
end
When you create an association between 2 of your models, you add functionality to them, depending on how you define your relationship. Each type kinda adds different functions to your model.
I really recommend reading this guide -> http://guides.rubyonrails.org/association_basics.html
Here you can see which functions get added by each different type of association.
http://guides.rubyonrails.org/association_basics.html#detailed-association-reference
If I do a small sample program like...
class HuntsController < ApplicationController
# GET /hunts
# GET /hunts.json
def index
#hunts = Hunt.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #hunts }
end
end
# GET /hunts/1
# GET /hunts/1.json
def show
#hunt = Hunt.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #hunt }
end
end
# GET /hunts/new
# GET /hunts/new.json
def new
#hunt = Hunt.new
3.times do |i|
t = #hunt.hunt_tasks.build
t.name = "task-#{i}"
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #hunt }
end
end
# GET /hunts/1/edit
def edit
#hunt = Hunt.find(params[:id])
end
# POST /hunts
# POST /hunts.json
def create
#hunt = Hunt.new(params[:hunt])
respond_to do |format|
if #hunt.save
format.html { redirect_to #hunt, notice: 'Hunt was successfully created.' }
format.json { render json: #hunt, status: :created, location: #hunt }
else
format.html { render action: "new" }
format.json { render json: #hunt.errors, status: :unprocessable_entity }
end
end
end
# PUT /hunts/1
# PUT /hunts/1.json
def update
#hunt = Hunt.find(params[:id])
respond_to do |format|
if #hunt.update_attributes(params[:hunt])
format.html { redirect_to #hunt, notice: 'Hunt was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #hunt.errors, status: :unprocessable_entity }
end
end
end
# DELETE /hunts/1
# DELETE /hunts/1.json
def destroy
#hunt = Hunt.find(params[:id])
#hunt.destroy
respond_to do |format|
format.html { redirect_to hunts_url }
format.json { head :no_content }
end
end
end
and this model-relation
class Hunt < ActiveRecord::Base
has_many :hunt_tasks
end
class HuntTask < ActiveRecord::Base
belongs_to :hunt
end
and add this snippet somewhere in views/hunts/_form.html
<% #hunt.hunt_tasks.each do |t| %>
<li><%= t.name %></li>
<% end %>
I get regular output, seeing that the 3 tasks were created.
have you tried
hunttask = #hunt.build_hunt_task
in the HuntsController new action?
http://guides.rubyonrails.org/association_basics.html#detailed-association-reference
The immediate error you are seeing is in app/views/shared/_error_messages.html.erb. object is not defined, You probably need to find where that partial is called. Find:
render :partial=>"/shared/error"
replace it with
render :partial=>"/shared/error", :locals=>{:object=>#hunt}
If you find it in app/views/hunts somewhere, if you find in in app/views/tasks, replace #hunt with #task
That will at least show you what the real error is.