[RUBY-ON-RAILS] accepts_nested_attributes_for find_or_create와?
RUBY-ON-RAILSaccepts_nested_attributes_for find_or_create와?
나는 큰 성공과 방법 accepts_nested_attributes_for '레일을 사용하고 있지만 내가 어떻게 기록이 이미 존재하는 경우는 새 레코드를 생성 할 수 있을까요?
예로서 :
말 나는 세 가지 모델, 팀, 회원, 그리고 플레이어를 가지고,과 구성원을 통해 각 팀 has_many 플레이어, 선수들이 많은 팀에 속할 수 있습니다했습니다. 팀 모델은 플레이어 중첩 된 속성을 허용하지만 수도가 결합 된 팀 + 플레이어를 통해 제출 된 각 선수가 (들) 형태는 새로운 선수 레코드로 생성된다는 것을 의미합니다.
어떻게 이미 같은 이름을 가진 플레이어가없는 경우 난 단지 새로운 플레이어가이 방법을 기록 만들려면 일을 가야 하는가? 같은 이름을 가진 선수가 있다면, 새로운 선수의 기록은 생성되지해야하지만, 대신에 올바른 플레이어는 발견되어야하고 새로운 팀 기록과 관련.
해결법
-
==============================
1.당신이 자동 저장 협회의 훅을 정의 할 때, 일반적인 코드 경로는 생략하고 당신의 방법 대신이라고합니다. 따라서, 당신은이 작업을 수행 할 수 있습니다 :
당신이 자동 저장 협회의 훅을 정의 할 때, 일반적인 코드 경로는 생략하고 당신의 방법 대신이라고합니다. 따라서, 당신은이 작업을 수행 할 수 있습니다 :
class Post < ActiveRecord::Base belongs_to :author, :autosave => true accepts_nested_attributes_for :author # If you need to validate the associated record, you can add a method like this: # validate_associated_record_for_author def autosave_associated_records_for_author # Find or create the author by name if new_author = Author.find_by_name(author.name) self.author = new_author else self.author.save! end end end
이 코드는 테스트되지 않은,하지만 꽤 많이 당신이 필요로해야한다.
-
==============================
2.팀에 선수를 추가로 생각하지 마십시오, 팀 구성원을 추가로 생각합니다. 양식은 직접 플레이어 작동하지 않습니다. 회원 모델은 PLAYER_NAME 가상 속성을 가질 수 있습니다. 무대 뒤에서이 두 선수를 조회하거나 만들 수 있습니다.
팀에 선수를 추가로 생각하지 마십시오, 팀 구성원을 추가로 생각합니다. 양식은 직접 플레이어 작동하지 않습니다. 회원 모델은 PLAYER_NAME 가상 속성을 가질 수 있습니다. 무대 뒤에서이 두 선수를 조회하거나 만들 수 있습니다.
class Membership < ActiveRecord::Base def player_name player && player.name end def player_name=(name) self.player = Player.find_or_create_by_name(name) unless name.blank? end end
그리고 그냥 회원 양식 빌더에 PLAYER_NAME 선수의 텍스트 필드를 추가합니다.
<%= f.text_field :player_name %>
이 방법은 accepts_nested_attributes_for하는 특정하지 않고 모든 회원 형태로 사용할 수 있습니다.
참고 : 유효성 검사가 발생하기 전에이 기술을 플레이어 모델이 생성됩니다. 이 효과를 원하지 않는 경우, 인스턴스 변수에 플레이어를 저장 한 다음 before_save 콜백에 저장.
-
==============================
3.사용하는 경우 : 기존 레코드의 ID를 제출, accepts_nested_attributes_for하는 액티브 대신 새 레코드를 만드는 기존의 기록을 갱신하게됩니다. 나는 확실하지 마크 업이 비슷하지만이 같은 대략 뭔가를하려고 무엇을 해요 :
사용하는 경우 : 기존 레코드의 ID를 제출, accepts_nested_attributes_for하는 액티브 대신 새 레코드를 만드는 기존의 기록을 갱신하게됩니다. 나는 확실하지 마크 업이 비슷하지만이 같은 대략 뭔가를하려고 무엇을 해요 :
<%= text_field_tag "team[player][name]", current_player.name %> <%= hidden_field_tag "team[player][id]", current_player.id if current_player %>
플레이어 이름은 ID가 공급되면 업데이트하지만, 그 생성됩니다.
autosave_associated_record_for_ 방법을 정의하는 방식은 매우 흥미 롭다. 나는 확실히를 사용합니다! 그러나이 간단한 해결책을 고려뿐만 아니라.
-
==============================
4.그냥 질문의 관점에서 라운드 것 밖으로에 프랑소와 '대답 블록으로 다시 표현 될 수 있다면, (find_or_create을 의미) :
그냥 질문의 관점에서 라운드 것 밖으로에 프랑소와 '대답 블록으로 다시 표현 될 수 있다면, (find_or_create을 의미) :
self.author = Author.find_or_create_by_name(author.name) unless author.name.blank? self.author.save!
-
==============================
5.당신이 has_one이나 관계 belongs_to이있는 경우이 잘 작동합니다. 하지만 통해 has_many 또는 has_many으로 부족했다.
당신이 has_one이나 관계 belongs_to이있는 경우이 잘 작동합니다. 하지만 통해 has_many 또는 has_many으로 부족했다.
관계를 통해 : 나는 has_many을 사용하는 태그 시스템을 가지고있다. 내가 다른 사람을 도울 수있는 솔루션을 함께했다, 그래서 갈 필요가 어디에 둘 솔루션의 날 여기 없어. 이 레일 3.2에서 테스트되었습니다.
여기 내 모델의 기본 버전은 다음과 같습니다 :
위치 개체 :
class Location < ActiveRecord::Base has_many :city_taggables, :as => :city_taggable, :dependent => :destroy has_many :city_tags, :through => :city_taggables accepts_nested_attributes_for :city_tags, :reject_if => :all_blank, allow_destroy: true end
태그 객체
class CityTaggable < ActiveRecord::Base belongs_to :city_tag belongs_to :city_taggable, :polymorphic => true end class CityTag < ActiveRecord::Base has_many :city_taggables, :dependent => :destroy has_many :ads, :through => :city_taggables end
다음과 같이 나는 실제로 autosave_associated_recored_for 메소드를 오버라이드 (override) 않았다 :
class Location < ActiveRecord::Base private def autosave_associated_records_for_city_tags tags =[] #For Each Tag city_tags.each do |tag| #Destroy Tag if set to _destroy if tag._destroy #remove tag from object don't destroy the tag self.city_tags.delete(tag) next end #Check if the tag we are saving is new (no ID passed) if tag.new_record? #Find existing tag or use new tag if not found tag = CityTag.find_by_label(tag.label) || CityTag.create(label: tag.label) else #If tag being saved has an ID then it exists we want to see if the label has changed #We find the record and compare explicitly, this saves us when we are removing tags. existing = CityTag.find_by_id(tag.id) if existing #Tag labels are different so we want to find or create a new tag (rather than updating the exiting tag label) if tag.label != existing.label self.city_tags.delete(tag) tag = CityTag.find_by_label(tag.label) || CityTag.create(label: tag.label) end else #Looks like we are removing the tag and need to delete it from this object self.city_tags.delete(tag) next end end tags << tag end #Iterate through tags and add to my Location unless they are already associated. tags.each do |tag| unless tag.in? self.city_tags self.city_tags << tag end end end
위의 구현은, 삭제를 저장하고 태그를 중첩 된 형태로 fields_for을 사용할 때 필요한 방식을 변경합니다. 간단하게 할 수있는 방법이 있다면 나는 피드백에 열려있어. 이 라벨 태그 라벨을 업데이트하는 대신 변경 때 명시 적으로 태그를 변경하고 있음을 지적하는 것이 중요하다.
-
==============================
6.before_validation 후크는 좋은 선택이다 : 그것은 더 애매한 autosave_associated_records_for_의 *를 오버라이드 (override)보다 간단 코드의 결과로 표준 메커니즘입니다.
before_validation 후크는 좋은 선택이다 : 그것은 더 애매한 autosave_associated_records_for_의 *를 오버라이드 (override)보다 간단 코드의 결과로 표준 메커니즘입니다.
class Quux < ActiveRecord::Base has_and_belongs_to_many :foos accepts_nested_attributes_for :foos, reject_if: ->(object){ object[:value].blank? } before_validation :find_foos def find_foos self.foos = self.foos.map do |object| Foo.where(value: object.value).first_or_initialize end end end
-
==============================
7.프랑수아 보 솔레이가 굉장 @으로 답변하고 큰 문제를 해결했다. autosave_associated_record_for의 개념에 대한 자세한 내용은 좋아요.
프랑수아 보 솔레이가 굉장 @으로 답변하고 큰 문제를 해결했다. autosave_associated_record_for의 개념에 대한 자세한 내용은 좋아요.
그러나, 나는이 구현 한 구석 케이스를 발견했다. 새로운 작성자 이름 (A2)가 전달되는 경우 기존 포스트의 저자 (A1)의 갱신의 경우, 원래 (A1) 저자의 이름을 변경 종료됩니다.
p = Post.first p.author #<Author id: 1, name: 'JK Rowling'> # now edit is triggered, and new author(non existing) is passed(e.g: Cal Newport). p.author #<Author id: 1, name: 'Cal Newport'>
원래 코드 :
class Post < ActiveRecord::Base belongs_to :author, :autosave => true accepts_nested_attributes_for :author # If you need to validate the associated record, you can add a method like this: # validate_associated_record_for_author def autosave_associated_records_for_author # Find or create the author by name if new_author = Author.find_by_name(author.name) self.author = new_author else self.author.save! end end end
1, 그것은 다른 블록으로 이동하고 새로 만드는 대신 그 저자를 업데이트합니다 : 편집의 경우, 게시물에 대한 self.author 이미 ID로 저자 될 것 때문이다.
나는이 문제를 완화하기 위해 코드 (ELSIF 조건)을 변경 :
class Post < ActiveRecord::Base belongs_to :author, :autosave => true accepts_nested_attributes_for :author # If you need to validate the associated record, you can add a method like this: # validate_associated_record_for_author def autosave_associated_records_for_author # Find or create the author by name if new_author = Author.find_by_name(author.name) self.author = new_author elsif author && author.persisted? && author.changed? # New condition: if author is already allocated to post, but is changed, create a new author. self.author = Author.new(name: author.name) else # else create a new author self.author.save! end end end
-
==============================
8.@ 더스틴-m의 대답은 나를 위해 쓸모 있었다 - 나는 has_many 뭔가 정의를하고있는 중이 야 : 관계를 통해. 나는 많은 아이들 (재귀)가 하나의 트렌드를 가지고 주제를 가지고있다.
@ 더스틴-m의 대답은 나를 위해 쓸모 있었다 - 나는 has_many 뭔가 정의를하고있는 중이 야 : 관계를 통해. 나는 많은 아이들 (재귀)가 하나의 트렌드를 가지고 주제를 가지고있다.
소스 동향 : : : 자녀 관계 검색을 통해 : 나는 표준 has_many으로이를 구성 할 때 액티브는 좋아하지 않는다. 그것은 topic.trend 및 topic.searches를 검색하지만 topic.searches.create하지 않을 것이다 (이름 : foo는).
나는 사용자 정의 자동 저장을 구성하기 위해 위의 사용 accepts_nested_attributes_for와 올바른 결과 달성하고 그래서 : 검색, allow_destroy을 : 사실 데프 autosave_associated_records_for_searches searches.each 할 | 의 | s._destroy 경우 self.trend.children.delete (들) ELSIF s.new_record? << S self.trend.children 그밖에 s.save 종료 종료 종료
from https://stackoverflow.com/questions/3579924/accepts-nested-attributes-for-with-find-or-create by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] 어떻게 레일에서 같은 양식 버튼을 제출 여러 만듭니 까? (0) | 2020.02.05 |
---|---|
[RUBY-ON-RAILS] 3 레일 : "필드 - 오류가있는"페이지의 모양이 변경 래퍼. 어떻게 이것을 피하기 위해? (0) | 2020.02.05 |
[RUBY-ON-RAILS] 어떻게 Arel와 레일에서 LIKE 쿼리를 할까? (0) | 2020.02.05 |
[RUBY-ON-RAILS] 경고 : PATH에서 안전하지 않은 세계 쓰기 가능한 디렉토리 / usr / 지방 / 빈 모드 040777 (0) | 2020.02.05 |
[RUBY-ON-RAILS] 3 개 형태의 레일에 루비의 _snowman PARAM은 무엇인가? (0) | 2020.02.05 |