了解 Rails 控制器 - 通过关联模型的实例变量查看连接

Posted

技术标签:

【中文标题】了解 Rails 控制器 - 通过关联模型的实例变量查看连接【英文标题】:Understanding Rails controller - view connection via instance variable of associated model 【发布时间】:2015-05-31 01:29:38 【问题描述】:

我是一个新手,试图了解如何正确使用控制器中关联模型的实例变量以使它们可用于视图。这是如何运作的?有标准吗?我不断收到未定义的方法错误。 @example = Example.find(params[:id]) 或 @example = Example.find(example_params) 的正确用法是什么?对于相关模型?每个控制器操作是否具有特定的 @instance 变量公式(即 Example.all 用于 index )? 有谁知道关于控制器视图使用实例变量的综合指南?

代码

型号

class Presupuesto < ActiveRecord::Base
      belongs_to :cliente
      has_many :ordenes, dependent: :destroy
      has_many :medios, :through => :ordenes
      has_one :factura
      validates :fecha, :titulo, :cliente_id, :producto, presence: true
    end

    class Factura < ActiveRecord::Base
       has_many :factura_items
       belongs_to :cliente
       belongs_to :presupuesto
       validates :fecha_de_expedicion, presence: true
    end

查看

   _form.html.erb
<% content_for :title do %>Factura<% end %>
    <h3>Factura</h3>
    <div class="form">
      <%= simple_form_for @factura do |form| %>
        <%= form.error_notification %>
        <%= form.input :fecha_de_expedicion %>
        <%= form.association :cliente, :label_method => :nombre,  label: "Cliente", :include_blank => false %>
        <%= form.association :presupuesto, :label_method => :titulo,  label: "Presupuesto", :include_blank => false %>
        <%= form.button :submit, 'Submit', class: 'submit' %>
      <% end %>
    </div>

    new.html.erb
    <h1>New Factura</h1>

    <%= render 'form' %>

    <%= link_to 'Back', facturas_path %>

控制器

