Rails:根据下拉列表中的选定值更改索引

Rails: Change index based on selected value in dropdown

我有两个模型:

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

class Cow < ActiveRecord::Base
    belongs_to :location
end

每个位置都有一个 ID、一个名称和三个布尔值。一头牛由一个id、两个字符串和两个日期组成,还包括一个location_id.

在我的母牛视图中,我有每个位置的下拉列表。每当我创建、编辑或删除位置时,它都会自动更新。

在下拉列表下方,您可以看到曾经创建的所有奶牛。假设有一个表单可以添加一个带有两个字符串字段和两个日期字段的新奶牛。

现在我想要两件事:每当我 select 下拉列表中的一个值时,显示的奶牛应该改变。如果我 select 例如位置 2,则只应显示 table 中具有 location_id = 2 的奶牛。另外,当我创建一头新牛时,selected 位置的 id 也应该保存(在这个例子中,当我点击最右边的按钮时,location_id = 2 应该保存在牛行中底部)。

牛index.html文件中的动态下拉是这样的:

  <%= simple_form_for Cow.new do |f| %>
    <%= f.collection_select :location, Location.order('name').all, :id, :name, { prompt: "Ort auswählen" } %>
  <% end %>

这是我的奶牛控制器:

  def index
    if (params[:location] && Location.all.collect(&:name).include?(params[:location][:name]))
     @cows = Cow.send(params[:location][:name].downcase)
    else
     @cows = Cow.all
    end
  end

  # (...)

  def create
    @cow = Cow.new(cow_params)
    # (...)
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_cow
      @cow = Cow.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def cow_params
      params.require(:cow).permit(:ohrmarke, :hin, :weg, :stallnummer, :location_attributes => [:id])
    end
end

编辑的索引部分不起作用。可能是因为我有 Cow.new 的下拉菜单,但没有提交按钮。现在的问题是:我需要一头新奶牛的下拉菜单(值),但也想显示适合 selected 下拉菜单值的奶牛。我也不想只为下拉框使用提交按钮。我的问题有什么解决办法吗?我在谷歌上搜索了很多,但就是找不到适合我的问题的答案。


编辑: 我编辑了奶牛控制器和索引页面: 牛控:

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 create
  @cow = Cow.new(cow_params)
  # (...)
end

private
  # Use callbacks to share common setup or constraints between actions.
  def set_cow
    @cow = Cow.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def cow_params
    params.require(:cow).permit(:ohrmarke, :hin, :weg, :stallnummer, :location_attributes => [:id])
  end

奶牛index.html:

  <%= simple_form_for Cow.new do |f| %>
    <%= f.collection_select :location, Location.order('name').all, :id, :name, { prompt: "Ort auswählen" } %>
    <ul>
      <% @locations_all.each do |loc| %>
        <li><%= link_to loc.name, @cows.index(location: loc.id) %></li>
      <% end %>
    </ul>


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

    <table class="striped">
      <thead class="thead-default">
        <tr>
          <th>Ohrmarke</th>
          <th>Stallnr.</th>
          <th>Hin/Weg</th>
        </tr>
      </thead>
      <tbody>
        <!-- ... -->
      </tbody>
    </table><br>

    <%= f.input :ohrmarke, as: :string, input_html: { maxlength: 5 } %>
    <%= f.input :stallnummer, as: :string, input_html: { maxlength: 3 } %>

    <!-- datepicker not functional yet -->
    <input type="date" class="datepicker" id="hin" placeholder="hin">
    <input type="date" class="datepicker" id="hin" placeholder="weg">

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

下拉菜单和内容

这是 cows_controller#index 的可能实现。

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

然而,有几点需要说明,也有一些问题。 您用于下拉列表的代码假定您正在发出 POST 请求,这在这种情况下是不必要的。使用简单的 link_to 也可以实现同样的效果。为了让它起作用,你需要类似这样的东西:

<ul>
    <% @locations_all.each do |loc| %>
        <li><%= link_to loc.name, cows_path(location: loc.id) %></li>
    <% end %>
</ul>

表格

为了让表单使用正确的位置创建新的 Cow,您需要在其中包含一个 hidden_field

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

但这引入了一个设计问题。如果您没有在下拉菜单中选择任何 location,会发生什么情况?有很多方法可以解决这个问题,但我最喜欢的解决方案是在这种情况下隐藏表单。

<% unless @location %>
    #form-block ...
<% end %>

如果没有指定的 location 就无法创建 cows,则此解决方案似乎很理想。


编辑

好的,现在我可以见到你了HTML。我可以告诉你哪里出了问题。您的 simple_form_for 块围绕着整个视图。这可能不是你想要的。 forms 通常是 POST 请求,因此只有在计划发送数据或在 table 上创建新条目时才需要这些请求。 link_to是GET请求,可以向服务器请求信息。这是我的观点的一个小例子:

#drop-down menu
<div id="cow_menu">
    <ul>
        <% @locations_all.each do |loc| %>
            <li><%= link_to loc.name, cows_path(location: loc.id) %></li>
        <% end %>
    </ul>
</div>

#table
<table class="striped">
    # your table logic...  
</table>

#new Cow form
<%= simple_form_for Cow.new do |f| %>
    <%= f.hidden_field :location_id, value: @location_id %>
    <%= f.input :ohrmarke, as: :string, input_html: { maxlength: 5 } %>
    <%= f.input :stallnummer, as: :string, input_html: { maxlength: 3 } %>
    <%= f.submit "Zuordnung speichern", class="btn waves-effect waves-light"%>
<% end %>