[RUBY-ON-RAILS] STI는 레일에 서브 클래스에 대한 모범 사례 경로를 처리하는
RUBY-ON-RAILSSTI는 레일에 서브 클래스에 대한 모범 사례 경로를 처리하는
내 레일 뷰와 컨트롤러는 redirect_to, LINK_TO 및 form_for 메소드 호출에 산재 해있다. 때로는 LINK_TO와 redirect_to은 (예를 들어, LINK_TO '새 사람', new_person_path)를 연결하고있는 경로의 명시 적 있지만, 여러 번 경로 (예를 들어 LINK_TO '쇼', 사람을) 암시 적이다.
내 모델에 약간의 단일 테이블 상속 (STI)를 추가 (예를 들어 직원 <사람),이 모든 메소드는 서브 클래스의 인스턴스에 대한 중단 (직원을 말한다) <: 0x000001022bcd40> 0x0000010226d038 #의
이 질문은 전에 물어되었습니다
가장 우아한 보인다 가장 공감대가 있습니다 (하지만이 모든 우아하고도 그 정도 합의 아니다) 대답 그래서, 당신의 routes.rb에 리소스를 추가합니다. 이 form_for에 대한 작업을하지 않는 경우를 제외하고. 좀 선명도를 필요로한다! 위의 선택을 증류하기 위해, 내 옵션은
이러한 모든 충돌과 답변, 나는 판결을해야합니다. 좋은 답변이없는 것처럼 날 것으로 보인다. 이것을 레일의 설계에 실패? 그렇다면, 그것은 고정받을 수 있음 버그? 하지 않을 경우 또는, 나는이 희망하고있는 사람이 똑바로 나를 설정 각 옵션의 장단점을 통해서 나를 걸어 (또는 그 옵션이 아닌 이유를 설명), 그리고 어느 쪽이 정답, 그리고 왜 할 수 있습니다. 아니면 웹에서 찾는 게 아니에요하는 정답이있다?
해결법
-
==============================
1.이것은 내가 최소한의 부작용으로 가지고 올 수 있었던 가장 간단한 솔루션입니다.
이것은 내가 최소한의 부작용으로 가지고 올 수 있었던 가장 간단한 솔루션입니다.
class Person < Contact def self.model_name Contact.model_name end end
예상대로 이제 url_for @person는 contact_path에 매핑합니다.
그것이 작동하는 방법 : URL 헬퍼는 모델에 반영하기 위해 YourModel.model_name에 의존 (많은 것들 사이에) 단수 / 복수의 루트 키를 생성합니다. 여기 사람은 기본적으로 내가 물어 바로 연락 친구처럼 해요 말하고있다.
-
==============================
2.저도 같은 문제가 있었다. STI를 사용 후, form_for 방법은 잘못된 자식 URL에 게시했다.
저도 같은 문제가 있었다. STI를 사용 후, form_for 방법은 잘못된 자식 URL에 게시했다.
NoMethodError (undefined method `building_url' for
나는 자식 클래스에 대한 별도의 경로에 추가하고 같은 컨트롤러를 가리키는 결국
resources :structures resources :buildings, :controller => 'structures' resources :bridges, :controller => 'structures'
또한 :
<% form_for(@structure, :as => :structure) do |f| %>
이 경우 구조 건물은 실제로 (자식 클래스)
그것은이 form_for와 함께 제출 수행 한 후 나를 위해 작동하는 것 같다.
-
==============================
3."form_for"사용할 수 있도록 할 것이다이 방법을 사용하여, https://stackoverflow.com/a/605172/445908 : 나는 당신을 살펴 보시기 바랍니다.
"form_for"사용할 수 있도록 할 것이다이 방법을 사용하여, https://stackoverflow.com/a/605172/445908 : 나는 당신을 살펴 보시기 바랍니다.
ActiveRecord::Base#becomes
-
==============================
4.경로의 유형을 사용합니다 :
경로의 유형을 사용합니다 :
resources :employee, controller: 'person', type: 'Employee'
http://samurails.com/tutorial/single-table-inheritance-with-rails-4-part-2/
-
==============================
5.@Prathan Thananart의 아이디어에 따라 아무것도 파괴하지하려고합니다. (이 때문에 많은 마법 관련된 있도록)
@Prathan Thananart의 아이디어에 따라 아무것도 파괴하지하려고합니다. (이 때문에 많은 마법 관련된 있도록)
class Person < Contact model_name.class_eval do def route_key "contacts" end def singular_route_key superclass.model_name.singular_route_key end end end
예상대로 이제 url_for @person는 contact_path에 매핑합니다.
-
==============================
6.나도이 문제에 문제가 및 우리와 비슷한 질문에 대한이 답변으로 온되었다. 그것은 나를 위해 일했습니다.
나도이 문제에 문제가 및 우리와 비슷한 질문에 대한이 답변으로 온되었다. 그것은 나를 위해 일했습니다.
form_for @list.becomes(List)
여기에 표시된 답변 : 같은 컨트롤러와 STI 경로를 사용
주로 당신의 form_for처럼 STI 문제를 해결하기 위해 사용 된 .becomes 방법을 정의한다.
여기에 정보를 .becomes : http://apidock.com/rails/ActiveRecord/Base/becomes
슈퍼 늦게 반응은, 그러나 이것은 내가 찾을 수있는 가장 좋은 대답과 나를 위해 잘 작동. 이것은 어떤 사람을 도움이되기를 바랍니다. 건배!
-
==============================
7.좋아, 필자는 아마도이 다른 사람을 도움이 될 것입니다, 레일의이 지역에서 좌절의 톤을 가지고, 다음과 같은 접근 방식에 도착했습니다.
좋아, 필자는 아마도이 다른 사람을 도움이 될 것입니다, 레일의이 지역에서 좌절의 톤을 가지고, 다음과 같은 접근 방식에 도착했습니다.
우선 위의 그물의 주위에 다수의 솔루션은 클라이언트가 제공 매개 변수에 대한 constantize를 사용하는 것이 좋습니다 것을 유의하십시오. 루비 따라서 공격자가 임의의 문자를 생성하고 사용 가능한 메모리를 소비 할 수없는 쓰레기 수집 문자처럼 이것은 알려진 DoS 공격 벡터이다.
나는 모델 서브 클래스의 인스턴스를 지원하며, 위의 contantize 문제로부터 안전하다 아래의 방법을 구현했습니다. 그것은 4 않습니다 레일 것과 매우 유사하지만 (레일 4와 달리) 서브 클래스와 레일 3 작품 중 하나 개 이상의 수준을 수 있습니다.
# initializers/acts_as_castable.rb module ActsAsCastable extend ActiveSupport::Concern module ClassMethods def new_with_cast(*args, &block) if (attrs = args.first).is_a?(Hash) if klass = descendant_class_from_attrs(attrs) return klass.new(*args, &block) end end new_without_cast(*args, &block) end def descendant_class_from_attrs(attrs) subclass_name = attrs.with_indifferent_access[inheritance_column] return nil if subclass_name.blank? || subclass_name == self.name unless subclass = descendants.detect { |sub| sub.name == subclass_name } raise ActiveRecord::SubclassNotFound.new("Invalid single-table inheritance type: #{subclass_name} is not a subclass of #{name}") end subclass end def acts_as_castable class << self alias_method_chain :new, :cast end end end end ActiveRecord::Base.send(:include, ActsAsCastable)
무슨 유사 많은 위에 제시 한 '으로 개발되어 문제의 sublclass로드'에 대한 다양한 접근을 시도 후, 나는 확실하게 일을 내 모델 클래스에 'require_dependency'를 사용했다 유일한을 발견했다. 이 것을 보장 클래스 로딩 개발에서 제대로 작동하고 생산에 아무런 문제가 발생하지 않습니다. 개발없이 'require_dependency'AR은 SQL이 유형 열에 일치에 방출 영향 모든 서브 클래스에 대해 알고 실 거예요. 'require_dependency'없이 또한 당신은 또한 같은 시간에 모델 클래스의 여러 버전이있는 상황에서 끝낼 수 있습니다! (예. 당신이 기본 또는 중간 클래스를 변경할 때 이런 일이 수, 하위 클래스는 항상 다시로드하는 것하고 기존 클래스의 왼쪽 서브 클래스입니다하지 않습니다)
# contact.rb class Contact < ActiveRecord::Base acts_as_castable end require_dependency 'person' require_dependency 'organisation'
위의 제안 또한 MODEL_NAME를 오버라이드 (override)하지 않는 내가 국제화를 사용하고 다른 서브 클래스의 속성, 예를 들어 다른 문자열을 필요로하기 때문에 : tax_identifier는 조직에 대한 'ABN'와 (호주에서) 사람에 대한 'TFN'을하게합니다.
위의 제안 또한 유형을 설정, 경로 매핑을 사용 :
resources :person, :controller => 'contacts', :defaults => { 'contact' => { 'type' => Person.sti_name } } resources :organisation, :controller => 'contacts', :defaults => { 'contact' => { 'type' => Organisation.sti_name } }
경로 매핑뿐만 아니라, 나는 InheritedResources 및 SimpleForm을 사용하고 있는데 나는 새로운 행동에 대한 다음과 같은 일반적인 형태의 래퍼를 사용합니다 :
simple_form_for resource, as: resource_request_name, url: collection_url, html: { class: controller_name, multipart: true }
... 편집 작업을 위해 :
simple_form_for resource, as: resource_request_name, url: resource_url, html: { class: controller_name, multipart: true }
그리고이 작품을 만들기 위해, 내베이스 ResourceContoller 나는 뷰의 도우미 방법으로 InheritedResource의 resource_request_name 노출 :
helper_method :resource_request_name
당신이 InheritedResources을 사용하지 않는 경우, 다음 'ResourceController'에 다음과 같은 것을 사용 :
# controllers/resource_controller.rb class ResourceController < ApplicationController protected helper_method :resource helper_method :resource_url helper_method :collection_url helper_method :resource_request_name def resource @model end def resource_url polymorphic_path(@model) end def collection_url polymorphic_path(Model) end def resource_request_name ActiveModel::Naming.param_key(Model) end end
다른 사람의 경험과 개선을 듣고 항상 행복.
-
==============================
8.나는 최근에 레일 3.0 응용 프로그램에서 안정적인 STI 패턴 작업을 얻을 나의 시도를 문서화. 여기서 TL이다; DR 버전 :
나는 최근에 레일 3.0 응용 프로그램에서 안정적인 STI 패턴 작업을 얻을 나의 시도를 문서화. 여기서 TL이다; DR 버전 :
# app/controllers/kase_controller.rb class KasesController < ApplicationController def new setup_sti_model # ... end def create setup_sti_model # ... end private def setup_sti_model # This lets us set the "type" attribute from forms and querystrings model = nil if !params[:kase].blank? and !params[:kase][:type].blank? model = params[:kase].delete(:type).constantize.to_s end @kase = Kase.new(params[:kase]) @kase.type = model end end # app/models/kase.rb class Kase < ActiveRecord::Base # This solves the `undefined method alpha_kase_path` errors def self.inherited(child) child.instance_eval do def model_name Kase.model_name end end super end end # app/models/alpha_kase.rb # Splitting out the subclasses into separate files solves # the `uninitialize constant AlphaKase` errors class AlphaKase < Kase; end # app/models/beta_kase.rb class BetaKase < Kase; end # config/initializers/preload_sti_models.rb if Rails.env.development? # This ensures that `Kase.subclasses` is populated correctly %w[kase alpha_kase beta_kase].each do |c| require_dependency File.join("app","models","#{c}.rb") end end
이 방법을 사용하면 다른 사람이 STI와 접근 방법 한 것을 다른 문제의 숫자뿐만 아니라 나열하는 문제를 중심으로 가져옵니다.
-
==============================
9.당신이 더 중첩 된 경로가있는 경우,이 시도 할 수 있습니다 :
당신이 더 중첩 된 경로가있는 경우,이 시도 할 수 있습니다 :
resources :employee, path: :person, controller: :person
또는 당신은 다른 방법을 가서 여기에 설명 된 것처럼 일부 OOP-마법을 사용할 수 있습니다 https://coderwall.com/p/yijmuq
두 번째 방법에서는 모든 중첩 모델과 유사한 헬퍼를 만들 수 있습니다.
-
==============================
10.여기가 형태로 우리가 사용하는 응용 프로그램 전반에 걸쳐 작동해야하는 안전하고 깨끗 방법입니다.
여기가 형태로 우리가 사용하는 응용 프로그램 전반에 걸쳐 작동해야하는 안전하고 깨끗 방법입니다.
resources :districts resources :district_counties, controller: 'districts', type: 'County' resources :district_cities, controller: 'districts', type: 'City'
그럼 난 내 양식에 있습니다. : 지역 : 이것에 대한 추가 부분은 그대로.
= form_for(@district, as: :district, html: { class: "form-horizontal", role: "form" }) do |f|
도움이 되었기를 바랍니다.
-
==============================
11.나는이 같은 STI 상속을 고려하는 경우 :
나는이 같은 STI 상속을 고려하는 경우 :
class AModel < ActiveRecord::Base ; end class BModel < AModel ; end class CModel < AModel ; end class DModel < AModel ; end class EModel < AModel ; end
'응용 프로그램 / 모델 / a_model.rb'에 내가 추가 :
module ManagedAtAModelLevel def model_name AModel.model_name end end
그리고 다음 AModel 클래스 :
class AModel < ActiveRecord::Base def self.instanciate_STI managed_deps = { :b_model => true, :c_model => true, :d_model => true, :e_model => true } managed_deps.each do |dep, managed| require_dependency dep.to_s klass = dep.to_s.camelize.constantize # Inject behavior to be managed at AModel level for classes I chose klass.send(:extend, ManagedAtAModelLevel) if managed end end instanciate_STI end
따라서 난 쉽게 내가 기본 하나를 사용하고자하는 모델을 선택하고,이 경우에도 하위 클래스 정의를 건드리지 않고 있습니다. 매우 건조.
-
==============================
12.이 방법은 나를 위해 확인 작업 (기본 클래스에서이 메소드를 정의) :
이 방법은 나를 위해 확인 작업 (기본 클래스에서이 메소드를 정의) :
def self.inherited(child) child.instance_eval do alias :original_model_name :model_name def model_name Task::Base.model_name end end super end
-
==============================
13.당신은 반환 목적을 그라우팅에 대한 부모 개체를 더미 있다는 방법을 만들 수 있습니다
당신은 반환 목적을 그라우팅에 대한 부모 개체를 더미 있다는 방법을 만들 수 있습니다
class Person < ActiveRecord::Base def routing_object Person.new(id: id) end end
다음 단순히 form_for @ employee.routing_object 전화 유형이없는 이는 Person 클래스의 객체를 반환합니다
-
==============================
14.하여 상위 모델에 다음 prathan-thananart 대답 @ 다음, 그리고 여러 STI 클래스에 대한, 당신은 추가 할 수 있습니다 ->
하여 상위 모델에 다음 prathan-thananart 대답 @ 다음, 그리고 여러 STI 클래스에 대한, 당신은 추가 할 수 있습니다 ->
class Contact < ActiveRecord::Base def self.model_name ActiveModel::Name.new(self, nil, 'Contact') end end
[: 접촉] 대신 PARAMS [: contact_person, PARAMS [: contact_whatever 즉 연락처 데이터와 각 양식은 PARAMS으로 PARAMS를 보내도록 할 것입니다.
-
==============================
15.hackish 솔루션의 목록에 있지만, 또 다른 하나.
hackish 솔루션의 목록에 있지만, 또 다른 하나.
class Parent < ActiveRecord::Base; end Class Child < Parent def class Parent end end
레일 2.x 및 3.x에 작품
from https://stackoverflow.com/questions/4507149/best-practices-to-handle-routes-for-sti-subclasses-in-rails by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 어떻게 S3에 데이터를 저장하고 레일 API / 아이폰 OS 클라이언트와의 보안 방법으로 사용자 액세스를 허용하려면? (0) | 2020.02.21 |
---|---|
[RUBY-ON-RAILS] 3.1 및 이미지 자산 레일 (0) | 2020.02.21 |
[RUBY-ON-RAILS] 하나의 마이그레이션 파일을 실행 (0) | 2020.02.21 |
[RUBY-ON-RAILS] 레일 국제화 검증 중단 경고 (0) | 2020.02.21 |
[RUBY-ON-RAILS] MySQL은 액티브를 사용하여 DISTINCT ON을 사용하는 방법 (0) | 2020.02.21 |