복붙노트

[RUBY-ON-RAILS] IN, EMU kontroller

RUBY-ON-RAILS

IN, EMU kontroller

나는 레일 새로운 그리고 난 종류이 디자인 문제와 붙어의 해요, 즉 쉽게 해결 될 수도 있지만 난 아무데도하지 않습니다 하이라이트와 매매 : 나는 광고의 두 가지 종류가 있습니다. 제목, 설명 및 (클립 포함) 하나 개의 이미지 : 둘 다 같은 속성이 있습니다. 인덱스, 새, 편집, 생성, 업데이트 및 파괴 : 그들은 또한 그들에 적용하는 작업 같은 종류가 있습니다.

나는이 같은 STI를 설정합니다 :

광고 모델 : ad.rb

class Ad < ActiveRecord::Base
end

바겐 세일 모델 : bargain.rb

class Bargain < Ad
end

모델을 강조 : highlight.rb를

class Highlight < Ad
end

문제는 나는 단지 하나의 컨트롤러 I는 URL에 따라 할인 또는 강조했다 조치를 실행 (AdsController)가하고 싶은 것입니다, www.foo.com/bargains는 [/ ...] 또는 www.foo 말한다. COM / 하이라이트 [/ ...].

예를 들면 :

내가 어떻게 할 수 있습니까?

감사!

