Rails用水量调查控制器问题:数据存储与得分计算
Hey, I see you're working on a Rails controller for your water usage survey and running into issues with handling form data and calculating the final score. Let's walk through how to get this sorted.
Right off the bat, I notice you're trying to do calculations with symbols like :average_shower—that won't work because symbols are just parameter names, not the actual numeric values submitted via the form. We need to pull the real values from the form params, convert them to numbers, then run your calculations. Also, with 30+ variables, we should use Rails' strong parameters to keep things secure and organized.
1. Set Up Strong Parameters
First, define a strong params method in your controller to whitelist all the survey variables. This prevents unwanted data from being saved to your database:
class WaterusagesController < ApplicationController def new @waterusage = Waterusage.new end def create @user = User.find(params[:user_id]) @waterusage = @user.waterusages.build(waterusage_params) # Calculation logic will go here next end private def waterusage_params params.require(:waterusage).permit( :average_shower, :shower_flow_rate, :household_size, # Add all 30+ of your survey variables here, e.g.: # :toilet_flush_volume, :daily_toilet_uses, :laundry_frequency, # ... rest of your variables ) end end
2. Calculate the Final Score
Now, let's pull the numeric values from your @waterusage object and run your calculations. We'll also handle potential empty values by converting them to numbers (empty strings become 0 with to_f/to_i):
def create @user = User.find(params[:user_id]) @waterusage = @user.waterusages.build(waterusage_params) # Calculate individual components (adjust these formulas to match your needs) shower_total = @waterusage.average_shower.to_f * @waterusage.shower_flow_rate.to_f * @waterusage.household_size.to_i toilet_total = @waterusage.toilet_flush_volume.to_f * @waterusage.daily_toilet_uses.to_i * @waterusage.household_size.to_i laundry_total = @waterusage.laundry_load_size.to_f * @waterusage.laundry_frequency.to_i * @waterusage.washer_efficiency.to_f # Sum components to get final score (adjust this logic to fit your scoring system) @waterusage.final_score = shower_total + toilet_total + laundry_total # Save the record and handle success/error if @waterusage.save redirect_to @user, notice: "Water usage survey submitted successfully!" else render :new end end
3. Optional (But Recommended): Move Calculations to the Model
If your scoring logic is complex or might need to be reused later, it's better to move it to the Waterusage model. This keeps your controller clean and follows Rails' separation of concerns:
# app/models/waterusage.rb class Waterusage < ApplicationRecord belongs_to :user # Auto-calculate score before saving the record before_save :calculate_final_score private def calculate_final_score # Same calculation logic as before, but using the model's own attributes shower_total = average_shower.to_f * shower_flow_rate.to_f * household_size.to_i toilet_total = toilet_flush_volume.to_f * daily_toilet_uses.to_i * household_size.to_i laundry_total = laundry_load_size.to_f * laundry_frequency.to_i * washer_efficiency.to_f self.final_score = shower_total + toilet_total + laundry_total end end
With this change, your controller's create method simplifies to:
def create @user = User.find(params[:user_id]) @waterusage = @user.waterusages.build(waterusage_params) if @waterusage.save redirect_to @user, notice: "Water usage survey submitted successfully!" else render :new end end
- Database Column: Make sure your
waterusagestable has afinal_scorecolumn (use adecimalorfloattype). If not, generate a migration:rails generate migration AddFinalScoreToWaterusages final_score:decimal rails db:migrate - Validations: Add model validations to ensure required fields are filled out and are numeric:
# In waterusage.rb validates :average_shower, :shower_flow_rate, :household_size, presence: true, numericality: true - Empty Values: Using
to_fandto_iensures empty form fields don't break your calculations (they'll be treated as 0).
内容的提问来源于stack exchange,提问作者ezweizig

