has_one:through - build_association undefined?

时间:2012-02-12 10:44:31

标签: ruby ruby-on-rails-3

我有一个Section模型,其中Section可以是另一个Section(子部分)的父级。

这是我的模特:

class Section < ActiveRecord::Base
  has_many :exercises

  has_one :parent_link,
    :foreign_key => 'subsection_id',
    :class_name => 'SectionLink',
    :dependent => :destroy

  has_one :parent, :through => :parent_link

  has_many :subsection_links,
    :foreign_key => 'parent_id',
    :class_name => 'SectionLink',
    :dependent => :destroy

  has_many :subsections, :through => :subsection_links

  attr_accessor :parent_id

  def to_param
    "#{id}-#{description.parameterize}"
  end

  def self.search(search)
    if search
      find(:all, :conditions => ['description LIKE ?', "%#{search}%"])
    else
      find(:all)
    end
  end
end

关联模型:

class SectionLink < ActiveRecord::Base
  belongs_to :parent, :class_name => 'Section'
  belongs_to :subsection, :class_name => 'Section'
end

我的控制器:

class SectionsController < ApplicationController
  # GET /sections
  # GET /sections.json
  def index
    @sections = Section.order("subsections_count DESC").search(params[:search])

    respond_to do |format|
      format.html # index.html.erb
    end
  end

  # GET /sections/1
  # GET /sections/1.json
  def show
    @section = Section.find(params[:id])
    @subsections = @section.subsections
    @exercises = @section.exercises

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @section }
    end
  end

  # GET /sections/new
  # GET /sections/new.json
  def new
    @section = Section.new
    @section.parent_id = params[:parent]

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @section }
    end
  end

  # GET /sections/1/edit
  def edit
    @section = Section.find(params[:id])
  end

  # POST /sections
  # POST /sections.json
  def create
    @section = Section.new(params[:section])
    @parent = @section.build_parent(:parent_id => @section.parent_id) unless @section.parent_id.empty?

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

  # PUT /sections/1
  # PUT /sections/1.json
  def update
    @section = Section.find(params[:id])

    respond_to do |format|
      if @section.update_attributes(params[:section])
        format.html { redirect_to @section, notice: 'Section was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @section.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /sections/1
  # DELETE /sections/1.json
  def destroy
    @section = Section.find(params[:id])
    @section.destroy

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

父ID通过隐藏字段输入,格式为:

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

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

  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_field :description %>
  </div>
  <div class="field">
    <%= f.label :body %><br />
    <%= f.text_area :body %>
  </div>
  <%= f.hidden_field :parent_id, :value => @section.parent_id %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

我正在

undefined method 'build_parent' for #<Section:0xb4f1764c>

有没有更好的方法来建模这种关联?为什么build_parent未定义?

更新

现在使用以下控制器代码:

@section = Section.new(params[:section])
unless @section.parent_id.empty?
  @parent = Section.find(@section.parent_id)
  @section.parent = @parent
end

寻找有关如何改进的建议,以及之前为什么不起作用的建议......

1 个答案:

答案 0 :(得分:3)

您正在寻找self join

class Section < ActiveRecord::Base
  has_many :subsections, :class_name => "Section"
  belongs_to :parent_section, :class_name => "Section",
    :foreign_key => "parent_id"
end