Question

I'm new to Rails and trying to understand how we build 'complex' Models (and their associations) using tools available to us in Rails. Quickly imagine the following example scenario: Users are a member of ONE racing Team. Users can create Cars and Schedules. These Cars have Drivers, Fuel levels, Engines and Wheels. These Wheels have Tires, Hubs and MilesDriven. You get the idea...

Given all the warnings about nesting only 1 level deep...I still struggle with how to be RESTful and Rails-y and present a UI that allows a user to build a Car with Tires.

I know we have a Session & Cookie at our disposal as well as Hidden fields. So user logs in...and is routed to their team page teams(current_user.team_id). Then they want to create a Car. this routes to new_team_car_path(current_user.team_id) where they can build a car... now I want to add a Wheel to this car... so does that route to new_team_car_wheel_path(current_user.team_id, car_id), etc, etc...? I think not... But, what is the Rail-y way?

Also, as everything built will be associated, ultimately, to a team (and user) is it best to 'carry' the team_id and/or user_id association all the way down to the Tire or is it reasonable to query the Team by following the associations up the hierarchy at runtime?

I'm sure this is basic stuff but newbness has me confused about how to best approach it...

Was it helpful?

Solution

There's no single answer to this question. You mentioned using session variables and hidden fields -- those are viable approaches, and the decision will have to be based on the specific requirements. The fact that you are struggling to find the best answer is a good sign, in that it shows you're willing to consider alternatives.

In this case you have a leg up because you don't need to pass in the user information or its associations in the URL, since your authorization code already makes it available in th controller. So I'd drop the user and team id from your params and access them from current_user:

# GET /cars/:car_id/wheels/new

def new
  @car = Car.find(params[:car_id])
  @wheel = @car.wheels.build
end

and

# POST /cars/:car_id/wheels

def create
  @user = current_user
  @team = @user.team
  @car = Car.find(params[:car_id]
  @wheel = @car.wheels.build(params[:car][:wheel])
  ...
end

The only problem is if you need to allow a user to access another user's Car. In that case a hidden form field (or a drop down menu) to select the user should work. Conversely, you may need an authorization check to prevent users from accessing each other's `Car'

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top