2010-03-12 3 views
5

레일에 3 레벨 다중 중첩 양식이 있습니다. 설정은 다음과 같습니다. 프로젝트에는 많은 마일스톤이 있고 마일스톤에는 많은 노트가 있습니다. 목표는 자바 스크립트로 페이지 내의 모든 것을 편집 할 수있는 것입니다. 여기에서 페이지 내 프로젝트에 여러 개의 새로운 마일스톤을 추가 할 수 있으며 새 노트와 기존 마일스톤을 추가 할 수 있습니다. 나는 실제로 필드를 편집하지 않는 한 예상대로 내가 (그들에게 메모를 추가 할 때 새로운 이정표가 잘 작동)을 기존 마일스톤에 새 메모를 추가 할 때다중 레벨 중첩 된 양식을 Rails에서 "더티 (dirty)"로 표시

모든 것을 제외 작품, 새로운 메모를 저장하지 않습니다 "더러운"/ 편집 된 양식을 표시하는 중요 시점에 속합니다.

마일스톤을 플래그하여 추가 된 새 노트가 저장되도록하는 방법이 있습니까?

편집 : 거기에 너무 많은 부분이, 그러나 여기 간다 때문에 죄송합니다,이 모든 코드에 붙여 어렵다 :

모델

class Project < ActiveRecord::Base 
    has_many :notes, :dependent => :destroy 
    has_many :milestones, :dependent => :destroy 

    accepts_nested_attributes_for :milestones, :allow_destroy => true 
    accepts_nested_attributes_for :notes, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } 
end 

class Milestone < ActiveRecord::Base 
    belongs_to :project 
    has_many :notes, :dependent => :destroy 

    accepts_nested_attributes_for :notes, :allow_destroy => true, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } 
end 

class Note < ActiveRecord::Base 
    belongs_to :milestone 
    belongs_to :project 

    scope :newest, lambda { |*args| order('created_at DESC').limit(*args.first || 3) } 
end 

내가 jQuery를 기반으로 사용하고, Ryan Bates의 콤보 헬퍼/JS 코드의 눈에 잘 띄지 않는 버전.

def add_fields_for_association(f, association, partial) 
    new_object = f.object.class.reflect_on_association(association).klass.new 
    fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder| 
    render(partial, :f => builder) 
    end 
end 

응용 프로그램 도우미 나는 숨겨진 사업부에서 협회의 양식을 렌더링하고 그것을 발견하고 필요에 따라 추가하려면 다음 자바 스크립트를 사용합니다.

자바 스크립트 나는이 NotesController의 방법을 만들 것 내가 생각할 수있는 코드의 유일한 기타 관련 부분을 추측하고있어

function addFields(link, association, content, func) { 
    var newID = new Date().getTime(); 
    var regexp = new RegExp("new_" + association, "g"); 
    var form = content.replace(regexp, newID); 
    var link = $(link).parent().next().before(form).prev(); 
    if (func) { 
     func.call(); 
    } 
    return link; 
} 

:

def create 
    respond_with(@note = @owner.notes.create(params[:note])) do |format| 
    format.js { render :json => @owner.notes.newest(3).all.to_json } 
    format.html { redirect_to((@milestone ? [@project, @milestone, @note] : [@project, @note]), :notice => 'Note was successfully created.') } 
    end 
end 

@owner의 바르 필터 전에 다음과 같이 생성됩니다.

def load_milestone 
    @milestone = @project.milestones.find(params[:milestone_id]) if params[:milestone_id] 
end 

def determine_owner 
    @owner = load_milestone || @project 
end 

기존 마일스톤에 새 노트를 추가하는 경우를 제외하고는 모든 작업이 정상적으로 작동하는 것 같습니다. 새로운 메모를 저장하려면 이정표를 "손댈"수 있어야합니다. 그렇지 않으면 Rails가주의를 기울이지 않게됩니다.

+0

마일스톤 'accept_nested_attributes_for : notes'? 또한 일부 코드가 도움이 될 수 있습니다. – Anurag

