1

Here is the situation :

class Activity < ApplicationRecord
  has_many :activity_amenities
end
class Amenity < ApplicationRecord
  has_many :activity_amenities
  has_many :activities, through: :activity_amenities
end
class ActivityAmenity < ApplicationRecord
  belongs_to :activity
  belongs_to :amenity
end

So basically i have Activities that have Amenities. The reason for me to use a has_many :through association is because I want to create basic Amenities and each Activity' amenities will have a description proper to the Activity.

So, I want to create new Amenities straight in the creation/edition of an Activity. This image should illustrate it very well :

enter image description here

So when I click on Add amenity button, it should add new select/input group.

Then when I click on create, it should create all the ActivityAmenities and associate them with the Activity model.

Any idea How this should be done (in the Controller and in the View) ? Couldn't find anything really...

ps : note that I'm using simple-form gem for the forms

user12178999
  • 63
  • 10

1 Answers1

0

For all your has_many associations, include the inverse_of option. Then when adding the ActivityAmenities by ID, pass them all in at once as an array. e.g when you make activity_params, pass in activity_amenity_ids[]. Rails will use the automatically generated #activity_amenity_ids= method to handle the creation for you.

Model:

class Activity < ApplicationRecord
  has_many :activity_amenities, inverse_of: activity
end
class Amenity < ApplicationRecord
  has_many :activity_amenities, inverse_of: amenity
  has_many :activities, through: :activity_amenities
end
class ActivityAmenity < ApplicationRecord
  belongs_to :activity
  belongs_to :amenity
end

Controller:

params.require(:activity).permit(activity_amenity_ids[], :whatever_else)

View: Whatever the name of your input for your form

name="activity[activity_amenity_ids][]"

If you want an explanation of why you you pass in activity_amenity_ids, is basically tl;dr it creates the object if it doesn't exist, and does nothing if it does.

E.g try

Activity.create(name: "Running or whatever", activity_amenity_ids: [1, 2, 3])

And see the result. Notice how a new activity is created along with its associated activity amenities in a single transaction?

TedTran2019
  • 887
  • 5
  • 15
  • Cool, let me try that ! – user12178999 Oct 25 '19 at 14:17
  • I just found this : https://stackoverflow.com/questions/32884412/how-to-handle-multiple-models-in-one-rails-form what do you think about it ? – user12178999 Oct 25 '19 at 20:02
  • Yeah, that'll work fine too, and it's more Rails-like. My method is just without the Rails magic, if you wrote the stuff out by hand. Good luck, man. – TedTran2019 Oct 25 '19 at 20:22
  • Okay everything works well now... I can add/edit ActivityAmenities straight from the Activity forms. The only thing I'm missing is the `Add amenity` button mechanic... Once clicked on, it should add a row of inputs (select + input). Do you have any idea how I can achieve that in a clean way ? (Once I have the full solution, I will post it as a solution below) – user12178999 Oct 25 '19 at 21:13