class FacturasController < ApplicationController

      # GET /facturas
      # GET /facturas.json
      def index
        @factura = Factura.all
        @cliente = Cliente.all
      end
      # GET /facturas/1
      # GET /facturas/1.json
      def show
        @factura = Factura.find(params[:id])
        @cliente = @factura.cliente
        @presupuesto = @factura.presupuesto
      end
      # GET /facturas/new
      def new
       @factura = Factura.new
       @presupuesto = Presupuesto.all
       #@ordenes = Ordene.where(aprobado_por_cliente: 1) 
      end
      # GET /facturas/1/edit
      def edit
      end
      # POST /facturas
      # POST /facturas.json
      def create
        @factura = Factura.new(factura_params)
        respond_to do |format|
          if @factura.save
            format.html  redirect_to @factura, notice: 'Factura was successfully created.' 
            format.json  render :show, status: :created, location: @factura 
          else
            format.html  render :new 
            format.json  render json: @factura.errors, status: :unprocessable_entity 
          end
        end`
      end

      # PATCH/PUT /facturas/1
      # PATCH/PUT /facturas/1.json
      def update
        respond_to do |format|
          if @factura.update(factura_params)
            format.html  redirect_to @factura, notice: 'Factura was successfully updated.' 
            format.json  render :show, status: :ok, location: @factura 
          else
            format.html  render :edit 
            format.json  render json: @factura.errors, status: :unprocessable_entity 
          end
        end
      end

      # DELETE /facturas/1
      # DELETE /facturas/1.json
      def destroy
        @factura.destroy
        respond_to do |format|
          format.html  redirect_to facturas_url, notice: 'Factura was successfully destroyed.' 
          format.json  head :no_content 
        end
      end

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

        # Never trust parameters from the scary internet, only allow the white list through.
        def factura_params
          params.require(:factura).permit(:fecha_de_expedicion, :cliente_id, :presupuesto_id )
        end
    end

错误 /facturas/new 处的 NoMethodError #

的未定义方法“presupuesto_id”
Started GET "/facturas/new" for ::1 at 2015-05-30 21:06:26 -0500
Processing by FacturasController#new as HTML
  Cliente Load (0.2ms)  SELECT "clientes".* FROM "clientes"
  Presupuesto Load (0.1ms)  SELECT "presupuestos".* FROM "presupuestos"
  Rendered facturas/_form.html.erb (21.1ms)
  Rendered facturas/new.html.erb within layouts/application (22.6ms)
Completed 500 Internal Server Error in 29ms

NoMethodError - undefined method `presupuesto_id' for #<Factura:0x007feadf9dc930>:
  activemodel (4.2.0) lib/active_model/attribute_methods.rb:433:in `method_missing'
  actionview (4.2.0) lib/action_view/helpers/tags/base.rb:28:in `value'
  actionview (4.2.0) lib/action_view/helpers/tags/collection_select.rb:16:in `block in render'
  actionview (4.2.0) lib/action_view/helpers/tags/collection_select.rb:16:in `render'
  actionview (4.2.0) lib/action_view/helpers/form_options_helper.rb:202:in `collection_select'
  actionview (4.2.0) lib/action_view/helpers/form_options_helper.rb:789:in `collection_select'
  simple_form (3.1.0) lib/simple_form/inputs/collection_select_input.rb:9:in `input'
  simple_form (3.1.0) lib/simple_form/wrappers/leaf.rb:19:in `render'
  simple_form (3.1.0) lib/simple_form/wrappers/many.rb:28:in `block in render'
  simple_form (3.1.0) lib/simple_form/wrappers/many.rb:26:in `render'
  simple_form (3.1.0) lib/simple_form/wrappers/root.rb:15:in `render'
  simple_form (3.1.0) lib/simple_form/form_builder.rb:115:in `input'
  simple_form (3.1.0) lib/simple_form/form_builder.rb:191:in `association'
  app/views/facturas/_form.html.erb:8:in `block in _app_views_facturas__form_html_erb___1959803079335200881_70323378590380'
  actionview (4.2.0) lib/action_view/helpers/capture_helper.rb:38:in `block in capture'
  actionview (4.2.0) lib/action_view/helpers/capture_helper.rb:200:in `with_output_buffer'
  actionview (4.2.0) lib/action_view/helpers/capture_helper.rb:38:in `capture'
  actionview (4.2.0) lib/action_view/helpers/form_helper.rb:444:in `form_for'
  simple_form (3.1.0) lib/simple_form/action_view_extensions/form_helper.rb:26:in `block in simple_form_for'
  simple_form (3.1.0) lib/simple_form/action_view_extensions/form_helper.rb:45:in `with_simple_form_field_error_proc'
  simple_form (3.1.0) lib/simple_form/action_view_extensions/form_helper.rb:25:in `simple_form_for'
  app/views/facturas/_form.html.erb:4:in `_app_views_facturas__form_html_erb___1959803079335200881_70323378590380'
  actionview (4.2.0) lib/action_view/template.rb:145:in `block in render'
  activesupport (4.2.0) lib/active_support/notifications.rb:166:in `instrument'
  actionview (4.2.0) lib/action_view/template.rb:333:in `instrument'
  actionview (4.2.0) lib/action_view/template.rb:143:in `render'
  actionview (4.2.0) lib/action_view/renderer/partial_renderer.rb:339:in `render_partial'
  actionview (4.2.0) lib/action_view/renderer/partial_renderer.rb:310:in `block in render'
  actionview (4.2.0) lib/action_view/renderer/abstract_renderer.rb:39:in `block in instrument'
  activesupport (4.2.0) lib/active_support/notifications.rb:164:in `block in instrument'
  activesupport (4.2.0) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (4.2.0) lib/active_support/notifications.rb:164:in `instrument'
  actionview (4.2.0) lib/action_view/renderer/abstract_renderer.rb:39:in `instrument'
  actionview (4.2.0) lib/action_view/renderer/partial_renderer.rb:309:in `render'
  actionview (4.2.0) lib/action_view/renderer/renderer.rb:47:in `render_partial'
  actionview (4.2.0) lib/action_view/helpers/rendering_helper.rb:35:in `render'
  app/views/facturas/new.html.erb:3:in `_app_views_facturas_new_html_erb___1900732511694118275_70323400237940'
  actionview (4.2.0) lib/action_view/template.rb:145:in `block in render'
  activesupport (4.2.0) lib/active_support
  :in `instrument'
  actionview (4.2.0) lib/action_view/template.rb:333:in `instrument'
  actionview (4.2.0) lib/action_view/template.rb:143:in `render'
  actionview (4.2.0) lib/action_view/renderer/template_renderer.rb:54:in `block (2 levels) in render_template'
  actionview (4.2.0) lib/action_view/renderer/abstract_renderer.rb:39:in `block in instrument'
  activesupport (4.2.0) lib/active_support/notifications.rb:164:in `block in instrument'
  activesupport (4.2.0) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (4.2.0) lib/active_support/notifications.rb:164:in `instrument'
  actionview (4.2.0) lib/action_view/renderer/abstract_renderer.rb:39:in `instrument'
  actionview (4.2.0) lib/action_view/renderer/template_renderer.rb:53:in `block in render_template'
  actionview (4.2.0) lib/action_view/renderer/template_renderer.rb:61:in `render_with_layout'
  actionview (4.2.0) lib/action_view/renderer/template_renderer.rb:52:in `render_template'
  actionview (4.2.0) lib/action_view/renderer/template_renderer.rb:14:in `render'
  actionview (4.2.0) lib/action_view/renderer/renderer.rb:42:in `render_template'
  actionview (4.2.0) lib/action_view/renderer/renderer.rb:23:in `render'
  actionview (4.2.0) lib/action_view/rendering.rb:100:in `_render_template'
  actionpack (4.2.0) lib/action_controller/metal/streaming.rb:217:in `_render_template'
  actionview (4.2.0) lib/action_view/rendering.rb:83:in `render_to_body'
  actionpack (4.2.0) lib/action_controller/metal/rendering.rb:32:in `render_to_body'
  actionpack (4.2.0) lib/action_controller/metal/renderers.rb:37:in `render_to_body'
  actionpack (4.2.0) lib/abstract_controller/rendering.rb:25:in `render'
  actionpack (4.2.0) lib/action_controller/metal/rendering.rb:16:in `render'
  actionpack (4.2.0) lib/action_controller/metal/instrumentation.rb:41:in `block (2 levels) in render'
  activesupport (4.2.0) lib/active_support/core_ext/benchmark.rb:12:in `block in ms'
  /Users/davefogo/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/benchmark.rb:303:in `realtime'
  activesupport (4.2.0) lib/active_support/core_ext/benchmark.rb:12:in `ms'
  actionpack (4.2.0) lib/action_controller/metal/instrumentation.rb:41:in `block in render'
  actionpack (4.2.0) lib/action_controller/metal/instrumentation.rb:84:in `cleanup_view_runtime'
  activerecord (4.2.0) lib/active_record/railties/controller_runtime.rb:25:in `cleanup_view_runtime'
  actionpack (4.2.0) lib/action_controller/metal/instrumentation.rb:40:in `render'
  action

