Reputation: 11
I'm pretty new to Rails and I couldn't find a solution to this problem (I hope I haven't missed something obvious).
how can I make my application accept blank fields, but not saving the empty value to the db?
I mean, if I do
validates :name, presence: true
I will get an error message, that name can't be blank. But I just want it to ignore blank/nil with not saving it into db.
How would I do that? (I hope asked that question comprehensible, tell me if not)
Update:
ok, so here is my code:
Models:
class Voting < ApplicationRecord
has_many :options
accepts_nested_attributes_for :options
validates :content, presence: true
end
and
class Option < ApplicationRecord
belongs_to :voting
validates_associated :voting
validates :vote, presence: { message: "at least two Options required." }, if: :option_counter
def option_counter
voting.options.count < 2
end
end
OptionsController:
class OptionsController < ApplicationController
def index
@voting = Voting.find(params[:voting_id])
@options = @voting.options
end
def create
@voting = Voting.find(params[:voting_id])
@option = @voting.options
@option.create(option_params)
if @voting.valid?
flash[:notice] = "Voting created!"
redirect_to voting_options_path
else
render 'votings/show'
end
end
private
def option_params
...
end
end
Views: votings/show.html.erb
<strong>Your Voting:</strong>
<p><%= @voting.content %></p>
<% if @voting.errors.any? %>
<div>
<% @voting.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</div>
<% end %>
<ul>
<%= form_with(model: [ @voting, @voting.options.build ], local: true) do |form| %>
<p>
<%= form.label :vote %><br>
<% 3.times do %>
<input type="string" name="option[][vote]" /><br><br>
<% end %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
</ul>
I think, this should be the interesting stuff. I hope it helps to understand the situation.
Upvotes: 0
Views: 2162
Reputation: 3005
Validations occur when saving to the database. So it is possible to accept empty fields even with your validation. But you must provide a value before saving. If you are getting an error it’s because your application is trying to save the record. So your code is not doing what you say (accepting empty fields without saving). You are saving.
The question is. Which line of code raises the error? Check your logs.
Validations are explained here: http://guides.rubyonrails.org/v2.3.11/activerecord_validations_callbacks.html (or any other version)
Edit 1
If you want to prevent this record from saving, but don’t inform the user, you could define a method save_unless_empty
def save_unless_empty
if empty_fields? and new_record?
delete
else
save
end
end
You must define the empty_fields? method so that you check the fields you need.
Edit 2
Thanks for adding the code. I see you are creating many options in the OptionsController#Create. This method is supposed to create only one option. You should create or update many options in VotingsController#create (or #update), given that all options belong to a voting object.
Another issue: You are building a new option object in the form (@voting.options.build), but you are not using it (you should use fields_for :option, @voting.options.build do.... This could be inside the 3.times loop. Even better, this can be done in the controller, before showing the view
And another one. Your validation regarding at least 2 options should be in the Voting model.
Some refactoring (although a lot is still missing):
In the view
<%= form_with @voting do |form| %>
<%= form.label :vote %><br>
<% @options.each do |option| %>
<%= form.fields_for option do |form_opt| %>
<%= form_opt.input_field :vote %><br><br> #question: is vote really the name of the attribute in the option model? or should this be a check_box showing the option name?
<% end %>
<% end %>
<%= form.submit %>
<% end %>
Then you should put the saving logic in VotingsController:
class VotingsController < ApplicationController
def new
@voting = Voting.new
3.times do
@voting.options.build
end
@options = @voting.options
end
def edit
@voting = Voting.find_by(id: params[:id])
@options = @voting.options
end
def create
@voting = Voting.create_without_null_options(voting_params)
#etc
end
def edit
@voting = Voting.find_by(id: params[:id])
@voting.update_without_null_options(voting_params)
#etc
end
private
def voting_params
...
end
end
In the Voting Model
def self.create_without_null_options params
#Create the voting without its options
@voting = Voting.create(params.except[:options_attributes])
#create options but save only non empty options
params[:options_attributes].each do |option_att|
@option = @voting.options.build(option_att)
@option.save_unless_empty
end
end
def update_without_null_options params
#Save the voting without its options
update_attributes(params.except[:options_attributes])
#create options but save only non empty options
params[:options_attributes].each do |option_att|
@option = options.build(option_att)
@option.save_unless_empty
end
end
Upvotes: 1
Reputation: 568
There is no such thing as saving specific database fields. An entire record is stored/received.
If the name field is not required, remove the validates :name, presence: true
on the model.
If there's a default value that you want in your database instead of nil/"", you can set it in the migration; for example a single space
add_column :name, :string, :default => " "
If you need to preserve those records and modify that database column, you can use change_column
in a new migration
change_column :users, :name, :string, :default => " "
I used users as an example table name, because from your code above I could not understand which table the name column was on.
Upvotes: 0
Reputation: 528
What that validation is doing is checking that the :name field has a value (if it does not have a value it will show the error message).
If you wanted to allow a blank value then I'm pretty sure you would just need to remove that validation. If a blank value (ie a string of ' ') is being saved in your database then I would check the 'name' column (in the database) to see if null is allowed.
Upvotes: 0