해결법

  1. ==============================

    1.먼저. 새로운 경로를 추가 :

    먼저. 새로운 경로를 추가 :

    resources :highlights, :controller => "ads", :type => "Highlight"
    resources :bargains, :controller => "ads", :type => "Bargain"
    

    그리고 AdsController에서 일부 작업을 수정. 예를 들면 :

    def new
      @ad = Ad.new()
      @ad.type = params[:type]
    end
    

    이 모든 컨트롤러 작업을위한 최선의 방법을 위해이 댓글을 보면

    그게 다야. 지금 당신은 localhost로 갈 수 : 3000 / 하이라이트 / 새로운 새로운 강조는 초기화됩니다.

    인덱스 작업은 다음과 같을 수 있습니다 :

    def index
      @ads = Ad.where(:type => params[:type])
    end
    

    로컬 호스트로 이동 하이라이트 3000 / 하이라이트 및 목록이 나타납니다. 특가 같은 방법 : 로컬 호스트 : 3000 / 할인

    기타

    URL이

    <%= link_to 'index', :highlights %>
    <%= link_to 'new', [:new, :highlight] %>
    <%= link_to 'edit', [:edit, @ad] %>
    <%= link_to 'destroy', @ad, :method => :delete %>
    

    다형성 것에 대한 :)

    <%= link_to 'index', @ad.class %>
    
  2. ==============================

    2.fl00r 그러나 내가 한 조정을 만들 것, 좋은 솔루션을 제공합니다.

    fl00r 그러나 내가 한 조정을 만들 것, 좋은 솔루션을 제공합니다.

    이 수도 있고 귀하의 경우에는 필요하지 않을 수 있습니다. 그것은 행동이 당신의 STI 모델, 특히 검증 및 라이프 사이클 후크의 변화에 ​​따라 달라집니다.

    사용하려는 실제 클래스 상수로 형 PARAM을 변환 컨트롤러에 개인 메서드를 추가합니다

    def ad_type
      params[:type].constantize
    end
    

    위에 그러나 불안하다. 유형의 화이트리스트 추가 :

    def ad_types
      [MyType, MyType2]
    end
    
    def ad_type
      params[:type].constantize if params[:type].in? ad_types
    end
    

    더 레일에 여기에 방법을 constantize : http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize

    그런 다음 컨트롤러 액션에 당신은 할 수 있습니다 :

    def new
      ad_type.new
    end
    
    def create
      ad_type.new(params)
      # ...
    end
    
    def index
      ad_type.all
    end
    

    그리고 지금 당신은 올바른 동작 대신 속성 유형 세트 부모 클래스와 실제 클래스를 사용하고 있습니다.

  3. ==============================

    3.이 모든 주제와 관련된 흥미로운 속임수의 번호가 있기 때문에 난 그냥이 링크를 포함하고 싶었다.

    이 모든 주제와 관련된 흥미로운 속임수의 번호가 있기 때문에 난 그냥이 링크를 포함하고 싶었다.

    알렉스 Reisner - 레일에 단일 테이블 상속

  4. ==============================

    4.나는이에 의해 여기 된 질문 패턴 내가하는 것처럼 @flOOr 및 @Alan_Peabody에서 답을 포함 알고있다. (레일 4.2에서 테스트, 아마 레일 (5)에서 작동)

    나는이에 의해 여기 된 질문 패턴 내가하는 것처럼 @flOOr 및 @Alan_Peabody에서 답을 포함 알고있다. (레일 4.2에서 테스트, 아마 레일 (5)에서 작동)

    모델에서 시작시 허용 목록을 만들 수 있습니다. DEV에서이로드 열망해야합니다.

    class Ad < ActiveRecord::Base
        Rails.application.eager_load! if Rails.env.development?
        TYPE_NAMES = self.subclasses.map(&:name)
        #You can add validation like the answer by @dankohn
    end
    

    이제 우리는의 수집뿐만 아니라, 올바른 범위를 구축 할 수있는 컨트롤러이 허용 된 사이트 목록을 참조 할 수 있습니다 : 타입 등 형태에 선택

    class AdsController < ApplicationController
        before_action :set_ad, :only => [:show, :compare, :edit, :update, :destroy]
    
        def new
            @ad = ad_scope.new
        end
    
        def create
            @ad = ad_scope.new(ad_params)
            #the usual stuff comes next...
        end
    
        private
        def set_ad
            #works as normal but we use our scope to ensure subclass
            @ad = ad_scope.find(params[:id])
        end
    
        #return the scope of a Ad STI subclass based on params[:type] or default to Ad
        def ad_scope
            #This could also be done in some kind of syntax that makes it more like a const.
            @ad_scope ||= params[:type].try(:in?, Ad::TYPE_NAMES) ? params[:type].constantize : Ad
        end
    
        #strong params check works as expected
        def ad_params
            params.require(:ad).permit({:foo})
        end
    end
    

    객체의 유형 : 우리는 라우팅이 실제에도 불구하고, 기본 클래스 컨트롤러에 보낼 수 있어야하기 때문에 우리의 양식을 처리해야합니다. 이 우리를 사용하려면 올바른 경로로 양식 빌더를 속여 "가", 그리고 : 지시어는 기본 클래스로 입력 이름을 강제로뿐만 아니라. 뿐만 아니라 강한 PARAMS가 PARAMS 확인 등 [: 광고] 다시 양식에서 오는 :이 조합은 우리가 수정되지 않은 루트 (광고 자원)을 사용할 수 있습니다.

    #/views/ads/_form.html.erb
    <%= form_for(@ad.becomes(Ad), :as => :ad) do |f| %>
    
  5. ==============================

    5.[완벽하게 작동 간단한 해결책으로 재 작성 :]

    [완벽하게 작동 간단한 해결책으로 재 작성 :]

    다른 답변에 반복, 나는 레일 4.1의 강력한 매개 변수와 함께 잘 작동 단일 테이블 상속 단일 컨트롤러에 대한 다음과 같은 솔루션으로 올라와있다. 그냥 포함 : 잘못된 유형 입력하면 허용 된 매개 변수 유형은 액티브 :: SubclassNotFound 오류가 발생했습니다. SQL 쿼리가 명시 적으로 기존의 유형을 찾습니다 때문에 또한, 유형은 업데이트되지 않습니다. 대신 : 그것은 현재 설정된 것보다 다른 유효한 형식 인 경우 유형은 update_column 별도로 업데이트해야합니다. 나는 모든 유형의 목록까지 건조에 성공했다고도합니다.

    # app/models/company.rb
    class Company < ActiveRecord::Base
      COMPANY_TYPES = %w[Publisher Buyer Printer Agent]
      validates :type, inclusion: { in: COMPANY_TYPES,
        :message => "must be one of: #{COMPANY_TYPES.join(', ')}" }
    end
    
    Company::COMPANY_TYPES.each do |company_type|
      string_to_eval = <<-heredoc
        class #{company_type} < Company
          def self.model_name  # http://stackoverflow.com/a/12762230/1935918
            Company.model_name
          end
        end
      heredoc
      eval(string_to_eval, TOPLEVEL_BINDING)
    end
    

    그리고 컨트롤러 :

      # app/controllers/companies_controller.rb
      def update
        @company = Company.find(params[:id])
    
        # This separate step is required to change Single Table Inheritance types
        new_type = params[:company][:type]
        if new_type != @company.type && Company::COMPANY_TYPES.include?(new_type)
          @company.update_column :type, new_type
        end
    
        @company.update(company_params)
        respond_with(@company)
      end
    

    그리고 경로 :

    # config/routes.rb
    Rails.application.routes.draw do
      resources :companies
      Company::COMPANY_TYPES.each do |company_type|
        resources company_type.underscore.to_sym, type: company_type, controller: 'companies', path: 'companies'
      end
      root 'companies#index'
    

    마지막으로, 응답자의 보석을 사용하고 STI와 호환되는 responders_controller를 사용하는 비계 설정하는 것이 좋습니다. 비계에 대한 설정은 다음과 같습니다

    # config/application.rb
        config.generators do |g|
          g.scaffold_controller "responders_controller"
        end
    
  6. from https://stackoverflow.com/questions/5246767/sti-one-controller by cc-by-sa and MIT license