0

I am new to Rails and just building my first app (coming from a PHP and .NET background and loving it btw) but I have run into a problem that I am struggling to find an answer to, even though I am sure there is an easy one!!

My project has 3 main Models; Locations, Services and Location Services

There are multiple services available and a Location can have any number of them. Basically I am using a record in Locations Services to store the ID of the selected service and the ID of the location.

A simplified version of my models are as below:

class Location < ActiveRecord::Base
    has_many :location_services
end

class Service < ActiveRecord::Base
    has_many :location_services
end

class LocationService < ActiveRecord::Base
    belongs_to :location
    belongs_to :service
end

I have read up about nested forms and using 'accepts_nested_attributes_for' to allow sub forms to edit data taken from another model which sounds very similar to what I want, except I don't want to just be able to edit the Location Services that I have, I want to be able to choose from every single available Service as checkboxes, then when checked and my Location is saved, I want it to create a record for each selected service in the Location Services table using the ID of the Location and the ID of the service

Im sure I could easily generate all the tickboxes with Services.all and then loop through that and then in my controller grab all of the ticked checkboxes from the POST, loop through them and build an array of all of them and then pass that array to Location.location_services.create([]) but this is rails and I feel like there is probably a better way to do it?

So firstly, am i going about this in a stupid way? Rather than having 3 tables, is there a better way of doing it? And is there a nice way of generating and saving all of the services?

Many thanks in advance David

2 Answers 2

1

Many thanks Yan for your help on this one, I have finally managed to resolve my issue and it actually turned out to be really simple. I am posting here in the hope it helps someone else.

What I needed to do was add a has_many relation to services through location services so my model now looks like below:

class Location < ActiveRecord::Base       
   has_many :services, :through => :location_services
   has_many :location_services

   accepts_nested_attributes_for :location_services
end

I updated my view to include:

<%= f.collection_check_boxes(:service_ids, Service.all, :id, :name) do |b| %>
    <%= b.label(class: "check_box") do %>
      <%= b.check_box %>
      <%= b.object.name %>
    <% end %>
<% end %>

Then in my controller I have:

def location_params    
   params.require(:location).permit(:service_ids => [])
end

I have stripped out all of my other fields for simplicity. Then finally in the Update method, it is as simple as:

def update
   @location.update(location_params)

   redirect_to @location, notice: 'Location was successfully updated.'
end

Hope this helps someone out!!

Many thanks David

Sign up to request clarification or add additional context in comments.

Comments

0

A has_many relationship adds a number of methods to your model. From which you only need the collection_singular_ids method, which does the following:

Replace the collection with the objects identified by the primary keys in ids. This method loads the models and calls collection=.

The above method can be combined with collection_check_boxes as explained in this tutorial. So in your case you'll have something like:

f.collection_check_boxes :location_service_ids, LocationService.all, :id, :name

Note that the last parameter (:name here) is the text_method_option which generates the labels for your check boxes.

Last but not least: don't forget to use accepts_nested_attributes properly.

6 Comments

Hi Yan, many thanks for this!! That has been a big help!! I have all my checkboxes appearing correctly, Last thing, what is the best method to save that data once I get it to my controller? Many thanks!!
Read more about nested attributes here. You can use create and/or update as usual.
Hi Yan, many thanks once again. I believe I understand it now. I have added :location_service_ids => [] to my list of allowed parameters and it appears to be trying to save now. However, the problem I am getting is 'Couldn't find LocationService with 'id'=2', it is obviously looking for a location_service with an id of my service which it isn't going to find (or at least not the correct record anyway because it is from the wrong table). Im starting to worry I have my model's structured incorrectly. Many thanks again for your help!!
So you mean you are getting ID of service instead of location_service? If yes make sure that you have LocationService.all in your collection_check_boxes.
Hi fan. Yes that is correct. Problem is though, if I used LocationService.all that will populate the checkbooks with the wrong data, I need it to show all of my available services, LocationServices just includes the selected services for that location. I have managed to save the data by looping through the post and adding it with location.location_services.create which works but in not sure it's the most elegant solution? Many thanks again!!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.