Rails how to create an independent object - ruby-on-rails

Two objects Task and Project have an association has_many - belongs_to:
class Project < ActiveRecord::Base
has_many :tasks, dependent: :destroy
end
class Task < ActiveRecord::Base
belongs_to :project
end
Task controller, method to create an associated object:
def create
#project = Project.find(params[:project_id])
#task = #project.tasks.build(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #project, notice: 'Task was successfully created.' }
format.js {}
format.json { render json: #task, status: :created, location: #task }
else
format.html { render action: "new" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
View task#index, where a list of all tasks. Task controller method index:
def index
#tasks = Task.all
#task= Task.new
end
How to create an independent object Task in this method?
Error:
ActiveRecord::RecordNotFound in TasksController#create
Couldn't find Project with 'id'=
Can I create another method create and use it?

add the following lines to your Project Model.
class Project < ActiveRecord::Base
has_many :tasks, dependent: :destroy
accepts_nested_attributes_for :tasks,
:allow_destroy => true
end
and in projects controller
private
def project_params
params.require(:project).permit(:name, ....., taks_attributes: [:id, .....,:_destroy])
end

def index
#tasks = Task.all
#task = Task.new
end
def create
#task = if params[:project_id]
#project = Project.find(params[:project_id])
#project.tasks.build(task_params)
else
Task.new(task_params)
end
...

Related

NoMethodError in ParticipantsController#new

Why does the error occur?
There hasen't been an adquate/similar solution for my problem. I just could find some tips and tricks here but now I am stuck.
We have a course management system. You can add new coures, participants and persons among other things. I had to change the database. Now there is a persons table, too. Earlier all informations about persons respectively participants where just saved in the participants table. Now when a new participant is added the persons table is involved.
We want to add a new participant of a course. I adjusted the new action in the participants controller and I was hoping passing all data like in the old way. The old way was working to add a new participant.
Earlier the way was: course > new participant form
Now it is: course > search for a person to use it in the form > new participant form
I think (better ways accepted) I just adjust the old code?! Below is my try.
The Error
NoMethodError in ParticipantsController#new undefined method `participants' for []:Array
occurs.
Here are the old classes:
Model Course
class Course < ActiveRecord::Base
has_many :participants
Model Participant
class Participant < ActiveRecord::Base
belongs_to :course
belongs_to :organization
belongs_to :function
ParticipantsController
class ParticipantsController < ApplicationController
....
def new
#course = Course.find(params[:course_id])
#participant = #course.participants.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #participant }
end
end
def create
#course = Course.find(params[:course_id])
#participant = #course.participants.new(params[:participant])
#course.updated_by = current_user.cn
#course.send(:create_version)
#course.tag_version(t(:participant_added))
#course.save!
respond_to do |format|
if #participant.save
format.html { redirect_to course_path(#participant.course), notice: 'Participant was successfully created.' }
format.json { render json: #participant, status: :created, location: #participant }
else
format.html { render action: "new" }
format.json { render json: #participant.errors, status: :unprocessable_entity }
end
end
end
When you look below at the course view snippet there is the old and new path to the form. Note that the person search is in between the course and the new participant form now.
**old** <%= link_to t(:add), new_course_participant_path(#course) %>
**new** <%= link_to t(:add), course_persons_path(#course, #person)%>
Here are the new classes
class Participant < ActiveRecord::Base
belongs_to :course
belongs_to :function
belongs_to :person
class Person < ActiveRecord::Base
has_many :participants
has_many :courses, through: :participants
Here are my adjustments in the ParticipantsController. My thoughts are maybe naive because I am still learning ruby on rails.
class ParticipantsController < ApplicationController
def new
#person = Person.find(params[:person_id])
#participant = Participant.find_by_person_id(params[:person_id])
#course= Course.find(:all, :conditions => {:id => #participant})
#participant = #course.participants.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #participant }
end
end
def create
#course= Course.find(params[:course_id])
#participant = #course.participants.new(params[:participant])
#course.updated_by = current_user.cn
#course.send(:create_version)
#course.tag_version(t(:participant_added))
#course.save!
respond_to do |format|
if #participant.save
format.html { redirect_to course_path(#participant.course), notice: 'Participant was successfully created.' }
format.json { render json: #participant, status: :created, location: #participant }
else
format.html { render action: "new" }
format.json { render json: #participant.errors, status: :unprocessable_entity }
end
end
end
Thanks in advance
Rewrite:
#person = Person.find(params[:person_id])
#participant = Participant.find_by_person_id(params[:person_id])
#course= Course.find(:all, :conditions => {:id => #participant})
#participant = #course.participants.build
To:
#person = Person.find(params[:person_id])
#course = Participant.find_by_person_id(params[:person_id]).course
#participant = #course.participants.build
Watch for out for exception in case Participant.find_by_person_id(params[:person_id]) returns a nil

ActiveModel::MissingAttributeError - rails

I have some problem with my code:
Models:
class UsefulPhrase < ActiveRecord::Base
has_many :useful_phrase_contents
accepts_nested_attributes_for :useful_phrase_contents
validates_presence_of :key
end
class UsefulPhraseContent < ActiveRecord::Base
belongs_to :useful_phrase
attr_accessor :useful_phrase_id
validates_presence_of :language, :content
end
Controller:
def new
#useful_phrase = UsefulPhrase.new
#available_languages = available_languages
#useful_phrase.useful_phrase_contents.build
end
def create
#useful_phrase = UsefulPhrase.new(useful_phrase_params)
#useful_phrase.useful_phrase_contents.build(upc_params)
respond_to do |format|
if #useful_phrase.save
format.html { redirect_to #useful_phrase, notice: 'bla-bla' }
format.json { render :show, status: :created, location: #useful_phrase }
else
format.html { render :new }
format.json { render json: #useful_phrase.errors, status: :unprocessable_entity }
end
end
end
def useful_phrase_params
params.require(:useful_phrase).permit(:key)
end
def upc_params
params.require(:useful_phrase).require(:useful_phrase_content).permit(:language, :content)
end
When i'm trying save any record I get:
ActiveModel::MissingAttributeError at /useful_phrases
can't write unknown attribute useful_phrase_id
I don't know how to repair it.
try edit your parameter in your upc_params
params.require(:useful_phrase)
.permit(:language, content, :useful_phrase_content => [puttheattributefor use_ful_phrase_content])

Matching up collection_select output with strong parameters

In rails console & using the models below, I connected grades K, 1, and 2 to the school whose Edit form has this select field:
As you can see, that association correctly selects the 3 items in the field, but if I click to select/deselect grades, those changes aren't getting saved.
Here are the models:
# app/models/school.rb
class School < ActiveRecord::Base
has_many :grades_schools, inverse_of: :school
has_many :grades, through: :grades_schools
accepts_nested_attributes_for :grades_schools, allow_destroy: true
end
# app/models/grades_school.rb
class GradesSchool < ActiveRecord::Base
belongs_to :school
belongs_to :grade
end
# app/models/grade.rb
class Grade < ActiveRecord::Base
has_many :grades_schools, inverse_of: :grade
has_many :schools, through: :grades_schools
end
The form looks like this:
# app/views/schools/_form.html.haml
= form_for(#school) do |f|
/ <snip> other fields
= collection_select(:school, :grade_ids, #all_grades, :id, :name, {:selected => #school.grade_ids, include_hidden: false}, {:multiple => true})
/ <snip> other fields + submit button
And the controller looks like this:
# app/controllers/schools_controller.rb
class SchoolsController < ApplicationController
before_action :set_school, only: [:show, :edit, :update]
def index
#schools = School.all
end
def show
end
def new
#school = School.new
#all_grades = Grade.all
#grades_schools = #school.grades_schools.build
end
def edit
#all_grades = Grade.all
#grades_schools = #school.grades_schools.build
end
def create
#school = School.new(school_params)
respond_to do |format|
if #school.save
format.html { redirect_to #school, notice: 'School was successfully created.' }
format.json { render :show, status: :created, location: #school }
else
format.html { render :new }
format.json { render json: #school.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #school.update(school_params)
format.html { redirect_to #school, notice: 'School was successfully updated.' }
format.json { render :show, status: :ok, location: #school }
else
format.html { render :edit }
format.json { render json: #school.errors, status: :unprocessable_entity }
end
end
end
private
def set_school
#school = School.find(params[:id])
end
def school_params
params.require(:school).permit(:name, :date, :school_id, grades_attributes: [:id])
end
end
I have a feeling that the crux of my problem has to do with a mismatch between the params generated by collection_select and the strong parameters. One or both of these is probably incorrect, but I can't for the life of me find example code online that shows me what I'm doing wrong.
After trying a load of failed variations, I'm at my wits end! Thanks in advance for your help!
Crap. I could have sworn I tried this before, but it must have been when using fields_for in the form instead of collection_select. The solution:
def school_params
params.require(:school).permit(:name, :date, :school_id, grades_attributes: [:id])
end
becomes
def school_params
params.require(:school).permit(:name, :date, :school_id, grade_ids: [])
end
I'm still curious how it would work when using fields_for #grades_schools, but will have to save that investigation for another day....

Polymorphic Associations not saving values

My models:
class LineItem < ActiveRecord::Base
attr_accessible :itemable
belongs_to :itemable, polymorphic: true
belongs_to :lead
belongs_to :cart
end
class House < ActiveRecord::Base
has_many :line_items, :as => :itemable
end
class Appartment < ActiveRecord::Base
has_many :line_items, :as => :itemable
end
line_item_controller:
def create
#line_item = #cart.line_items.build item: #object
respond_to do |format|
if #line_item.save
format.html { redirect_to #line_item.cart,
notice: 'Vakantiehuis toegevoegd in lijst.' }
format.json { render action: 'show',
status: :created, location: #line_item }
else
format.html { render action: 'new' }
format.json { render json: #line_item.errors,
status: :unprocessable_entity }
end
end
end
private
def create_object
id = params[:house_id] || params[:appartment_id]
model = "House" if params[:house_id]
model = "Apartment" if params[:apartment_id]
model = model.constantize
#object = model.find(id)
end
When a new item list is created the values in de table line_items (itemable_id, itemable_type) are not saved. What am i doing wrong here? thanks..remco
try replace:
#cart.line_items.build item: #object
to:
#cart.line_items.build itemable: #object

Rails 4 - has_many through controller actions

I'm trying to set a has_many trough relationship and I'm new to this
#models/partner.rb
class Partner < ActiveRecord::Base
has_many :cards_partners
has_many :cards, through: :cards_partners
#models/card.rb
class Card < ActiveRecord::Base
has_many :cards_partners
has_many :partners, through: :cards_partners
#models/cards_partner.rb
class CardsPartner < ActiveRecord::Base
belongs_to :card
belongs_to :partner
And I specified the controllers
#controllers/cards_controller.rb
before_action :set_card, only: [:show, :edit, :update, :destroy]
def show
#user = #card.user
#partners = #card.partners.order(lastname: :desc)
#partner = #card.partners.new #because I have a modal to create new Partner too
#address is in a polymorphic table. I have to refactor the if-else
if #card.address.street.blank? && #card.address.city.blank?
#address = #user.address
else
#address = #card.address
end
end
def create
#card = current_user.cards.new(card_params)
respond_to do |format|
if #card.save
format.html { redirect_to #card, notice: 'Card was successfully created.' }
format.json { render :show, status: :created, location: #card }
else
format.html { render :new }
format.json { render json: #card.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #card.update(card_params)
format.html { redirect_to #card, notice: 'Card was successfully updated.' }
format.json { render :show, status: :ok, location: #card }
else
format.html { render :edit }
format.json { render json: #card.errors, status: :unprocessable_entity }
end
end
end
private
def set_card
#card = Card.find(params[:id])
end
def card_params
params.require(:card).permit(partner_ids: [])
end
#controllers/partners_controller.rb
def partner_params
params.require(:partner).permit(card_ids: [])
end
My join table cards_partners is properly set.
To sum up the logic, a User can create Cards and add Partners to this Card.
I set a has_many through between Cards and Partners because I want User to be able to assign already Created Partners to multiple Cards.
I have inside my cards#show view a partial that shows all the partners, and a link to add a new one to this card.
I define my #partners inside my card#show action with (not sure about this since no join specified):
#partners = #card.partners.order(lastname: :desc)
I can't figure how to specify the card and then creating a new partner from card#show view using the link new_partner_path.
Any help would be really appreciated.
Thank you a lot

Resources