0

I have two models, Designer and Influence. They have a "has_many" relationship to eachother :through a join model called Relation.

I want to use a single form to create/update the designer model with information from the influence model. Is it possible to create a relation object through the create/update actions in the designer controller? Or do I need to create a Relations controller?

My current code is as below, and results in a NoMethodError in DesignersController#Update.

Designer.rb

attr_accessible :name, :relation, :influence
has_many :relations
has_many :influences, :through => relations

Influence.rb

attr_accessible :name, :relation, :designer
has_many :relations
has_many :designers, :through => :relations

Relation.rb

attr_accessible :designer_id, :influence_id
belongs_to :designer
belongs_to :influence

designers/_form.html.erb

<%= form_for @designer do |f| %>

  <%= f.label :name %><br />
  <%= f.text_field :name %>

  <%= f.label :influence %><br />
  <%= f.collection_select :influence, Influence.order(:name), :id, :name, include_blank: true %>

  <%= f.submit %>

<% end %>

designers_controller.rb

def update
  @designer = current_designer
  ** Is there a way to create a new relation object here? **
jordanpg
  • 6,386
  • 4
  • 46
  • 70
umezo
  • 1,519
  • 1
  • 19
  • 33

1 Answers1

1

There are 2 general ways to do this. You can create a Relations object directly or you can create an Influence object using the Designer association, and one will be made automatically:

Relation.create relation_attributes

or

@designer.influences.create influence_attributes (this creates a new Relation object)

jordanpg
  • 6,386
  • 4
  • 46
  • 70
  • Thanks @jordanpg. I will opt for the first, as I do not want to create any new influences, but want to just add existing influences to existing and new designers through new relations. For the first example, how to I reference the influence_id from the collection_select input in the designer form? I have added the following to my update method in my designers controller. Relation.create(designer_id: current_designer.id, influence_id: :influence_id) Is this incorrect? – umezo Aug 06 '12 at 21:44
  • In the `collection_select` statement, you are already referencing the `influence_id`: `Influence.order(:name), :id, :name`. If you want to reference an `influence_id` associated with the @designer object, do: `f.object.influences.first`, for example. Also, don't forget to accept the answer if you are happy with it. – jordanpg Aug 06 '12 at 21:52
  • Hi @jordanpg, I'll accept as soon as I can get this to work. Sorry for the novice questions... For the first option, what would be the best way to define "relation_attributes"? I have kept all of my files unchanged, except for adding "Relation.create relation_attributes" to the update method in the designers_controller. This give me "undefined local variable or method 'relation_attributes'". Could you please help me understand where and how can I define this? – umezo Aug 06 '12 at 22:12
  • `relations_attributes` was just a stand-in for a hash of attributes for the new Relation object. So, for example, if a Relation has a name and a color: `Relation.create({name: 'a name', color: 'blue'})` – jordanpg Aug 06 '12 at 22:17
  • Yes, so Relation has only two attributes, designer_id and influence_id. The first would be equal to current_designer (ie. the person that's editing the form), and the second attribute would be the input from the form. That's why I initially tried "Relation.create(designer_id: current_designer.id, influence_id: :influence_id). What am I doing wrong? – umezo Aug 06 '12 at 22:23
  • I see. `influence_id` is not set to anything in the Designer controller. Add `:id` to the view: `f.collection_select :influence, :id, Influence.order(:name), :id, :name, include_blank: true` and then access this in the Designer controller with `params[:influence][:id]`. – jordanpg Aug 06 '12 at 22:28
  • Thanks @jordanpg. Relation.create(designer_id: current_designer.id, influence_id: params[:influence][:id]) results in undefined method '[]'... I need to go now, but will try again later tonight. Thanks again for your help. – umezo Aug 06 '12 at 22:40
  • Should be OK... did you add `:id` to the second argument of `collection_select`? – jordanpg Aug 06 '12 at 23:00
  • Figured it out. I had to remove the "f" from "f.collection select." This makes sense to me, as the "f" is a variable for "@designer", not "@influence". Thanks for the help! – umezo Aug 07 '12 at 02:05