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
Related
I'm trying to associate a current_user.id to a #patient.medic_id via a controller.
I try this in my controller:
def create
# #patient = Patient.new(patient_params)
#patient = current_user.patients.build(patient_params[:medic_id => current_user.id])
respond_to do |format|
if #patient.save
format.html { redirect_to #patient, notice: 'Patient was successfully created.' }
format.json { render :show, status: :created, location: #patient }
else
format.html { render :new }
format.json { render json: #patient.errors, status: :unprocessable_entity }
end
end
end
This will automatically fill medic_id in the view with the current_user.id, but when I submit the form active record doesn't save the others parameters for patient like name, last_name, age, blood_type, etc.
This is my model /medic.rb (devise - user)
class Medic < ActiveRecord::Base
has_many :patients
end
This is my model /patient.rb
class Patient < ActiveRecord::Base
belongs_to :medic
end
And I need a way to call all registers (patients) from a medic-user, to a show view; what it is the best way to do this?
Thanks for the help.
To solve the problem when you create a patient:
medic_id = {medic_id: current_user.id}
current_user.patients.build(patient_params.merge(medic_id))
Assuming you have #medic in your show action, to get all patients of a medic-user:
#patients = #medic.patients
And in your show view, you can access #patients as an array.
I'm trying to create a form that allow called submits. I've got all the appropriate MVC created. I've then created a model called questions that works and am using active admin to allow admin users to add new questions to the form as they see fit. When I test submitting the form I get this error
undefined method `each' for nil:NilClass
#submit = Submit.new(submit_params)
#submit.save
params[:submit][:question_ids].each do |question_id|
#question = Question.find(question_id)
#submit.questions << #question
end
Here's my submits controller:
class SubmitsController < ApplicationController
before_action :set_submit, only: [:show, :edit, :update, :destroy]
def index
#submits = Submit.all
end
def show
end
def new
#submit = Submit.new
#questions = Question.all
end
def edit
end
def create
#submit = Submit.new(submit_params)
#submit.save
params[:submit][:question_ids].each do |question_id|
#question = Question.find(question_id)
#submit.questions << #question
end
respond_to do |format|
if #submit.save
format.html { redirect_to #submit, notice: 'Application was successfully created.' }
format.json { render :show, status: :created, location: #submit }
else
format.html { render :new }
format.json { render json: #submit.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #submit.update(submit_params)
format.html { redirect_to #submit, notice: 'Application was successfully updated.' }
format.json { render :show, status: :ok, location: #submit }
else
format.html { render :edit }
format.json { render json: #submit.errors, status: :unprocessable_entity }
end
end
end
def destroy
#submit.destroy
respond_to do |format|
format.html { redirect_to submits_url, notice: 'Submit was successfully destroyed.' }
format.json { head :no_content }
end
end
Here's my Submit and Question model:
Submit:
class Submit < ActiveRecord::Base
has_and_belongs_to_many :questions
belongs_to :user
end
Question:
class Question < ActiveRecord::Base
has_and_belongs_to_many :submits
end
I'm sure it's some kind of syntax error in my controller but I don't know what. Still pretty new to using join tables. Any help/explanation would be very appreciated.
Thanks!
You don't need this
params[:submit][:question_ids].each do |question_id|
#question = Question.find(question_id)
#submit.questions << #question
end
I don't see your submit params but if you add question ids to the permitted parameters then rails will build the entry in the join table on it's own.
def submit_params
params.require(:submit).permit(:user_id, question_ids: [])
end
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
I am having a ridiculously hard time trying to figure out how to do this. I have been at it literally all day.
I have an Account class and a Transaction class.
Accounts are created with a balance and I want the Transaction amount, depending on its type, to either add or subtract from the balance.
I want to be able to update the Account balance every time a transaction is created. This is for a personal finance application. As of now when I create a new transaction, nothing happens to the account balance.
accounts_controller.rb
class AccountsController < ApplicationController
def index
#accounts = Account.all
end
def show
#account = Account.find(params[:id])
end
def new
#account = Account.new
end
def edit
#account = Account.find(params[:id])
end
def create
#account = Account.new(params[:account])
respond_to do |format|
if #account.save
format.html { redirect_to #account, notice: 'Account was successfully created.' }
format.json { render json: #account, status: :created, location: #account }
else
format.html { render action: "new" }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
def update
#account = Account.find(params[:id])
respond_to do |format|
if #account.update_attributes(params[:account])
format.html { redirect_to #account, notice: 'Account was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
# DELETE /accounts/1
# DELETE /accounts/1.json
def destroy
#account = Account.find(params[:id])
#account.destroy
respond_to do |format|
format.html { redirect_to accounts_url }
format.json { head :no_content }
end
end
def update_balance
#a = Account.find(params[:id])
#a.transactions.each do |t|
#update_balance = t.t_type + #a.balance
#a.update_attributes(:balance => #update_balance)
end
end
end
transactions_controller.rb
class TransactionsController < ApplicationController
def create
#account = Account.find(params[:account_id])
#transaction = #account.transactions.create(params[:transaction])
redirect_to account_path(#account)
end
end
transaction.rb
class Transaction < ActiveRecord::Base
belongs_to :account
attr_accessible :amount, :category, :t_type
end
account.rb
class Account < ActiveRecord::Base
attr_accessible :balance, :name
has_many :transactions
end
If anyone has any idea what I'm doing wrong or can point me in the direction of a good thorough explanation, that would be great. I am so lost at this point.
Try this.
class Account < ActiveRecord::Base
attr_accessible :balance, :name
has_many :transactions
def update_with_transaction(transaction)
return unless self.transactions.include? transaction
if transaction.t_type.eql? SOME_TYPE
self.balance += transaction.ammount
else
self.balance -= transaction.ammount
end
save
end
end
class TransactionsController < ApplicationController
def create
account = Account.find(params[:account_id])
#transaction = account.transactions.create(params[:transaction])
account.update_with_transaction(#transaction)
redirect_to account_path(account)
end
end
It doesn’t update because you haven’t told it to. Create an after_create callback to do so:
class Transaction < ActiveRecord::Base
# ...
after_create :update_account_balance
private
def update_account_balance
account.balance += amount
account.save
end
end
Adjust as needed. Note that this won’t handle updates to a transaction’s amount, which is left as an exercise for the reader.
I'm follow this tutorial http://railscasts.com/episodes/196-nested-model-form-part-1 for nested form.
I have 3 model the first user.rb:
class User
has_many :boards, dependent: :destroy
has_many :posts, dependent: :destroy, :autosave => true
accepts_nested_attributes_for :boards
accepts_nested_attributes_for :posts
end
The second model its board.rb
class Board
has_many :posts, :dependent => :destroy , :autosave => true
accepts_nested_attributes_for :posts
belongs_to :user
end
The third model its post.rb
class Post
belongs_to :user
belongs_to :board
end
I want create a new post since a board form and I have in boards_controller.rb
def new
#board = Board.new
#board.posts.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #board }
end
end
def create
#board = current_user.boards.new(params[:board])
#board.user = current_user
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
With this 2 methods I get every attributes of posts in my views. in my console if I put after create a board Post.first I get:
1.9.2-p290 :007 > Post.first
=> #<Post _id: 4f0b0b211d41c80d08002afe, _type: nil, created_at: 2012-01-09 15:43:29 UTC, user_id: nil, board_id: BSON::ObjectId('4f0b0b1b1d41c80d08002afd'), content: "hello post 2">
But If you take a look I get user_id: nil.
In normal model I get user id for example in create action of controller I put #post.user = current_user.id or #post.user = current_user
How Can I get the user_id in nested model post through from nested forms?
def create
#board = current_user.boards.new(params[:board])
##board.user = current_user - you don't need this line, since you create new board record using current_user object
# assign current_user id to the each post.user_id
#board.posts.each {|post| post.user_id = current_user}
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
You should be able to simply set the user_id property.
In your code you are assigning the current_user object to the association.
This should work:
def create
#board = current_user.boards.new(params[:board])
#board.user_id = current_user.id
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end