Updating attributes through a different object - ruby-on-rails

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.

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

Ruby on Rails ActiveResource not saving resource model properly

ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux],
Rails 4.2.5
I have two projects. from 1st project i am getting data into second project through api.
User model in 1st project:
class User < ActiveRecord::Base
has_many :cars
end
Car model in 1st project:
class Car < ActiveRecord::Base
belongs_to :user
end
Car model(remote) in 2nd project:
class Car < ActiveResource::Base
self.site = 'https://myeasyb-vssram.c9users.io'
self.format = :json
end
Gpstablecontroller(2nd project):
class GpstablesController < ApplicationController
before_action :set_gpstable, only: [:show, :edit, :update, :destroy]
# GET /gpstables
# GET /gpstables.json
def index
#gpstables = Gpstable.all
end
# GET /gpstables/1
# GET /gpstables/1.json
def show
end
# GET /gpstables/new
def new
#gpstable = Gpstable.new
#gpstables = Gpstable.all
end
# GET /gpstables/1/edit
def edit
#gpstables = Gpstable.all
end
# POST /gpstables
# POST /gpstables.json
def create
#cars = Car.all
#gpstable = Gpstable.new(gpstable_params)
#cars.each do |car|
if #gpstable.car_id == car.id
#car = car
end
end
#car.update_attribute(:gpss, #gpstable.device_id)
respond_to do |format|
if #gpstable.save
format.html { redirect_to gpstables_url, notice: 'Gpstable was successfully created.' }
format.json { render :show, status: :created, location: #gpstable }
else
format.html { render :new }
format.json { render json: #gpstable.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /gpstables/1
# PATCH/PUT /gpstables/1.json
def update
respond_to do |format|
if #gpstable.update(gpstable_params)
Car.all.each do |car|
if #gpstable.car_id == car.id.to_json
#car = car
end
if #gpstable.device_id == car.gpss
car.gpss = 0
car.save!
end
end
#car.gpss = #gpstable.device_id
#car.save!
format.html { redirect_to #gpstable, notice: 'Gpstable was successfully updated.' }
format.json { render :show, status: :ok, location: #gpstable }
else
format.html { render :edit }
format.json { render json: #gpstable.errors, status: :unprocessable_entity }
end
end
end
# DELETE /gpstables/1
# DELETE /gpstables/1.json
def destroy
#cars.each do |car|
if #gpstable.device_id == car.gpss
car.gpss = 0
car.user_id = #gpstable.user_id
car.save
end
end
#gpstable.destroy
respond_to do |format|
format.html { redirect_to gpstables_url, notice: 'Gpstable was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_gpstable
#gpstable = Gpstable.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def gpstable_params
params.require(:gpstable).permit(:device_id, :car_id, :user_id)
end
end
when creating gpstable record i want to update Gpss attribute of car model(remote, calling through api).
it is updating gpss attribute.But it is changing all foriegnkeys including user_id attribute of car model to null.
using devise for users in 1st project.
The problem is i am giving user_id to current user_id in car_params. so i was unable to edit this through resource model. so i changed this to create action.
In my first app i have car controller:
def car_params
params.require(:car).permit(:name, :model, :colour, :ac, :gpss, :wifi, :luggage, :cfare, :card, :crfare, :no, :nos, :user_id, {carpicss: []} ).**merge(user: :current_user)**
end
i removed .merge(user: :current_user) from above code.
and added this in create action
def create
#car = Car.new(car_params)
#car.card=" #{#car.name} : #{#car.no}"
#car.user_id=current_user.id #added here to save current user_id
respond_to do |format|
if #car.save
format.html { redirect_to cars_path, notice: 'Car was successfully created.' }
format.json { render :show, status: :created, location: cars_path }
else
format.html { render :new }
format.json { render json: #car.errors, status: :unprocessable_entity }
end
#car.reload
end
end

User information isn't storing to proper user

In my Users controller, I have the following method
def show
#user = User.find(params[:id])
if current_user.id == params[:id] # im not sure if this is right
#answer = Answer.new
else
#answer = Answer.find(params[:id])
end
end
where
class User
has_many :answers
end
and
class Answer
belongs_to :user
end
When I open another user (A) by the signed in user (B), I want A's quiz questions (which also belongs_to User through a has_one association) to have the answers by B.
As is, if B answers A's questions, and then I log in with A, they will have the same answers of the original B to A.
If it helps, in my Answers controller I have the following methods.
def create
#answer = current_user.answers.build(answer_params)
if #answer.save
flash[:success] = "Updated"
redirect_to '/'
else
render 'new'
end
end
def update
respond_to do |format|
#answer = Answer.find(params[:id])
if #answer.update(answer_params)
format.html { redirect_to '/', notice: 'Answers were successfully updated.' }
format.json { render :show, status: :ok, location: #answer }
else
format.html { render :edit }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
def answer_params
params.require(:answer).permit(:r1, :r2, :r3, :r4, :r5)
end
and I also have the migration
class AddUserIdToAnswers < ActiveRecord::Migration
def change
add_column :answers, :user_id, :integer
end
end
EDIT:
Quizzes Controller (belongs_to User, User has_one :quiz)
class QuizzesController < ApplicationController
def edit
#quiz = Quiz.find(params:[id])
end
def create
#quiz = current_user.build_quiz(quiz_params)
if #quiz.save
flash[:success] = "Updated"
redirect_to '/'
else
render 'new'
end
end
def update
respond_to do |format|
#quiz = Quiz.find(params[:id])
if #quiz.update(quiz_params)
format.html { redirect_to '/', notice: 'Quiz was successfully updated.' }
format.json { render :show, status: :ok, location: #quiz }
else
format.html { render :edit }
format.json { render json: #quiz.errors, status: :unprocessable_entity }
end
end
end
def quiz_params
params.require(:quiz).permit(:q1, :q2, :q3, :q4, :q5)
end
def show
#quizzes = Quiz.all
end
end
and my Routes.rb
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'welcome#landing'
resources :users, :quizzes, :answers
end
I am not gone through every aspect. But one issue in your show action.
if current_user.id == params[:id] # im not sure if this is right
With this you will not get new form. Because params[:id] type is string and current_user.id type is integer. So it will always return false.
Try change like :
if current_user.id == params[:id].to_i
Or compare user object directly
if current_user == #user
Try my suggestion helpisgood
def show
#user = User.find(params[:id])
if current_user == #user
#answer = Answer.new
else
#answer = Answer.find_by(user_id: #user.id)
end
end

Merit doesn't add points to user after create action

I've used this instructions for simply add score when a user creates a "solucion" (which is a kind of "answer" to a micropost). I have added the has_merit line to user.rb (user model).
I want to display the user points earned for that action at the show view.
show.html.erb (for solucion):
<h2><span class="red"><%= current_user.points %></span><br>Points</br></h2>
It displays 0 points...
point_rules.rb:
module Merit
class PointRules
include Merit::PointRulesMethods
def initialize
score 5, on: 'solucions#create'
end
end
end
When I create a solucion with the current_user (already saving the user_id index and identifier to solucion), This is what my rails server output shows...
Direct link to github gist:
https://gist.github.com/roadev/7b34fd67ab93c979fa48
Embed:
<script src="https://gist.github.com/roadev/7b34fd67ab93c979fa48.js"></script>
EDIT:
solucions_micropost.rb
class SolucionsController < ApplicationController
before_action :set_solucion, only: [:show, :edit, :update, :destroy]
def index
#solucions = Solucion.all
end
def show
end
def new
#solucion = current_user.solucions.build
end
def edit
end
def create
#solucion = current_user.solucions.build(solucion_params)
respond_to do |format|
if #solucion.save
format.html { redirect_to #solucion, notice: 'Solucion was successfully created.' }
format.json { render action: 'show', status: :created, location: #solucion }
else
format.html { render action: 'new' }
format.json { render json: #solucion.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #solucion.update(solucion_params)
format.html { redirect_to #solucion, notice: 'Solucion was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #solucion.errors, status: :unprocessable_entity }
end
end
end
def destroy
#solucion.destroy
respond_to do |format|
format.html { redirect_to solucions_url }
format.json { head :no_content }
end
end
private
def set_solucion
#solucion = Solucion.find(params[:id])
end
def current_micropost
#solucion = microposts.find_by(id: params[:id])
end
def solucion_params
params.require(:solucion).permit(:solucion, :image, :micropost_id)
end
end
user.rb:
class User < ActiveRecord::Base
has_many :dreams
has_many :microposts
has_many :solucions
has_merit
end
I had a problem with a migration when I installed the merit gem.

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