+0

위 코드가 추가되었습니다! :) – simplesessions

답변

2

이 레일 2.3.5에서 bug #4242이며이에 fixed을하고있다 : 여기에 새로운 정보를 기반으로 나를 위해 일한 코드는 Rails 2.3.8.

+0

정말 고마워요! 몇 달 간의 고뇌 끝에 너는 나에게 대답을 주었다. 나는 아무도 내가 무슨 말을하고 있는지 알지 못해서 내가 미쳤다고 생각했다. – simplesessions

0

귀하의 모델이 잘못되었다고 생각합니다. 메모에 직접 프로젝트와의 관계가 없습니다. 그들은 이정표를 통해 있습니다.

class Project < ActiveRecord::Base 
    has_many :milestones, :dependent => :destroy 
    has_many :notes, :through => :milestones 
    accepts_nested_attr ibutes_for :milestones, :allow_destroy => true 
end 

class Milestone < ActiveRecord::Base 
    belongs_to :project 
    has_many :notes, :dependent => :destroy 

    accepts_nested_attributes_for :notes, :allow_destroy => true, :reject_if => proc { |attributes| attributes['content'].blank? } 
end 

class Note < ActiveRecord::Base 
    belongs_to :milestone 
end 

업데이트를 시도 :

## project controller 

# PUT /projects/1 
def update 
    @project = Project.find(params[:id]) 

    if @project.update_attributes(params[:project]) 
    redirect_to(@project) 
    else 
    render :action => "edit" 
    end 
end 

# GET /projects/1/edit 
def edit 
    @project = Project.find(params[:id]) 
    @project.milestones.build 
    for m in @project.milestones 
    m.notes.build 
    end 
    @project.notes.build 
end 

## edit.html.erb 
<% form_for(@project) do |f| %> 
    <%= f.error_messages %> 

    <p> 
    <%= f.label :name %><br /> 
    <%= f.text_field :name %> 
    </p> 
    <% f.fields_for :notes do |n| %> 
     <p> 
     <div> 
      <%= n.label :content, 'Project Notes:' %> 
      <%= n.text_area :content, :rows => 3 %> 
     </div> 
     </p> 
    <% end %> 
    <% f.fields_for :milestones do |m| %> 
     <p> 
     <div> 
      <%= m.label :name, 'Milestone:' %> 
      <%= m.text_field :name %> 
     </div> 
     </p> 
     <% m.fields_for :notes do |n| %> 
      <p> 
      <div> 
       <%= n.label :content, 'Milestone Notes:' %> 
       <%= n.text_area :content, :rows => 3 %> 
      </div> 
      </p> 
     <% end %> 
    <% end %> 
    <p> 
    <%= f.submit 'Update' %> 
    </p> 
<% end %> 
+0

아니, 맞아. 프로젝트는 자신의 노트도 가질 수 있습니다.그래도 조언 주셔서 감사합니다! 모든 것이 계획대로 작동합니다. 필자는 프로젝트 마일스톤 자체에 영향을 미치지는 않았지만 Rails에게 저장시 프로젝트 이정표 노트 (* 기존 마일스톤의 일부로)를 저장하는 방법을 알고 싶었습니다. 이정표에있는 필드를 편집하지 않는 한, 새로운 프로젝트 일지라도 이정표의 노트를 무시하는 것처럼 보입니다. – simplesessions

+0

미안하지만, 원래 노트가 프로젝트에도 속할 수 있다고 언급하지 않았다는 것을 깨달았습니다. – simplesessions

+0

업데이트 해 주셔서 감사합니다! 그래도 여전히 효과가 없습니다. 위의 Javascript는 양식에 새로운 메모를 동적으로 추가하고 현재 시간을 기준으로 ID를 부여합니다. 그러나 업데이트 작업과 같은 일반 양식은 훌륭하게 작동하지만 새로 만든 메모는 내가 이정표를 편집 할 때만 작동합니다. – simplesessions

관련 문제