Daniel Peñaloza
Daniel Peñaloza

Reputation: 98

Rails New Action with Different Models

I've got an issue in Rails with the create action - I have this information in my controller:

ComputerController 
def create
  @computer = Computer.new(computer_params)
  redirect_to computers_path
end

private  
 def computer_params
 require.params(:computer).permit(:computer_name,
 :cpu_tag,:serial,:location,:brand,:model,:ram,:cpu,:os,:warranty,:comments)  
end

Then in my model I have some validations:

class Computer < ActiveRecord::Base
 validates :computer_name,  uniqueness: true, presence: true,
 length:{maximum: 12} 
 validates :cpu_tag, length: {maximum: 4}, uniqueness: true, 
 :numericality =>   {:only_integer => true}
 validates :serial, presence: true
 validates :location, presence: true
 validates :brand, presence: true
 validates :model, presence: true
 validates :ram, presence: true
 validates :cpu, presence: true
 validates :os, presence: true
 validates :warranty, presence: true
 validates :comments, presence: true
end

The view new.html.erb is:

<div class="row text-center">
 <h2 class = "mimsinfoblackindex">Add A Computer To The Inventory </h2><hr/>

<div class="col-md-3 description_pc text-left">
   <%= form_for @computer do |f|%>  

    <h4 class = "mimsformgreen">
      <%= f.label :computer_name,'Computer Name:'%>
      <%= f.text_field :computer_name%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :cpu_tag, 'Computer Tag:'%>
      <%= f.text_field :cpu_tag%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :serial, 'Serial:'%>
      <%= f.text_field :serial%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :location, 'Location:'%> 
      <%= f.text_field :location%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :brand, 'Brand:'%>
      <%= f.text_field :brand%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :model, 'Model:'%>
      <%= f.text_field :model%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :ram, 'Ram:'%> 
      <%= f.text_field :ram%>
    </h4>

    <h4 class = "mimsformblack">  
      <%= f.label :cpu, 'Processor:'%>
      <%= f.text_field :cpu %>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :os, 'Operating System:'%> 
      <%= f.text_field :os%>
    </h4>

    <h4 class = "mimsformblack">
      <%= f.label :warranty, 'Warranty:'%>
      <%= f.text_field :warranty%>
    </h4>

     <h4 class = "mimsformblack">
      <%= f.label :comments, 'Comments:'%>
      <%= f.text_field :comments%>
    </h4>

        <%= f.submit 'Add The Computer'%>
  <% end %>

I already did TDD for my models and I don't have any problems, but when I submit the computer form, I get an error message in the screen that says:

 wrong number of arguments (0 for 1)
 private  
 def computer_params
  require.params(:computer).permit(:computer_name,:cpu_tag,
  :serial,:location,:brand,:model,:ram,:cpu,:os,:warranty,:comments)  
 end

Upvotes: 1

Views: 87

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

To add to the answer, there are some fixes you could make with your code:


1 Validations

When defining the same presence validation, you can pass multiple arguments (attributes) to the method:

#app/models/computer.rb
class Computer < ActiveRecord::Base
   validates :serial, :location, :brand, :model, :ram, :cpu, :os, :warranty, :comments, presence: true
end

2 Params

Rails' strong params functionality is pretty specific in stating you need to "require" a top-level param, and then "permit" its child params:

def computer_params
  params.require(:computer).permit(:computer_name,:cpu_tag, :serial,:location,:brand,:model,:ram,:cpu,:os,:warranty,:comments)  
end

3 Loops

In programming, the most efficient code wins.

This means you should not be replicating a bunch of code time & time again (using the attributes method):

#app/views/computers/new.html.erb
<%= form_for @computer do |f| %>

    <% @computer.attributes.each do |attr| %>
       <% xtra = "green" if attr == :computer_name %>
       <%= content_tag :h4, class: "misform #{xtra}" do %>
          <%= f.label attr.to_sym, attr.titleize + ":" %>
          <%= f.text_field attr.to_sym %>
       <% end %>
    <% end %>

    <%= f.submit 'Add The Computer'%>
<% end %>

See how much cleaner that is?


4 HTML Classes

You've used these two class names:

mimsformblack mimsformgreen

Looking at my #3 recommendation, can you see how this is very inefficient? It's violates a principle called DRY (Don't Repeat Yourself), in which you're meant to use as little code with as much functionality as possible.

You can apply multiple CSS classes to each element, which means you'll be able to do the following:

<div class="mimsform">This will be black</div> 
<div class="mimsform green">This will be green</div>

5 Create

When you create in Rails, you have to save the object to the model:

def create
  @computer = Computer.new computer_params
  redirect_to computers_path if @computer.save
end

Many newbie developers don't save their new object, preventing them from actually saving the data to the db.

Upvotes: 0

Zoran
Zoran

Reputation: 4226

Try rewriting your computer_params to:

private  

def computer_params
  params.require(:computer).permit(:computer_name, :cpu_tag, :serial, :location, :brand, :model, :ram, :cpu, :os, :warranty, :comments)  
end

It appears that params and require are reversed in your original code.

Hope it helps!

Upvotes: 3

Related Questions