Search code examples
ruby-on-railsrubysimple-formnested-attributes

Rails saving value from dynamic dropdown of foreign model not working


I have two models:

class Location < ActiveRecord::Base
    has_many :cows
    accepts_nested_attributes_for :cows
end

class Cow < ActiveRecord::Base
    belongs_to :location
end

Every location has an id and a name. A cow consists of an id, two strings and two dates and it also includes a location_id.

In my cow view I have a dropdown of every location. It gets updated automatically whenever I create, edit or delete a location. When I choose a location from the dropdown, the cow index changes based on the fitting location_id in cows.

Cows index.html.erb:

<!-- Dropdown Button -->
<a class='dropdown-button' href='#' data-activates='dropdown_locations'>
<i class="fa fa-arrow-down" aria-hidden="true"></i> Ort auswählen</a>

<!-- Dropdown Content -->
<ul id='dropdown_locations' class='dropdown-content'>
  <% @locations_all.each do |loc| %>
    <li><%= link_to loc.name, cows_path(location: loc.id) %></li>
  <% end %>
</ul>

The cows index page is a page for showing the content and adding new values at the same time. As I mentioned, the index changes based on the selected location. But it only works if I populate the cow table manually in a database editor since the selected location from the dropdown won't be saved to cows.

Here's the form for creating new cows in cows index.html.erb:

<%= simple_form_for Cow.new do |f| %>
    <%= f.input :ohrmarke, as: :string, input_html: { maxlength: 5 } %>
    <%= f.input :stallnummer, as: :string, input_html: { maxlength: 3 } %>
    <%= f.hidden_field :location_id, value: @location_id %>

    <button class="btn waves-effect waves-light" type="submit" name="action">Zuordnung speichern</button>
<% end %>

I use a hidden_field for the location_id and the value should be the location_id of the selected location from the dropbox.

But for some reason creating new cows just does not work. Here's my cow controller (shortened):

def index
  @locations_all = Location.all
  if (params[:location] && cows = Cow.where(location_id: params[:location]))
    @cows = cows
    @location = Location.where(id: params[:location])
  else
    @cows = Cow.all
  end
end

def new
  @cow = Cow.new
end

def create
  @cow = Cow.new(cow_params)

  respond_to do |format|
    if @cow.save
      # format.html blabla... the usual stuff
    end
  end
end

private
  def set_cow
    @cow = Cow.find(params[:id])
  end

  def cow_params
    params.require(:cow).permit(:ohrmarke, :hin, :weg, :stallnummer, location_attributes: [:location_id])
  end
end

I think that either my hidden_field or the create controller is not working. But I don't know what I did wrong. At least changing the index based on the selected location works. Thanks for any help in advance.


Edit: I solved it with your help and on my own, see my answer.


Solution

  • After some suggestions I changed the code and set the location_id. Now everything works fine. Here's the new code:

    Cow controller:

    def index
      @locations_all = Location.all
      if (params[:location] && cows = Cow.where(location_id: params[:location]))
        @cows = cows
        @location_id = params[:location] # used for the form
        @location = Location.find(@location_id) # used for ex. showing the name
      else
        @cows = Cow.all
      end
    end
    
    def cow_params
      params.require(:cow).permit(:ohrmarke, :hin, :weg, :stallnummer, :location_id)
    end
    

    Form:

    <%= f.hidden_field :location_id, value: @location_id %>
    

    I also changed the models accordingly (moved nested_attributes to Cow).