Kirti Thorat
Kirti Thorat

Reputation: 53048

Checkbox implementation logic for a model

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

Answers (1)

PinnyM
PinnyM

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

Related Questions