Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialAllen Lamphear
Courses Plus Student 6,660 PointsRails Nested Attributes?
So I am not sure if nested attributes is what I need to know/learn but i'll give my scenario.
I have a model that is called "Inventory" this has 3 references "tablet_id, vehicle_id, employee_id"
I have 3 models, "Tablet", "Vehicle", "Employee" and in each I have a status column amongst other columns. ie. alias, serial, etc.
Now, in my "Inventory" form, I have 3 dropdowns and each generate from the models above.
<div class="form-group">
<%= f.label :tablet_id, "Tablet #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "tablet_id", Tablet.where("status == '1'").all.collect{ |t| [t.alias, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<div class="form-group">
<%= f.label :employee_id, "Employee #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "employee_id", Employee.where("status == '1'").all.collect{ |t| [t.employeeNum, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<div class="form-group">
<%= f.label :vehicle_id, "Vehicle #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "vehicle_id", Vehicle.where("status == '1'").all.collect{ |t| [t.vehNum, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
Now, when I submit this form the selected fields will go into the "Inventory" tables and on the Index page I can see a table that shows what I submitted.
BUT!
I want to also change the status of each selected field in their own model.
Meaning, if I select Tablet = "Tablet01", Employee = "Employee23", Vehicle = "Vehicle23" in the dropdowns I want to change their "status" to say "2".
How would I go about doing that?
2 Answers
Kevin Korte
28,149 PointsIt would be inside your inventory model, since the form submits to the inventory model it sounds like, that's the model that has to know and expect that it will be getting data for other models.
So inventory will look like
class Inventory < ActiveRecord::Base
belongs_to :tablet
belongs_to :employee
belongs_to :vehicle
validates :tablet_id, :employee_id, :vehicle_id, presence: true
validates :tablet_id, :employee_id, :vehicle_id, uniqueness: { message: " is already checked out." }
accepts_nested_attributes_for :tablet
accepts_nested_attributes_for :employee
accepts_nested_attributes_for :vehicle
end
Now when your form submits to inventory, your params will be something like
params = { inventory: { table_id: 'id', employee_id: 'id', vehicle_id: 'id',
tablet_attributes: [{ //table attributes would be here }],
employee_attributes: [{ //employee attributes would be here }],
vehicle_attributes: [{ //vehicle attributes would be here }]
}}
And than you'll have 3 new methods available to the model tablet_attributes(attributes)
, employee_attributes(attributes)
, and vehicle_attributes(attributes)
.
Just play with it, it takes a little bit to get the hang of if, but the error messages I find are really helpful, and you should be fine.
Kevin Korte
28,149 PointsYes, you need nested attributes. Anytime you want to modify one model from another model, you'll need the :accepts_nested_attributes_for
and than Rails will bundle the form submit up into a hash, which you can use to update the models.
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Allen Lamphear
Courses Plus Student 6,660 PointsWould I place this inside my Inventory model or each one of my other models (Tablet, Employee, Vehicle)??
Inventory Model
class Inventory < ActiveRecord::Base
belongs_to :tablet
belongs_to :employee
belongs_to :vehicle
validates :tablet_id, :employee_id, :vehicle_id, presence: true
validates :tablet_id, :employee_id, :vehicle_id, uniqueness: { message: " is already checked out." }
end
Tablet Model
class Tablet < ActiveRecord::Base
has_many :notes
has_one :inventory
validates :alias, :email, presence: true
validates :alias, uniqueness: { message: " is already taken." }
end
Allen Lamphear
Courses Plus Student 6,660 PointsCan't seem to get this. I must be missing or not understanding.
Inventory Form
<%= form_for(@inventory, html: {class: "form-horizontal"}) do |f| %>
<% if @inventory.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@inventory.errors.count, "error") %> prohibited this inventory from being saved:</h2>
<ul>
<% @inventory.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :tablet_id, "Tablet #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "tablet_id", Tablet.where("status == '1'").all.collect{ |t| [t.alias, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<%= f.fields_for :tablets do |t| %>
<%= t.hidden_field :status, value: 2 %>
<% end %>
<div class="form-group">
<%= f.label :employee_id, "Employee #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "employee_id", Employee.where("status == '1'").all.collect{ |t| [t.employNum, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<%= f.fields_for :employees do |t| %>
<%= t.hidden_field :status, value: 2 %>
<% end %>
<div class="form-group">
<%= f.label :vehicle_id, "Vehicle #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "vehicle_id", Vehicle.where("status == '1'").all.collect{ |t| [t.vehNum, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<%= f.fields_for :vehicles do |t| %>
<%= t.hidden_field :status, value: 2 %>
<% end %>
<div class="form-group">
<div class="col-md-2 col-md-offset-2">
<%= f.submit class: "btn btn-sm btn-success" %>
</div>
</div>
<% end %>
My Inventory params
def inventory_params
params.require(:inventory).permit(:tablet_id, :chauffeur_id, :vehicle_id, tablets_attributes: [:status], chauffeurs_attributes: [:status], vehicles_attributes: [:status])
end
Allen Lamphear
Courses Plus Student 6,660 PointsAllen Lamphear
Courses Plus Student 6,660 PointsThanks! This does help. I do have another question (sorry).
For the attributes, I want to specify a predefined value. So for each models (tablet,employee,vehicle) they have a status and I want to say, take that submitted "tablet_id" and change the "status" from say "1" to "2'.
I dont see how the attributes would know which id would be correct, or does it?
Again, thanks so much for the help!