2014-08-28 5 views
0

편집 : 매우 간단한 오류가 발생하여 더 이상 존재하지 않는 LocalTemplate ID와 연결된 템플릿이 있습니다. 누구나이 문제가 있고 어떻게 든 업데이트 작업에서 다른 모델의 ID를 연결할 수 없다고 생각하면 실수로 상위 개체를 삭제하지 않아야 해당 ID가 더 이상 존재하지 않게됩니다! 극적으로 단순화되었지만 아래 코드는 저에게 효과적이었습니다.Rails NoMethodError 정의되지 않은 메소드 'data'for nil : NilClass (Controller # update)

나는 내 레일 앱에 템플릿 모델이 있습니다. 그것에는 "데이터"라는 메소드가 정의되어 있습니다.

@ template.data를 사용하여 만들기 및 표시 작업에서이 메서드에 액세스 할 수 있지만 내 컨트롤러의 업데이트 작업에서 동일한 @ template.data를 사용할 때 표시하지 않기 때문에 메서드 없음 오류가 발생합니다. 정확한 로컬 템플릿 ID. 이 행은 읽는 모델에서 찾을 수 있습니다 base_data = YAML.load(local_template.data)

처음에 새 템플릿을 저장할 때 관련된 local_template의 ID가 저장되었지만 업데이트 작업에서 해당 ID를 다시 참조하도록하려면 어떻게해야합니까? 방법이 없다는 오류가 발생합니까?

class Template < ActiveRecord::Base 
     def data 
     base_data = YAML.load(local_template.data) 
     # couldn't pass the correct LocalTemplate here because 
     # the local_template_id I had in my Template model no 
     # longer existed. Changing the id to a LocalTemplate 
     # that did exist fixed the issue. 
     end 
    end 

컨트롤러 : @template가

class TemplatesController < ApplicationController 
     def index 
     @business = Business.find(params[:business_id]) 
     @templates = @business.templates.all 
     end 

     def new 
     @business = Business.find(params[:business_id]) 
     @local_templates = LocalTemplate.all 
     @template = @business.templates.build 
     end 

     def create 
     @business = Business.find(params[:business_id]) 
     @local_templates = LocalTemplate.all 
     @template = @business.templates.build(template_params) 

     if @template.save 
      @template.data #works fine here 

      redirect_to business_url(@template.business_id) 
     else 
      render 'new' 
     end 
     end 

     def show 
     @business = Business.find(params[:business_id]) 
     @template = @business.templates.find(params[:id]) 
     @template.data #works fine here too 
     end 

     def edit 
     @business = Business.find(params[:business_id]) 
     @local_templates = LocalTemplate.all 
     @template = @business.templates.find(params[:id]) 
     end 

     def update 
     @business = Business.find(params[:business_id]) 
     @template = @business.templates.find(params[:id]) 

     if @template.update_attributes!(pass_template_params) 

      Api.new.update_template(@template.data.to_json) #this is where I had a problem 

      redirect_to business_url(@template.business_id) 
     else 
      render 'edit' 
     end 
     end 
    end 
+0

'@ template.update_attributes (template_params)'와 '@template.data # 여기에 그것을 사용할 수 없거나 아무런 메소드 오류도 발생하지 않습니다 .'에서 'update_attributes'를 재정의 했습니까? '템플릿'? –

+0

일을 명확히하기 위해 많은 코드를 제거했지만'if @ template.update_attributes (template_params)'후에 @ template.data를 사용해야하는 API 호출을합니다. 나는 그 전화를 보여주지 않을 것이지만 그것이 그것이 갈 것이고 그것이 작동하지 않는 곳이다. – dual88

+0

그 라인은 다음과 같습니다 :'Api.new.update_template (@ template.data)' – dual88

답변

0

많이 혼합하고 있습니다. 귀하의 컨트롤러에 리팩토링하는 사람이 많이 있습니다 ...
먼저 TemplatesController는 템플릿 리소스에 관한 것이어야하지만 컨트롤러는 BusinessesController와 비슷한 모양입니다. 일반적으로 예를 들어, 귀하의 업데이트 작업은 더 좋아 보일 것입니다 : 당신은 전혀 사용하지 않기 때문에

def update 
    @template = Template.find params[:id] 
    @template.attributes = template_params # though this should raise a NoMethodError, because you dind't define it; I'd prefer params[:template] if possible 
    if @template.save 
    redirect_to business_url(@template.business_id) 
    else 
    @local_templates = LocalTemplate.all 
    render 'edit' 
    end 
end 

인스턴스화 @business 및 @local_templates가 아닌 의미가 있습니다. 최대한 빨리 응답하십시오! :)
중첩 된 리소스의 오버 헤드가 (이전처럼) 업데이트 할 필요가 없음을 수정했습니다. 당신의 /templates/edit.html.erb 부분에

@template.business 

: @template을 절약 검증 이유로 실패 할 경우
, 당신은 더 나은에 의해 늦게 비즈니스 오브젝트를로드해야합니다. 그런 다음 편집 작업에 중첩 된 경로가 필요하지 않습니다. 알다시피, 많이 정리됩니다.
일반적인 가이드 라인으로 컨트롤러 인스턴스 변수를 가능한 적게 만들어야합니다.
컨트롤러 및보기를 지운 경우 데이터 문제를 디버깅하는 것이 더 쉬울 것입니다.
나는 가정 당신의 템플릿 모델

local_template 

는 관련 LocalTemplate 모델 객체가 될 수 있습니다.

class Template < ActiveRecord::Base 
    def data 
    return if local_template.nil? 
    YAML.load(local_template.data) 
    end 
end 

을하거나 local_template 객체의 존재를 확인 : 그래서 더 문제는이 보장 어디서나 경우 참조 된 개체가 있는지 문의 없습니다해야한다. 또는 심지어

+0

고마워요. @tobago 내 코드 예제는 극적으로 단순화되어 문제와 관련이 있다고 생각되는 부분만을 보여줍니다. 실제 컨트롤러에는 더 많은 복잡성이 따른다. 템플릿은 비즈니스에 속하며 특정 비즈니스 관점에서 편집됩니다. 당신은 정확하지만 더 이상 존재하지 않는 LocalTemplate에 속한 템플릿을 가지고있는 간단한 실수를했습니다. 새로운 LocalTemplate ID를 부여해야만하고 업데이트 작업이 효과적이었습니다. 고맙습니다! – dual88

0

당신은 @template을 확인해야이 전무되지 않은 경우 다음

이 모델 템플릿 모델과 컨트롤러의 단순화 된 버전입니다 nil, 데이터 메소드를 사용할 수 없습니다.

1.9.3-p547 :024 > nil.data 
NoMethodError: undefined method `data' for nil:NilClass 
from (irb):24 
from /Users/tap4fun/.rvm/rubies/ruby-1.9.3-p547/bin/irb:12:in `<main>' 

그리고 당신은 update_attributes을 사용한다!, 레코드가 유효하지 않은 경우 예외를 발생시킬 수 있습니다.

이렇게 할 수 있습니다.

if @template 
    @template.update_attributes!(template_params) 
    @template.data 
end 
+0

고마워, 나는이 문제가 실제로'base_data = YAML.load (local_template.data) '모델의이 줄 안에 있음을 발견하고 나의 질문을 업데이트했다. 나는 아직도 정확한 해결책을 확신하지 못한다. 나는 update_attributes를 사용할 것이다! 대신에. 그 점을 지적 해 주셔서 감사합니다. – dual88

관련 문제