2

I'm relatively new to Rails and I am having an enormous difficulty trying to work with models that have HABTM associations between them.

These are my models:

challenge.rb:

class Challenge < ActiveRecord::Base
    has_and_belongs_to_many :skills
    attr_accessible :description, :name, :relevant_content, :solutions, :skills
end

skill.rb:

class Skill < ActiveRecord::Base
    has_and_belongs_to_many :challenges

    attr_accessible :name
end

I've also created a join table called challenges_skills using the following migration:

class CreateChallengesSkills < ActiveRecord::Migration
    def up
        create_table :challenges_skills, :id => false do |t|
        t.integer :challenge_id
        t.integer :skill_id
        end
    end

    def down
    drop_table :challenges_skills
    end
end

And I'm using the helper below to to select my challenge required skills:

<%= collection_select(:challenge, :skills, Skill.all, :id, :name, {}, {:multiple => "true"}) %>

HTML:

<select id="challenge_skills" multiple="multiple" name="challenge[skills][]">
    <option value="2">Pesquisa</option>
    <option value="3">Senso Critico</option>
    <option value="4">Criatividade</option>
    <option value="5">Colaboracao</option>
    <option value="6">Comunicacao</option>
    <option value="7">Proatividade</option>
</select>

Here's my params hash:

{"utf8"=>"✓",
 "authenticity_token"=>"n0ggK8eE7vjh+qY33lYbNLJtZW6Sz7LyM2IRVbAPwhM=",
 "challenge"=>{"description"=>"My description.",
 "skills"=>["", "3", "4"],
 "name"=>"Test Challenge",
 "relevant_content"=>"My relevant_content",
 "solutions"=>"My solutions"},
 "commit"=>"Create Challenge!"
}

Error: Skill(#70228688111620) expected, got String(#14953820)

The problem is that I don't know how to handle the skills hash, turn it into an object array inside my challenges controller create action. I know it should be something simple but I cannot find a pratical solution. I want to know how to code to associate the skills collection to my challenge instance inside challenges controller.

ChallengesController#create

def create

    @challenge = Challenge.new(params[:challenge])

    ???

Thanks

2 Answers2

0

The actual answer is add "skills" to your accepted parameters:

def approved_params
  params.require(:challenge).permit(
    :name,
    :description,
    ...
    :skills => []
  )
end

then have in your create/update:

def update
  @controller.update(approved_params)
end

That's it

David Moritz
  • 92
  • 10
-5

My advice is to stay away from HABTM and switch to has_many :through it'll be easier to work with and more flexible to change (add attributes) over time.

See

http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association

and

https://stackoverflow.com/a/11601236/631619

and here's a nice comparison of the two:

http://railscasts.com/episodes/47-two-many-to-many

Community
  • 1
  • 1
Michael Durrant
  • 93,410
  • 97
  • 333
  • 497
  • Thanks for your help, but I still haven't got my problem solved. – Guilherme Solinscki Apr 12 '13 at 21:39
  • I suggest you try the has_many :through and if it isn't working post both the error and your code as another question. Hang in there, rails has a million little things to know but it can work if you keep at it and keep posting on SO. – Michael Durrant Apr 12 '13 at 22:00
  • OK. I'll try it. What's the best way to write the association in my create action? Could you give me an example? Thank you – Guilherme Solinscki Apr 12 '13 at 22:03
  • You need to look at the documentation and give it a go. In the guides.rubyonrails... you'll see physician and patients and appointment, so for you that will be Challenge, Skill and ChallengeSkill. In the railscast you see category and product and categorization and again for you that is Challenge, Skill and ChallengeSkill. Please give it a go first and if stuck post a new question (I won't be checking this). – Michael Durrant Apr 12 '13 at 22:09
  • 1
    After refactoring my code I've realized that the problem was in my params hash. I don't know whats the best way to convert "skills"=>["", "3", "4"] into {{"id" => 3, "name" => "Senso Critico" }} The associations types worked both fine with some stub code. I'll try to find a solution to the hash problems. Thanks – Guilherme Solinscki Apr 12 '13 at 22:45