簡體   English   中英

如何在Rails 4的ruby中從父對象創建嵌套的子對象

[英]How to create a nested child from parent object in ruby on rails 4

我嘗試在Rails 4中重現在Rails 3中運行良好的功能:使用new_parent_child_path(@parent)從其父級的Show視圖創建子記錄。

不幸的是,當我驗證子項的創建時,收到一條消息,指出child.parent_id field cannot be null 通讀一遍,看起來確實很少使用此new_parent_child_path(@parent)功能。 這是我的代碼的一部分...

楷模:

class BusinessArea < ActiveRecord::Base
     ... some checks ...
 validates :playground_id, presence: true
 belongs_to :playground
 belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"       # helps retrieving the owner name
 belongs_to :status, :class_name => "Parameter", :foreign_key => "status_id"    # helps retrieving the status name
 has_many :business_flows
end

class BusinessFlow < ActiveRecord::Base
     ... some checks ...
 validates :playground_id, presence: true
 belongs_to :playground
 belongs_to :owner, :class_name => "User", :foreign_key => "owner_id"       # helps retrieving the owner name
 belongs_to :status, :class_name => "Parameter", :foreign_key => "status_id"    # helps retrieving the status name
 has_many :business_processes
 belongs_to :business_area
end

路線:

ODQStep1::Application.routes.draw do

#static pages
get '/help',        to: "static_pages#help"
get '/about',   to: "static_pages#about"
get '/contact',     to: "static_pages#contact"
get '/home',        to: "static_pages#home"

#root definition
root to: "static_pages#home"

resources :sessions, only: [:new, :create, :destroy]  
get '/signin',  to: 'sessions#new'  , via: :get
match '/signout', to: 'sessions#destroy', via: :delete

resources :parameters

resources :business_areas do
     resources :business_flows, :only=>[:new, :create]
end
end

用於創建子業務流程的鏈接位於“業務區域顯示”視圖的末尾:

<% provide(:title, 'Managing business areas') %>

  <h1>Business area: <%= @business_area.name %></h1>

  <ul class="mid_menu">
    <li><%= link_to 'Edit', edit_business_area_path(@business_area) %> |</li>
    <li><%= link_to 'Back to list', business_areas_path %> |</li>
    <li><%= link_to 'Destroy', @business_area, confirm: 'Are you sure?', method: :delete %></li>
  </ul>

<!-- <p id="notice"><%= notice %></p> -->

  <div class="tabbable">
    <ul class="nav nav-tabs">
      <li class="active"><a href="#tab1" data-toggle="tab">Definition</a></li>
      <li><a href="#tab2" data-toggle="tab">Ownership</a></li>
    </ul>
    <div class="tab-content">

    <div class="tab-pane active" id="tab1">
<!-- Tab content for Definition -->

      <div class="row">
        <div class="span2 text-right">Name:
        </div>
        <div class="span6"><%= @business_area.name%>
        </div>
        <div class="span1 text-right">Code:
        </div>
        <div class="span1"><%= @business_area.code%>
        </div>
        <div class="span1 text-right">Status:
        </div>
        <div class="span1"><%= @business_area.status.name%>
        </div>
      </div>

      <div class="row">
        <div class="span2 text-right">Description:
        </div>
        <div class="span10"><%= @business_area.description%>
        </div>
      </div>

      <div class="row">
        <div class="span2 text-right">Hierarchy:
        </div>
        <div class="span2"><%= @business_area.hierarchy%>
        </div>
      </div>

      <div class="row">
        <div class="span2 text-right">PCF index:
        </div>
        <div class="span2"><%= @business_area.PCF_index%>
        </div>
        <div class="span2 text-right">PCF reference:
        </div>
        <div class="span2"><%= @business_area.PCF_reference%>
        </div>
      </div>


<!-- Tab content -->
    </div>    

    <div class="tab-pane" id="tab2">