【问题讨论】:

不清楚你在问什么。在控制器方法中定义的任何实例变量都将在该方法呈现的视图中可用。请发布您正在使用的实际代码以及您收到的任何错误消息的完整文本。 如果您需要其他内容,请告诉我。我真的很困惑如何使代码通过。 【参考方案1】:

您的视图中似乎有一个未定义的方法#presupuesto_id,特别是在 app/views/facturas/_form.html.erb 第 8 行中。这可能需要在控制器底部注释掉所需的参数文件或您试图在错误的对象(@factura)上调用方法(presupuesto_id)。查看两个呈现的视图以查看对象是如何传递的也很有帮助,即_form.html.erb和new.html.erb。

这篇文章很好地解释了控制器/视图的关系以及每个动作中的实例变量的解释。 http://www.sitepoint.com/building-your-first-rails-application-views-and-controllers/

尝试更改表单以查找 presupuesto 的 id 而不是标题。如果可行,那么您需要向 Factura 模型添加一个新方法或范围,该模型将找到名称为“title”的 presupuesto,并将其分配给新创建的 Factura 实例。

        <%= form.association :cliente, :label_method => :nombre,  label: "Cliente", :include_blank => false %>
    <%= form.association :presupuesto, :label_method => :nombre,  label: "Presupuesto", :include_blank => false %>

【讨论】:

以上是关于了解 Rails 控制器 - 通过关联模型的实例变量查看连接的主要内容,如果未能解决你的问题,请参考以下文章

复杂的 Rails 模型/关联

ruby on rails 中的关联

从控制台获取 rails 关联

rails 3中没有模型的控制器的路由

通过 Rails 5 中的另一个模型继承关联

Rails 控制台比较模型实例