Reputation: 27
Having trouble with the controller of my survey (Waterusage). It has 30+ variables collected from a form and those inputs need to be saved to the waterusage db and used to calculate a final score, also saved in the database.
class Waterusage < ApplicationRecord
belongs_to :user
end
class WaterusagesController < ApplicationController
def new
@waterusage = Waterusage.new
end
def create
@user = User.find(params[:user_id])
_showerTotal = :average_shower * :shower_flow_rate * :household_size
_bathTotal = :bath_rate * :bath_multiplier * 35
_bathroomSinkTotal = :bathroom_sink_usage * :bathroom_sink_flow_rate * :household_size
_toiletTotal = :mellow * :low_flow_toilet * :household_size
_kitchenTotal = :kitchen_sink_usage * :kitchen_sink_flow_rate
_dishwashingTotal = :dishwasher_rate * :dishwasher_multiplier * :dishwasher_method
_laundryTotal = :laundry_rate * :laundry_method * :laundry_multiplier
_homeUsage = _showerTotal + _bathTotal + _bathroomSinkTotal + _toiletTotal + _kitchenTotal + _dishwashingTotal + _laundryTotal + :greywater
_lawnTotal = :lawn_rate * :lawn_multiplier * :lawn_size * :xeriscaping
_swimmingTotal = (:swimming_pool / 365) + (:swimming_months * 1000 / 365
_carwashTotal = :carwash_rate * :carwash_multiplier * :carwash_method
_outsideUsage = _lawnTotal + _swimmingTotal + _carwashTotal
_drivingTotal = 0.735 * :miles
_powerTotal = :statewater * :percent_statewater / 100
_indirectTotal = :shopping + :paper_recycling + :plastic_recycling + :can_recycling + :textile_recycling + :diet + (200 * :pet_cost / 30)
:household_total = _homeUsage + _outsideUsage + _drivingTotal + _powerTotal + _indirectTotal
:individual_total = :household_total / :household_size
@waterusage = @user.waterusage.create(waterusage_params)
redirect_to user_path(@user)
end
def destroy
@user = User.find(params[:user_id])
@waterusage = @user.waterusage.find(params[:id])
@waterusage.destroy
redirect_to user_path(@user)
end
private
def waterusage_params
params.require(:waterusage).permit(:household_size, :average_shower,
:shower_flow_rate, :bath_rate, :bath_multiplier, :bathroom_sink_usage,
:bathroom_sink_flow_rate, :mellow, :low_flow_toilet, :kitchen_sink_usage,
:kitchen_sink_flow_rate, :dishwasher_rate, :dishwasher_multiplier,
:dishwasher_method, :laundry_rate, :laundry_multiplier, :laundry_method,
:greywater, :lawn_rate, :lawn_multiplier, :lawn_size, :xeriscaping,
:swimming_pool, :swimming_months, :carwash_rate, :carwash_multiplier,
:carwash_method, :miles, :statewater, :percent_statewater, :shopping,
:paper_recycling, :plastic_recycling, :can_recycling, :textile_recycling,
:diet, :pet_cost, :individual_total, :household_total)
end
end
Is there a better way I can be doing this? Currently there are errors on the lines that are working to sum subtotals. (ie. :household_total = _homeUsage + _outsideUsage + _drivingTotal + _powerTotal + _indirectTotal ) Also I'm not sure if I am properly connecting the user info to the survey schema
Upvotes: 0
Views: 41
Reputation: 37
First of all prefix every ':' inside of create with a 'params[' and suffix ']', then change every '_' with a '@'.
It would be like this:
_powerTotal = :statewater * :percent_statewater / 100
turns into
@powerTotal = params[:statewater].to_i * params[:percent_statewater].to_i /100
Like that,
:individual_total = :household_total / :household_size
turns into
@individual_total = params[:household_total].to_i / params[:household_size].to_i
Also you're doing nothing with your calculations, they are just floating around, as it is, you can't even invoke them from your view.
If you want it to save on your waterusage object that relates to an user the individual_total attributes it would be;
@waterusage = @user.waterusage.create(waterusage_params, individual_total: @individual_total).
Upvotes: 0
Reputation: 3409
You don't want to do that math in the controller. Skinny controllers, fat models. Aside from that, one reason it's failing is that the syntax is incorrect. A symbol (:hello_world) can't be assigned a value nor does it contain one. Less importantly, while it's not illegal to have an underscore prefixed local variable, that is not the convention in Ruby. Neither is camelcase. You want hello_world rather than helloWorld. Anyway...
Assumption: You have a requirement that the totals must be persisted. They cannot be calculated values.
You want to move those calculations to the model. And instead of assigning a ton of variables, use methods. That way you can easily unit test them.
What's missing here: Validations in the model that ensure that all expected attribute values are present. The controller should handle an invalid Waterusage instance on create, too. This code is untested and is just for illustrative purposes.
class Waterusage < ApplicationRecord
belongs_to user
before_validation :calculate_totals
def calculate_totals
self.household_total = get_household_total
self.individual_total = get_individual_total
end
def get_household_total
home_usage + outside_usage + driving_total + power_total + indirect_total
end
def get_individual_total
household_total / household_size
end
def home_usage
shower_total + bath_total + bathroom_sink_total + toilet_total + kitchen_total + dishwashing_total + laundry_total + greywater
end
def outside_usage
lawn_total + swimming_total + carwash_total
end
def driving_total
0.735 * miles
end
def power_total
statewater * percent_statewater / 100
end
def indirect_total
shopping + paper_recycling + plastic_recycling + can_recycling + textile_recycling + diet + (200 * pet_cost / 30)
end
def shower_total
average_shower * shower_flow_rate * household_size
end
def bath_total
bath_rate * bath_multiplier * 35
end
def bathroom_sink_total
bathroom_sink_usage * bathroom_sink_flow_rate * household_size
end
def toilet_total
mellow * low_flow_toilet * household_size
end
def kitchen_total
kitchen_sink_usage * kitchen_sink_flow_rate
end
def dishwashing_total
dishwasher_rate * dishwasher_multiplier * dishwasher_method
end
def laundry_total
laundry_rate * laundry_method * laundry_multiplier
end
def lawn_total
lawn_rate * lawn_multiplier * lawn_size * xeriscaping
end
def swimming_total
(swimming_pool / 365) + (swimming_months * 1000 / 365)
end
def carwash_total
carwash_rate * carwash_multiplier * carwash_method
end
end
class WaterusagesController < ApplicationController
...
def create
@user = User.find(params[:user_id])
@waterusage = @user.waterusage.create(waterusage_params)
redirect_to user_path(@user)
end
...
end
Upvotes: 1