<!-- Tab content for Ownership -->

      <div class="row">
        <div class="span2 text-right">Unique id:
        </div>
        <div class="span2"><%= @business_area.id%>
        </div>
        <div class="span2 text-right">Created by:
        </div>
        <div class="span2"><%= @business_area.created_by%>
        </div>
      </div>
      <div class="row">
        <div class="span2 text-right">Playground id:
        </div>
        <div class="span2"><%= @business_area.playground_id%>
        </div>
        <div class="span2 text-right">Created at:
        </div>
        <div class="span2"><%= @business_area.created_at%>
        </div>
      </div>
      <div class="row">
        <div class="span2 text-right">Owner:
        </div>
        <div class="span2"><%= @business_area.owner.login%>
        </div>
        <div class="span2 text-right">Updated by:
        </div>
        <div class="span2"><%= @business_area.updated_by%>
        </div>
      </div>
      <div class="row">
        <div class="span2 text-right">
        </div>
        <div class="span2">
        </div>
        <div class="span2 text-right">updated at:
        </div>
        <div class="span2"><%= @business_area.updated_at%>
        </div>
      </div>

<!-- Tab content -->
    </div>

    </div>
  </div>

<table width=100%>    
  <tr><td><hr /></td></tr>
  <tr align="left">
    <th>Linked Business Flows</th>
    <th></th>
  </tr>
  <tr>
    <td>
      <table class="table table-striped table-condensed">
        <%@business_area.business_flows.each do |business_flow| %>
        <tr align="left">
          <td valign="top"> <%=link_to business_flow.code, business_flow%> </td>
          <td valign="top"> <%=business_flow.name%> </td>
          <td valign="top"> <%=business_flow.description%> </td>
          <td> </td>
        </tr>
        <% end%>
      </table>
    </td>
  </tr>
  <tr>
    <td>
      <%= link_to 'Add business flow', new_business_area_business_flow_path(@business_area) %>
    </td>
  </tr>
</table>

業務流程表格

<%= form_for [@business_area, @business_flow] do |f| %>
  <% if @business_flow.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@business_flow.errors.count, "error") %> prohibited this business_flow from being saved:</h2>

      <ul>
      <% @business_flow.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

      <div class="row">
        <div class="span2 text-right">Name:
        </div>
        <div class="span10 field"><%= f.text_field :name, :class => "span8" %>
        </div>
      </div>
      <div class="row">
        <div class="span2 text-right">Code:
        </div>
        <div class="span2 field"><%= f.text_field :code %>
        </div>
        <div class="span2 text-right">Status:
        </div>
        <div class="span2 field"><%= f.collection_select :status_id, @statuses_list, :id, :name %>
        </div>
      </div>

      <div class="row">
        <div class="span2 text-right">Description:
        </div>
        <div class="span10 field"><%= f.text_area :description, :rows => 5, :class => "span8" %>
        </div>
      </div>

      <div class="row">
        <div class="span2 text-right">Hierarchy:
        </div>
        <div class="span2 field"><%= f.text_field :hierarchy %>
        </div>
      </div>

      <div class="row">
        <div class="span2 text-right">PCF index:
        </div>
        <div class="span2 field"><%= f.text_field :PCF_index %>
        </div>
        <div class="span2 text-right">PCF reference:
        </div>
        <div class="span2 field"><%= f.text_field :PCF_reference %>
        </div>
      </div>

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

業務流程控制器

class BusinessFlowsController < ApplicationController
# Check for active session 
  before_action :signed_in_user

# Retrieve current business flow
  before_action :set_business_flow, only: [:show, :edit, :update, :destroy]

