Michael Johnston
Michael Johnston

Reputation: 2382

Rails form to create model with reference

I'm trying to create a model form that will allow me to add references by name via a <select> tag.

e.g.

In the database there are already RefModels with ref_name = "a", ref_name = "b", ref_name = "c".

Form:

<%= form_for @model %>
  <%= f.label :ref_models, "Referenced Models:" %>
  <%= f.select :ref_models, ["a","b","c"], {}, {:multiple => true} %>

Controller:

def create
  @model = Model.new(model_params)
  params[:model][:ref_models].each do |ref|
    @ref = RefModel.where("ref_name = ?", ref)
    @model.ref_models << @ref
  end
  respond_to do |format|
    ...
  end
end

In my logs I'm getting this error:

Started POST "/models" for 127.0.0.1 at 2013-06-25 16:20:48 -0300
Processing by ModelssController#create as JS
  Parameters: {"utf8"=>"✓", "models"=>{..., "ref_models"=>["a", "b", "c"], ...}, "commit"=>"Create"}
Completed 500 Internal Server Error in 2ms

ActiveRecord::AssociationTypeMismatch (RefModel(#70144007274440) expected, got String(#70144005442620)):
  app/controllers/models_controller.rb:52:in `create'

What's the problem?

Note:

I changed the actual model names for "model" and "ref_model" to generalize.

EDIT: The error occurs on this line:

@model = Model.new(model_params)

Upvotes: 1

Views: 830

Answers (2)

MrYoshiji
MrYoshiji

Reputation: 54902

The error comes from this part:

@model = Model.new(model_params)

I'm pretty sure your model_params is actually params[:model]. If yes, it means it tries to create a record for Model with the attribute ref_models and the values contained in params[:model][:ref_models]

You should take off the params[:model][:ref_models] before passing it to the Model.new(params[:model]):

def create
  ref_models = params[:model].delete(:ref_models)
  @model = Model.new(params[:model])
  ref_models.each do |ref|
    @ref = RefModel.where("ref_name = ?", ref)
    @model.ref_models << @ref
  end
  respond_to do |format|
    ...
  end
end

Upvotes: 1

GoGoCarl
GoGoCarl

Reputation: 2517

Do these ref_models have IDs as well as names? If so, you can get Rails to do the heavy lifting for you.

In your view, do:

<%= f.select :ref_model_ids, RefModel.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>

Then, you can take out the custom code from your controller, Rails knows how to link those models up appropriately. That's assuming you have a table like model_ref_model with columns for model_id and ref_model_id.

Hope that helps...

Upvotes: 1

Related Questions