Reputation: 53048
I am having trouble in implementing checkbox
logic for a model. There is a field named skills
in model Resume
which accepts multiple values through checkboxes
.
Resume
model schema is as below:
create_table :resumes do |t|
t.string :name, null: false
t.text :bio
t.string :skills
t.timestamps
end
In the view, specific to checkbox here is my code:
<% skills = ["Ruby", "Perl", "Java", "C", "C++"] %>
<div class="form-group">
<% skills.each do |skill| %>
<%= check_box_tag "resume[skills][]", skill %> <%= skill %>
<% end %>
</div>
In controller:
def resume_params
params[:resume][:skills] = params[:resume][:skills].join(",")
params.require(:resume).permit(:name, :bio, :skills)
end
I get an array of skills
returned from the form. As I have declared skills
as string type in database, I am joining the checked values stored in the array on comma
before sending them to the database. The reason I am doing this is because I don't know the data type
for an Array
in order to store the skills in database directly.
Is this the correct approach to store checkbox values in database or it could be implemented in a better way?
It seems like unnecessary work to split and join the skills
(checkbox values) just to create/update in database.
EDIT
With my approach(non-serialize), when I update bio
field in a Resume, this is how its updated
SQL (0.2ms) UPDATE "resumes" SET "bio" = ?, "updated_at" = ? WHERE "resumes"."id" = 20 [["bio", "This is my bio"], ["updated_at", Thu, 27 Feb 2014 19:27:06 UTC +00:00]]
Using serialize
approach as suggested by PinnyM,
class Resume < ActiveRecord::Base
....
serialize :skills
end
When I update bio
field in a Resume, this is how its updated
SQL (0.2ms) UPDATE "resumes" SET "bio" = ?, "updated_at" = ?, "skills" = ? WHERE "resumes"."id" = 20 [["bio", "This is my new bio"], ["updated_at", Thu, 27 Feb 2014 20:18:31 UTC +00:00], ["skills", "---\n- Java\n- C\n- Ruby\n"]] (0.6ms) commit transaction
Notice the difference that skills
is getting updated again even though I didn't make any change to it whereas, with my approach skills
is not updated since I didn't make any changes to it. I am wondering why the difference in behavior? Is there any option which I could pass to serialize
to stop this kind of behavior?
Upvotes: 0
Views: 219
Reputation: 35531
Use the serialize
macro in your Resume model to help with this:
serialize :skills, Array
With this you can leave the skills parameter set as an Array, and ActiveRecord will perform the serialization/deserialization for you.
As for the constant UPDATEs performed, this is an ongoing issue discussed in the links I provided below. If this behavior bothers you, the simplest workaround that I can see would be a variation of @M.G.Palmer's answer here. The gist of it would be to break this out to a simple model for storing this Array:
class Resume < AR::Base
has_one :skill_store
delegate :skills, to: :skill_store, allow_nil: true
class SkillStore < AR::Base
belongs_to :resume
serialize :skills, Array
Because this data is now in a separate table, don't forget to eager-load if collecting groups of Resume's that require the skills
data.
Upvotes: 2