Rails - 通过表或选择添加到关联

时间:2016-04-27 17:26:26

标签: ruby-on-rails ruby ajax activerecord

我是Rails世界的新手,所以我尝试做一些示例应用以了解更多信息。我被卡住了,我会感激任何帮助。我没有成功地寻找类似的问题。但我认为那里有一个。

案例是:我有一个蛋糕模型,通过食谱有很多成分。创建,编辑,删除是好的,我已经学过的基础知识。但是我想在创建(或编辑)蛋糕的同时,能够看到已经在该食谱中的所有成分(完成)并从中选择"选择"或表格(列出,如下所示)我想在食谱中添加或删除的任何成分。在不提交数据库且不重新加载页面(Ajax)的情况下完成所有这些操作。然后当我点击" Save cake"一切都被提交到数据库。我说清楚了吗?

以下是我到目前为止所做的事情:

的routes.rb

Rails.application.routes.draw do
  resources :cakes do
    resources :ingredients do
      member do
        get 'add', to: 'cakes#add'
        get 'remove', to: 'cakes#remove'
      end  
    end  
  end  

  resources :ingredients 

end 

cake.rb

class Cake < ActiveRecord::Base
  has_many :recipes
  has_many :ingredients, through: :recipes
end

ingredient.rb

class Ingredient < ActiveRecord::Base
  has_many :recipes
  has_many :cakes, through: :recipes
end

recipe.rb

class Recipe < ActiveRecord::Base
  belongs_to :cake
  belongs_to :ingredient
end 

cakes_controller.tb

class CakesController < ApplicationController
  before_action :set_cake, only: [:show, :edit, :update, :destroy]
  before_action :set_ingredients, only: [:new, :edit]

  def index
    @cakes = Cake.all
  end

  def show

  end

  def new
    @cake = Cake.new
  end

  def edit

  end

  def create
    @cake = Cake.new(cake_params)
    @cake.save
    redirect_to cakes_path
  end

    private
          def cake_params
            params.require(:cake).permit(:name)
          end

          def set_cake
            @cake = Cake.find(params[:id])
            @used_ingredients = @cake.ingredients
          end

          def set_ingredients
            @ingredients = Ingredient.all
          end

end

形成蛋糕 - _form.html.erb

<%= form_for @cake do |f| %>
<p>
    <%= f.label :name %>
    <%= f.text_field :name%>
</p>
<div id="used ingredients" >
    <%= render 'recipe_ingredients'%>
</div>
<div id="available ingredients" >
    <%= render 'available_ingredients'%>
</div>
<p>
    <%= f.submit%>
</p>
<% end %>

食谱中的成分--_recipe_ingredients.html.erb

<table border="1px">
<tr>
    <th colspan="2">Used Ingredients</th>
</tr>

<% @used_ingredients.each do |ingredient| %>
    <tr>
        <td> <%= ingredient.name %> </td>
        <td> <%= link_to 'Remove', remove_cake_ingredient_path(@cake,ingredient), remote: true %> </td>
    </tr>
<% end %>

</table>

可用的成分 - _available_ingredients.html.erb

<table border="1px">
<tr>
    <th colspan="2">Available Ingredients</th>
</tr>

<% @ingredients.each do |ingredient| %>
    <tr>
        <td> <%= ingredient.name %> </td>
        <td> <%= link_to 'Add', add_cake_ingredient_path(@cake,ingredient), remote: true %> </td>
    </tr>
<% end %>

</table>

这里是我卡住的地方,如何添加或删除@ cake.ingredients中的项目而不提交数据库并重新加载配方成分列表而不重新加载页面(事实上,重新加载列表我知道怎么做,通过JS再次渲染局部,这没关系。)。 但这里的诀窍是点击&#34;添加&#34;或&#34;删除&#34;链接,添加或从配方中删除一个成分,只在&#34; Save Cake&#34;之后提交。提交按钮。或者如果用户改变主意,取消任何更改。这就是我需要处理对象列表而不是直接处理数据库的原因。

有人可以帮助我吗?

PS:1 - 我知道remote:true会在链接上触发action.js.erb文件。这对我来说很清楚。问题是我无法在每次添加/删除链接点击时使用相同的对象(@ cake.recipes)。在另一个测试中,我制作了一个全局哈希$成分,但我不认为这是Rubier模式。

2 - 我制作了一个包含所有可用成分的表格(网格),但它是一个select或collection_select,但我不想使用multiple:true选项

3 - 如果有人知道的话,也许有一些宝石会做我需要的东西。

1 个答案:

答案 0 :(得分:0)

卢西亚诺,

为什么不能创建蛋糕然后添加成分的过程会导致数据库中的增量变化?为什么这一切都必须是完整的客户端(并增加用户失去工作的风险)。

如果您想在客户端执行此操作,请在准备提交之前避免跳转到后端。您必须提供JS以在用户选择时动态添加表单元素。

回答你的问题: 1)不要使用全局...不仅不是Ruby ..如果你有多个用户,它将无法工作。但是,如果您愿意,可以自由使用会话,但这通常是一种沮丧的做法,在您的情况下不需要。如果您如上所述逐步构建模型,则可以完全避免这种情况。

2)看看'选择'js选择..它非常强大,我相信它会满足你的要求

3)在您第一次学习Rails时尽量避免使用gem。大项目团队中发现的宝石数量惊人,这使得新团队成员越来越难以加快速度。大多数项目都有数百个宝石,但对于某些应用程序来说,大多数都是已知的(或几乎是默认的)。