BnMcG
BnMcG

Reputation: 688

Ruby on Rails: params[] Variable in Controller

I'm new to Ruby (and Rails), so apologies for the basic question.

As I understand it, the params[...] variable inside of my controller is supposed to hold data from the form I've just submitted on my web page? I'm trying to use the following code to update a model depending on whether or not a field is blank:

@s3_destination = S3Destination.find(params[:id])

if params[:credentials_secret].to_s.empty?

    update = @s3_destination.update_attributes({
         :name => params[:name],
         :bucket => params[:bucket],
         :region => params[:region],
         :credentials_id => params[:credentials_id]
    })

    if update
        redirect_to @s3_destination
    else
        render 'edit'
    end

else

    update = @s3_destination.update_attributes({
         :name => params[:name],
         :bucket => params[:bucket],
         :region => params[:region],
         :credentials_id => params[:credentials_id],
         :credentials_secret => params[:credentials_secret],
    })

    if update
        redirect_to @s3_destination
    else
        render 'edit'
    end

end

The controller action executes fine, but there is now no data in the model, so I'm assuming i'm doing something wrong when setting it in the update_attributes function.

Shouldn't params[:name] take the value from the form element with the name "name"? Or have I misunderstood its purpose?

Edit

To answer some questions:

I believe this is the relevant log entry, it all looks OK to me?

Started PATCH "/s3_destinations/1" for 127.0.0.1 at 2015-12-09 12:40:51 +0000
Processing by S3DestinationsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"a26uTf4+58v/O+pTqOYn0R7cjzGVWBnbFVdJ1OWwNnybEpUdYt2FNruOla/ikOnAFLpY3mn71Wow5oVee+R3Ng==", "s3_destination"=>{"name"=>"Cogative Bucket 1", "bucket"=>"cogative-backup-01", "region"=>"eu-west-1", "credentials_id"=>"AKIAIZG2HJ35NR3DQYGA", "credentials_secret"=>"12345"}, "commit"=>"Save S3 destination", "id"=>"1"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ?  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
  S3Destination Load (0.0ms)  SELECT  "s3_destinations".* FROM "s3_destinations" WHERE "s3_destinations"."id" = ? LIMIT 1  [["id", 1]]
   (0.1ms)  begin transaction
   (0.0ms)  commit transaction
Redirected to http://localhost:3000/s3_destinations/1
Completed 302 Found in 3ms (ActiveRecord: 0.2ms)

The form itself is generated like this:

<h2>Editing AWS S3 Destination</h2>

<%= form_for :s3_destination, url: s3_destination_path(@s3_destination), method: :patch do |f| %>

    <% if @s3_destination.errors.any? %>
        <div id="error_explanation">
          <h2>
            <%= pluralize(@s3_destination.errors.count, "error") %> prohibited this source from being saved:
          </h2>
          <ul>
            <% @s3_destination.errors.full_messages.each do |msg| %>
                <li><%= msg %></li>
            <% end %>
          </ul>
        </div>
    <%end %>

    <p>
      <%= f.label :name %><br>
      <%= f.text_field :name %>
    </p>

    <p>
      <%= f.label :bucket %><br>
      <%= f.text_field :bucket %>
    </p>

    <select name="s3_destination[region]">
      <option value="us-east-1">US Standard (N. Virginia)</option>
      <option value="us-west-2">US West (Oregon)</option>
      <option value="us-west-1">US West (N. California)</option>
      <option value="eu-west-1">EU (Ireland)</option>
      <option value="eu-central-1">EU (Frankfurt)</option>
      <option value="ap-southeast-1">Asia Pacific (Singapore)</option>
      <option value="ap-southeast-2">Asia Pacific (Sydney)</option>
      <option value="ap-northeast-1">Asia Pacific (Tokyo)</option>
      <option value="sa-east-1">South America (Sao Paulo)</option>
    </select>

    <p>
      <%= f.label :credentials_id %><br>
      <%= f.text_field :credentials_id %>
    </p>

    <p>
      <%= f.label :credentials_secret %><br>
      <%= f.password_field :credentials_secret %>
    </p>

    <p>
      <%= f.submit %>
    </p>

<% end %>

Upvotes: 0

Views: 2361

Answers (1)

Kristj&#225;n
Kristj&#225;n

Reputation: 18803

You're referencing params[:name], but the parameters are all bundled up together under params[:s3_destination], so you need to reference params[:s3_destination][:name], etc.

The nice thing about this is you don't need to call out each attribute you want to update. In simple cases, you can just

@s3_destination.update_attributes(params[:s3_destination])

For safety (eg, so I can't edit the form to submit attributes you don't want me editing), you should use strong parameters:

s3_params = params.require(:s3_destination)
  .permit(:name, :bucket, :region, :credentials_id, :credentials_secret)
@s3_destination.update_attributes(s3_params)

And then for your credentials_secret logic, you can just delete the blank value from this hash:

s3_params = params.require(:s3_destination)
  .permit(:name, :bucket, :region, :credentials_id, :credentials_secret)
s3_params.delete(:credentials_secret) if s3_params[:credentials_secret].blank?
@s3_destination.update_attributes(s3_params)

blank? will catch both nil and "" the way you're currently doing with .to_s.empty?.

Upvotes: 1

Related Questions