# Create the list of statuses to be used in the form
  before_action :set_statuses_list, only: [:new, :edit, :update, :create]

  # GET /business_flows
  # GET /business_flows.json
  def index
    @business_flows = BusinessFlow.order("hierarchy ASC")

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @business_flows }
    end
  end

  # GET /business_flows/1
  # GET /business_flows/1.json
  def show
    ### Retrieved by Callback function
  end

  # GET /business_flows/new
  # GET /business_flows/new.json
  def new
    @business_flow = BusinessFlow.new
    @business_flow.business_area_id = params[:business_area_id]
  end

  # GET /business_flows/1/edit
  def edit
    ### Retrieved by Callback function
  end

  # POST /business_flows
  # POST /business_flows.json
  def create
    @business_flow = BusinessFlow.new(business_flow_params)
    @business_flow.business_area_id = params[:business_area_id]
    @business_flow.updated_by = current_user.login
    @business_flow.created_by = current_user.login
    @business_flow.playground_id = current_user.current_playground_id
    @business_flow.owner_id = current_user.id

    respond_to do |format|
      if @business_flow.save
        format.html { redirect_to @business_flow, notice: 'Business flow was successfully created.' }
        format.json { render json: @business_flow, status: :created, location: @business_flow }
      else
        format.html { render action: "new" }
        format.json { render json: @business_flow.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /business_flows/1
  # PUT /business_flows/1.json
  def update
    ### Retrieved by Callback function
    @business_flow.updated_by = current_user.login

    respond_to do |format|
      if @business_flow.update_attributes(business_flow_params)
        format.html { redirect_to @business_flow, notice: 'Business flow was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @business_flow.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /business_flows/1
  # DELETE /business_flows/1.json
  def destroy
    ### Retrieved by Callback function
    @business_flow.destroy

    respond_to do |format|
      format.html { redirect_to business_flows_url }
      format.json { head :no_content }
    end
  end


### private functions
  private

  ### Use callbacks to share common setup or constraints between actions.
    # Retrieve current business flow
    def set_business_flow
      @business_flow = BusinessFlow.includes(:owner, :status).find(params[:id]) 
    end

  ### before filters
    # Check for active session
    def signed_in_user
      redirect_to signin_url, notice: "You must log in to access this page." unless signed_in?
    end

  ### strong parameters
  def business_flow_params
    params.require(:business_flow).permit(:code, :name, :hierarchy, :status_id, :PCF_index, :PCF_reference, :description)
  end

end

單擊“新業務流程”鏈接時記錄

--- !ruby/hash:ActionController::Parameters
action: new
controller: business_flows
business_area_id: '2'

驗證業務流程創建時記錄

--- !ruby/hash:ActionController::Parameters
utf8: ✓
authenticity_token: PwhUukDm3f0OIDhOZfeKxwgtH7M5GFoOuy63Mt7Tcw=
business_flow: !ruby/hash:ActionController::Parameters
  name: aaaaaaa
  code: bbbbbbb
  status_id: '8'
  description: ''
  hierarchy: cccccccc
  PCF_index: ''
  PCF_reference: ''
commit: Create Business flow
action: create
controller: business_flows

我可以想象在表單中隱藏一個business_area_id字段,但是我希望有一種更聰明的方法,可以將傳遞給new()函數的參數也可以在create()函數中使用,即使它們必須通過強參數。

作為一個初學者,我不能說我對問題的分析是否正確,希望您能幫助我找到一個好的解決方案。

非常感謝你的幫助,

最好的祝福,

弗雷德

我看到您的新操作確實具有business_area_id: '2'參數,但是,在控制器的新操作中,您沒有實例化business_area。 它看起來應該像這樣:

class BusinessFlowsController < ApplicationController
  def new
    @business_area = BusinessArea.find params[:business_area_id]
    @business_flow = BusinessFlow.new
    # not needed here since this isn't being created yet
    # @business_flow.business_area_id = params[:business_area_id]
  end
  ... rest of code ...
end

現在,您實例化了business_areaform_for應該能夠正確構建嵌套路徑,其中應包含business_area_id 現在,您的business_flows控制器的create動作應如下所示:

def create
  @business_area = BusinessArea.find params[:business_area_id]
  @business_flow = @business_area.business_flows.build(business_flow_params)
  # assigning the parent id happens automatically in the build method
  # @business_flow.business_area_id = params[:business_area_id]
  @business_flow.updated_by = current_user.login
  @business_flow.created_by = current_user.login
  @business_flow.playground_id = current_user.current_playground_id
  @business_flow.owner_id = current_user.id

  ... rest of code ...
end

要確保表單的操作包括business_area_id請檢查呈現的html。 表單的屬性應如下所示:

action="/business_areas/<:business_area_id>/business_flows" method="post"

其中<:business_area_id>是父的整數ID,你的情況2

您使用的是嵌套路線,所以很好。 您沒有發布視圖代碼,因此我假設您不是在使用嵌套路由發布到business_flows控制器的create動作。 您的business_flow視圖的表單應類似於:

# in your controller: @business_flow = BusinessFlow.new
form_for [@business_area, @business_flow] do |f|

... rest of code ...

這會將表單發布到business_flows控制器的嵌套create動作中。 這樣,父母的ID將以params[:business_area_id]形式出現在路由中。 然后,您可以像在create動作中那樣簡單地將該ID分配給子模型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM