2017-01-05 1 views
6

레일즈 앱에서 페이지, 블록, 블록 컨텐츠, 필드 및 필드 내용을 저장합니다.레일스에 동적 필드 저장하기

연관성은 다음과 같습니다

class Page < ActiveRecord::Base 
    has_many :blocks 
    has_many :block_contents, :through => :blocks 
end 

class Block < ActiveRecord::Base 
    belongs_to :page 
    has_many :block_contents 
end 

class BlockContent < ActiveRecord::Base 
    belongs_to :block 
    has_many :field_contents 
end 

class Field < ActiveRecord::Base 
    has_many :field_contents 
end 

class FieldContent < ActiveRecord::Base 
    belongs_to :block_content 
    belongs_to :field 
    validates :content, presence: true 
end 

이 사용 나는 페이지에 대한 동적 필드를 가질 수 있어요. 그러나 DB에 쓰기

현재과 같이 컨트롤러에서 이루어집니다 :이 일을 수행하는 동안

def update 
    @page = Page.find(params[:id]) 
    if params[:field_content].present? 
    params[:field_content].each do |block_content| 
     block_content.last.each do |field| 
     field_content_row = FieldContent.where(block_content_id: block_content.first, field_id: field.first).first 
     if field_content_row.present? 
      field_content_row.update(content: field.last) 
     else 
      field_content = FieldContent.new 
      field_content.block_content_id = block_content.first 
      field_content.field_id = field.first 
      field_content.content = field.last 
      field_content.save 
     end 
     end 
    end 
    end 
    if @page.update_attributes(page_params) 
    redirect_to pages_path 
    else 
    render 'edit' 
    end 
end 

, 그것은 아주 더러운 그리고 그것은 (뷰 내 FieldContent 내 검증을 표시하지 않습니다 유효성 검증은 유효하지 않은 경우 FieldContent를 저장하지 않으므로 작동하지만 전체 페이지가 저장되지 않도록하고 뷰에 표시해야합니다.

FieldContent의 유효성을 표시 할 수 있도록 어떻게 만들 수 있습니까?

<% @page.blocks.each do |block| %> 
    <% block.block_contents.each do |block_content| %> 
     <% field_group.fields.each do |field| %> 
      <input name="field_content[<%= block_content.id %>][<%= field.id %>]" id="field_content_<%= block_content.id %>_<%= field.id %>" type="text" value="<%= get_field_content(block_content, field.name) %>"> 
     <% end %> 
    <% end %> 
<% end %> 

나는 내용 얻기 위해 사용하는 도우미 : 첫째로 당신이 위해 먼저해야 할 일

def get_field_content(block_content, field) 
    content = '' 
    block_content.field_contents.each do |field_content| 
    if field_content.field.name == field && field_content.block_content_id == block_content.id 
     content = field_content.content 
    end 
    end 
    content 
end 
+0

5 년 전 비슷한 앱을 사용했는데 여전히 유용 할 수 있습니다. 다른 부분을 확인해도 되겠지만 컨트롤러를 통합 한 컨트롤러로 [관련 티끌은 여기에 있습니다] (https://github.com/coreyward/talent-releases/blob/master/app/concerns/response_form.rb) 여기를 클릭하십시오. ] (https : // github.co.kr/coreyward/talent-releases/blob/master/app/controllers/releases_controller.rb # L149-L153). – coreyward

+0

@coreyward 흥미로워 보이지만 Ruby와 Rails에 새로운 점이 있습니다. 코드가하는 것에 대한 자세한 설명을 제공 할 수 있습니까? 두 모델에서 동시에 저장이 이루어 지도록 내 모델이 연관되어 있다고 생각합니까? – Cameron

+0

@coreyward보기가 어떻게 보이는지 보여주기 위해 내 게시물을 업데이트했습니다. – Cameron

답변

2

를보기를보고 싶어하는 사람들을 위해


여러 모델을 포함하는 양식 제출은 중첩 된 속성을 허용하는 것입니다. 당신의 page.rb 파일에서

넣어 :

class Page < ActiveRecord::Base 
has_many :blocks 
has_many :block_contents, :through => :blocks 
accepts_nested_attributes_for :field_contents 

을 두 번째로보기에 - 당신은 form_for @page 내부 그래서 'fields_for', 당신은 놓아야 사용하는 모델에있는 필드를 지정해야합니다

<%= f.fields_for :field_contents do |b| %> 

이후 : field_contents는 @page와 함께 업데이트되는 유일한 개체입니다. 그것의 전체 양식 요소는 다음과 같습니다 있도록 : 난 당신이 page.field_content @ 액세스 이미 수 배운 이후로는 자동으로 기록을 갱신으로

<% @page.blocks.each do |block| %> 
    <% block.block_contents.each do |block_content| %> 
     <% field_group.fields.each do |field| %> 
      <%= form_for @page do |f| %> 
       <%= f.input :any attribute %> 
        <%= f.fields_for :field_contents do |b| %> 
         <%= b.text_field :content %> 
          <%= f.fields_for :block_contents do |b| %> 
           <%= b.hidden_field :block_content, value: "#{@block_content.id}"%> 
        <% end %> 
       <% end %> 
      <% end %> 
     <% end %> 
    <% end %> 
<% end %> 

, 당신은 컨트롤러에 아무것도 만지지 필요가 없습니다 기존 관계를 기반으로

이제 모든 모델을 단일 요청으로 제출 했으므로 유효성 검사가 완료된 후 오류 메시지가보기 내에 표시되도록 지정했습니다. 그리고 이것은 쉬운 부분입니다.

내가 볼 수 있듯이 현재 :content의 존재를 확인 중입니다. 보기에

은 : 단순히 HTML 태그 또는 레일 내용 태그

<p class= "error"><%= "Your error message"if @field_content.errors[:content].present? %></p> 

당신이 추가 질문이 있으면 알려주세요 넣어.

+0

나는보기 부분을 따라 가지 않을 것입니다. 필드를 작성하는 방법을 보여주기 위해 예제를 확장 할 수 있습니까? 감사. – Cameron

+0

내 대답을 – Crashtor

+0

업데이트'@ blocks '은 어디에서 왔습니까? 컨트롤러에있는 유일한 변수는'@ page '입니다. '@ page.blocks.build'는'@ blocks'을 생성합니까? 또한 컨트롤러의 FieldContents 및 BlockContents에 대한 작업을 수행해야합니까? – Cameron