Reputation: 688
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
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