【问题标题】:Rails Nested Resources - create and edit 2 levels away with form_for in partialRails 嵌套资源 - 在部分使用 form_for 创建和编辑 2 个级别
【发布时间】:2012-11-06 08:59:31
【问题描述】:

真的在这件事上绞尽脑汁。我对 Rails 比较陌生,尝试做一些我确信不会太难的事情。

我有一个模型“Trip”,它有很多“天”,里面有很多“活动”

我在“Trip”的 show.html.erb 视图中,在这个视图中,我正在渲染一个表单的部分内容,该表单应该允许我创建一个新的“Activity”以与“Day”或编辑已经属于“日”的现有“活动”

如何在表单部分中传递给 form_for,我想为其创建新的“活动”的“天”的局部变量。并且使用相同的表单部分,我如何检索与“活动”相关联的“日”?最终这些将是 AJAX 加载的对象。 在过去的几个小时里,我用谷歌搜索,找不到任何类似的例子。非常感谢您的帮助。

routes.rb

  resources :trips do
    resources :days    
  end

  resources :days do
    resources :activities
  end 

旅行的show.html.erb

<div id="activities_list">
  <%= render :partial => "activities" %>
</div> 

<div id="activity_form">
  <%= render :partial => "/activities/form", :locals => { :activity => @activity}  %>
</div>

<div id="bottom">
<%= link_to 'Edit', edit_trip_path(@trip) %> |
<%= link_to 'Back', trips_path %>
</div>

_activities.html.erb 部分

<h1><%= @trip.title %></h1>

<% @trip.days.each do |day| %>
<div id="blech_<%= day.id %>">
  <b><%= day.summary %></b>
      <% day.activities.each do |activity| %>
            <li id="activity_<%= activity.id %>"><%= link_to activity.address, edit_day_activity_path(day, activity), :remote => true  %></li>
      <% end %>
    <% end %>
  <%= link_to 'New Activity', new_day_activity_path(day), :remote => true %>
</div>
<% end %>

_form.html.erb partial 我知道我需要使用 (@day,@activity) 变量调用 day_activity_path。但我不知道如何在这里获取@day 变量

  <%= form_for([@activity], :remote => true) do |f| %>
     <fieldset>
       <%= f.label :title, "Activity" %><br />
       <%= f.text_field :title, :rows => 1 %><br />
     </fieldset>

    <div class="actions">
      <%= f.submit %>
    </div>
  <% end %>

