У меня есть модель Раздела, где Раздел может быть родительским для другого Раздела (подраздела).
Вот моя модель:
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
Родительский идентификатор вводится через скрытое поле в форме:
<%= 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 не определен?
UPDATE:
Теперь работает со следующим кодом контроллера:
@section = Section.new(params[:section])
unless @section.parent_id.empty?
@parent = Section.find(@section.parent_id)
@section.parent = @parent
end
Ищет какие-либо предложения о том, как его можно улучшить, и почему он не работал раньше ...