KrauseFx
KrauseFx

Reputation: 11751

Avoid nested resources and still create a proper reference

I'm new to Ruby On Rails and followed the RoR guide to create a blog: http://guides.rubyonrails.org/getting_started.html

According to different articles I should avoid having resources nested more than one level. (http://guides.rubyonrails.org/routing.html#nested-resources 2.7.1)

They reference to this article about best practices: http://weblog.jamisbuck.org/2007/2/5/nesting-resources

Without having nested resources in my project right now, how do I have to create the form properly to set the reference properly?

My routes.rb file

Monitoring::Application.routes.draw do
resources :companies
resources :jobs
root :to => 'companies#index'

company.rb

class Company < ActiveRecord::Base
  attr_accessible :name
  has_many :jobs, :dependent => :destroy
end

job.rb

class Job < ActiveRecord::Base
  belongs_to :company
  attr_accessible :interval, :name
end

A job belongs to one company.

_form.html.erb inside the jobs view folder

<%= form_for @job, :html => { :class => 'form-horizontal' } do |f| %>
  <div class="control-group">
    <%= f.label :name, :class => 'control-label' %>
    <div class="controls">
      <%= f.text_field :name, :class => 'text_field' %>
    </div>
  </div>
  <div class="control-group">
    <%= f.label :interval, :class => 'control-label' %>
    <div class="controls">
      <%= f.number_field :interval, :class => 'number_field' %>
    </div>
  </div>

  <div class="form-actions">
    <%= f.submit nil, :class => 'btn btn-primary' %>
    <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
                jobs_path, :class => 'btn' %>
  </div>
<% end %>

To actually create the job with a reference to its company I tried the following code

  def new
    @company = Company.find(params[:company])
    @job = @company.jobs.build

    respond_to do |format|
      format.html # new.html.erb
    end
  end

Is there any open source example code that demonstrates creating new objects without nested objects?

Right now, the company parameter is not properly set when creating a new job, which means I can't fetch the company to create the job from there. How do I create a new job with the correct reference to its company?

Upvotes: 2

Views: 227

Answers (1)

Peter P.
Peter P.

Reputation: 3507

without doing nested routes you should just drop a hidden input in the form with the company id.

<%= f.hidden_field :company_id, value: @company.id %>

However, this is obviously easily hackable by the client. If permissions are a concern, then you should just set it server side:

@job = Job.new(company_id: @company.id)

and if you need to do mass assignment:

@job = Job.new(params[:job].merge(company_id: @company.id))
#or do it after the fact
@job = Job.new(params[:job])
@job.company_id = @company.id

As an aside, I see no inherent problem with nesting resources 2 or even 3 levels deep. Its really a case-by-case kind of thing. For me, the two major considerations when deciding levels of nesting, are 1) how will the urls be accessed 2) what does my object graph look like; will I always have the parent model(s) around when dealing with links and forms

Upvotes: 3

Related Questions