【问题讨论】:

    标签: jquery ruby-on-rails ruby ajax ruby-on-rails-3


    【解决方案1】:

    好吧,假设您想在一天中添加一个新活动。

    不要忘记我们在这里使用的是 REST (http://old.thoughtsincomputation.com/posts/understanding-rest-in-rails-3)

    我们的一天必须有很多活动 我们的活动属于_一天

    class Day < ActiveRecord::Base
      has_many :activities
    end
    
    class Activity < ActiveRecord::Base
      belongs_to :day
    end
    

    我们的路线应该是这样的

    resources :days do
      resources :activities
    end
    

    使用该路由,我们生成的路径类似于

    days_path
    day_path
    new_day_path
    
    new_day_activity_path
    delete_day_activity_path
    edit_day_activity_path
    

    在我们的日视图中,我们位于类似 localhost:3000/days/1 的 URL 中 (DaysController,动作秀)

    在这种情况下,我们可以添加 @activity = Activity.new 并在下面部分添加表格

    <%= form_for [@day, @activity] do |form_field| %>
      rest_code_goes_here
    <% end %>
    

    这个表单会在ActivityController中提交,action :create with the day 控制器将检查验证并保存。

    看看链接是我用过的一个小应用程序 https://github.com/leftis/tefteraki/blob/master/app/views/debts/_new_dose.haml

    【讨论】:

    • 谢谢,但我实际上是从课堂上开始旅行显示视图所以(localhost:3000/trips/1/ 并想下去创建(或更新)一个活动(属于一天)属于旅行)。当我们处于“旅行”级别时,我将如何传递“@day”?我想点击一个链接,上面写着“为第 5 天添加活动”和“@day”是 Day #5,@activity = activity.new。但是如何?
    • 另外,它必须通过 AJAX 传递到部分
    【解决方案2】:

    哦,这实际上意味着旅行有很多天,资源有更多的嵌套,比如

    resources :trips
      resources :days
        resources :activities
      end
    end
    

    所以当你在 local/trips/1/ 你实际上是在 TripController 中时,显示动作 如果不创建一天,您就无法做到这一点,您可以有一个当天的表格,您可以在其中使用嵌套表格进行活动。

    最简单的方法是 ryan bates https://github.com/ryanb/nested_form 但要做到这一点,您必须首先将您的关系从 habtm 更改为

    class Day
      has_many :activities
    end
    
    class Activity
      belongs_to :day
    end
    

    然后您将在您的旅行显示视图中添加一个日期表单

    <% nested_form_for [:trip, Day.new], :remote => true do |form| %>
    
      <%= form.text_field :date %>
    
      <%= form.fields_for :activities do |activity_form| %>
        <%= activity_form.text_field :name %>
        <%= activity_form.link_to_remove "Remove this activity" %>
      <% end %>
      <p><%= form.link_to_add "Add an activity", :tasks %></p>
    
    <% end %>
    

    表单现在向 DaysController.create 发出请求,并带有旅行的参数 以及活动和要求 ajaxly 服务

    检查 gem 和我的应用程序,我正在使用所有这些,希望对您有所帮助!!!

    【讨论】:

    • 我想这会起作用,但不想使用 gem。嵌套模型表单的更新 Railscast 是否适用于此处?我可以更新 Days 模型以使用“accepts_nested_attributes_for :activities”。
    • 在这个例子中,Trips“Show”的控制器动作是什么样的?
    【解决方案3】:

    这就是我最终做的事情,并且有效。

    在我的“Trip”的 show.html.erb 中。

    show.html.erb

    <div id="activity_form">
    <h2>Activities</h2>
    </div> 
    

    链接到“编辑”一个 Activity。注意 :remote => true 告诉 Rails 控制器这将是一个 AJAX 请求,以便呈现 edit.js.erb

    <%= link_to activity.location[0, 20], edit_day_activity_path(day, activity), :class=>"btn btn-info fixedwidthbtn", method: :get, :remote => true 
    

    _form.html.erb 此表单部分位于活动视图目录 (../views/activities/_form.html.erb) 下。

    <%= form_for([@day, @activity], :remote => true) do |f| %>
    <fieldset>
      <%= f.label :title, "Activity" %>
      <%= f.text_field :title, :rows => 1 %> 
    </fieldset>
      <div class="actions">
        <%= f.submit %>
      </div>
    </form>
       <%= link_to 'Delete', [@day, @activity], method: :delete, data: { confirm: 'Are you sure?' } %>
    <% end %>
    

    edit.js.erb 这是活动视图目录 (../views/activities/edit.js.erb) 下的一个文件。表示要抓取 ID 为“activity_form”的 DOM 元素并渲染部分“表单”

    $("#activity_form").html("<%= escape_javascript(render(:partial => "form"))%>");
    

    update.js.erb 在编辑表单上点击更新后,我包含了这个 javascript,以呈现活动列表的更新部分。这样我就不必重新加载页面来查看更新。

    $("#activities_list").html("<%= escape_javascript( render(:partial => "/trips/activities") ) %>");
    

    routes.rb 这就是我嵌套路由的方式。仅按照最佳实践进行 1 级。

    资源 :trips do 资源:天 结束

    资源:天做 资源:活动 结束

    【讨论】:

      猜你喜欢
      • 2019-08-30
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      相关资源
      最近更新 更多