0

我在轨以下设置:如何创建关系记录,并且如果已经存在,则忽略并保存到关联中?

book.rb可有带has_and_belongs-to_many很多学校:学校

class Book < ActiveRecord::Base 

    before_save :get_school 

    include PgSearch 
    pg_search_scope :search, :against => [:title, :slug, :synopsis, :body], 
    using: { tsearch:{ dictionary: "english" } } 

    def self.text_search(query) 
     if query.present? 
     where("title @@ :q or synopsis @@ :q", q: query) 
     else 
     scoped 
     end 
    end 

    has_attached_file :jacket_cover, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png" 
    validates_attachment_content_type :jacket_cover, :content_type => /\Aimage\/.*\Z/ 

    validates :jacket_cover, :title, :slug, :synopsis, :body, :age, :publisher, presence: true 
    validates_uniqueness_of :title 

    extend FriendlyId 
    friendly_id :title, use: [:slugged, :finders] 

    belongs_to :author 
    belongs_to :gallery 
    has_many :stories 
    has_many :images 

    has_and_belongs_to_many :schools, join_table: "books_schools" 

    accepts_nested_attributes_for :author 
    accepts_nested_attributes_for :gallery, :allow_destroy => true 
    accepts_nested_attributes_for :schools, :reject_if => :all_blank, :allow_destroy => true 
    accepts_nested_attributes_for :images, :allow_destroy => true 

    def get_school 
     self.schools.map do |school| 
      School.where(:id).first_or_create 
     end 
    end 

    scope :available, ->{ where(available: true) } 
    scope :unavailable, ->{ where(available: [nil, false]) } 

end 

school.rb可以有has_and_belongs-to_many许多书籍:图书

class School < ActiveRecord::Base 
    has_and_belongs_to_many :books 

    validates :school_name, :address, presence: true 
    #validates_uniqueness_of :school_name 
end 

在我的数据库架构我有枢轴/连接表,此事看起来如下:

create_table "books_schools", id: false, force: true do |t| 
    t.integer "book_id", null: false 
    t.integer "school_id", null: false 
    end 

    add_index "books_schools", ["book_id", "school_id"], name: "index_books_schools_on_book_id_and_school_id", using: :btree 
    add_index "books_schools", ["school_id", "book_id"], name: "index_books_schools_on_school_id_and_book_id", using: :btree 

这工作正常,我可以添加许多学校书籍,并添加到另一所学校同一本书。这很好,工作正常,但我正在尝试使用此模型执行以下操作。

我试图阻止一个新的学校被创建,如果该名称已经存在于记录中,但仍然将该记录作为关系关联并添加到书中并将其传递。

到目前为止,我已经尝试了book.rb文件这样的:

def schools_attributes=(schools_attributes) 
    schools_attributes.values.each do |school_attributes| 
     if school_attributes[:id].nil? and school_attributes[:school_name].present? 
     school = School.find_by_school_name(school_attributes[:school_name]) 
     if school.present? 
      school_attributes[:id] = school.id 
      self.schools << school 
     end 
     end 
    end 
    #assign_nested_attributes_for_collection_association(:schools, schools_attributes) 
    end 

这并没有在系统中添加上学。

我也曾在book.rb尝试这样:

before_save :get_school 

def get_school 
     self.schools.map do |school| 
      School.where(:id).first_or_create 
     end 
    end 

这扔这些错误:ERROR: invalid input syntax for type boolean: "id"

我很努力看到这将开始以及如何得到它运行起来。

+0

你得到的'invalid input syntax'错误是因为你的where调用不正确。你可以做'School.where(id:school.id)'。它是否如你所期望的那样工作? – ptd 2014-10-09 16:56:27

+0

不,它仍然创建重复的记录,因为我需要使用'School.where(school_name:school.school_name).first_or_create',甚至使用id它仍然复制记录在/学校索引 – 2014-10-09 17:04:19

+0

如果existing_school = School.where (school_name:school.school_name).first then school.id = existing_school.id end'。这将在'self.schools.map'块中。 – ptd 2014-10-09 17:09:17

回答

0

所以看起来像你遇到的问题是,你正在尝试为已存在的项目accept_nested_attributes。我相信你想拒绝存在的学校的嵌套属性,而只是将学校添加到书中。

accepts_nested_attributes_for :schools, :reject_if => :find_school, :allow_destroy => true 

,然后定义你的Book模型find_school

def find_school(school) 
    if existing_school = School.find_by_school_name(school['school_name']) 
    self.schools << existing_school 
    return true 
    else 
    return false 
    end 
end 

这将不接受现有学校嵌套的属性,而是只是现有在校添加到您的Book

+0

那还在学校索引中创建复制学校 – 2014-10-09 18:15:36

+0

对不起,我真假混淆了,所以只是存在的那些存档。我编辑了答案。 – ptd 2014-10-09 18:17:14

+0

谢谢,完美的工作:) – 2014-10-09 18:20:51