Rails 4 – best_in_place gem和多对多关联

我正在努力添加使用best_in_place (jQuery inplace -editor gem)更新联系语言的能力。

我有联系人对象,语言对象和联系人和语言之间的has_and_belongs_to_many:languages关系。 因此,has_and_belongs_to_many隐含了联系人和语言表之间的连接表。 总结一下,我有这样的事情:

contacts contacts_languages languages +------+--------+ +------------+-------------+ +------+------------+ | id | name | | contact_id | language_id | | id | name | +------+--------+ +------------+-------------+ +------+------------+ | 1 | John | | 1 | 2 | | 1 | EN | | 2 | Mike | | 1 | 3 | | 2 | FR | | 3 | Dick | | 2 | 1 | | 3 | DE | +------+--------+ | 3 | 1 | | 4 | ES | | 3 | 5 | | 5 | ZH | | 3 | 6 | | 6 | JP | +------------+-------------+ +------+------------+ 

现在,为了显示和编辑联系语言,我使用的表单中包含:

 - @contact.languages.uniq.each_with_index do |lang, index| = best_in_place lang, :name, type: :select, collection: @all_languages.map { |name| [name.id, name.name] }, classes: "#{'empty' if lang.blank?}" 

请注意,我在这里使用slim模板引擎。

@contact在控制器中设置为Contact.find(params[:id]) @ contact.languages返回#language对象的ActiveRecord @all_languages在控制器中设置为Language.order("name ASC")

另请注意, @contact.language_ids会打印一个@contactlanguage_id数组,我正在使用@contact.update_attributes(language_ids: [1, 2, 3])来设置联系语言。

上面的当前源代码用于显示语言,但在更新它们时不起作用,因为lang被best_in_place用作对象。 因此,我最终不会更新* contacts_languages *表,而是更新语言表,如下所示:

  languages +------+------------+ | id | name | +------+------------+ | 1 | 1 | | 2 | FR | | 3 | DE | | 4 | ES | | 5 | ZH | | 6 | JP | +------+------------+ 

其中name已被应该设置为contacts_languages表的语言的id替换。

您是否知道我如何更新* contacts_languages *表而不是编辑语言? 如果可能的话,一切都使用best_in_place。

谢谢!

编辑

contact.rb

 # == Schema Information # # Table name: contacts # # id :integer not null, primary key # first_name :string(255) # last_name :string(255) # title :string(255) # age :float # gender :integer # active :integer # info :text # created_at :datetime not null # updated_at :datetime not null # user_id :integer # slug :string(255) # account_id :integer # image :string(255) # uid :integer # tracking_friend_token :string(255) # tracking_friend_id :string(255) # user_token :string(255) # job_title :string(255) # dob :date # marital_status :integer # class Contact (controller, model) { model && model } include PgSearch pg_search_scope :search, against: [:first_name, :last_name, :uid], associated_against: { email_addresses: :email } after_create :set_defaults attr_accessible :first_name, :last_name, :title, :age, :gender, :active, :info, :user_id, :type_list, :industry_list, :tag_list, :category_list, :phone_numbers_attributes, :email_addresses_attributes, :social_networks_attributes, :addresses_attributes, :websites_attributes, :instant_messengers_attributes, :company_ids, :language_ids, :user_ids, :slug, :account_id, :image, :uid, :tracking_friend_token, :tracking_friend_id, :job_title, :dob, :marital_status, :children_attributes, :important_dates_attributes, :user_token #Will Paginate default self.per_page = 100 acts_as_tenant(:account) acts_as_taggable acts_as_taggable_on :type, :industries, :categories has_many :addresses has_many :alerts has_many :attachments has_many :call_requests has_many :children has_many :comments has_many :contact_companies has_many :email_addresses has_many :important_dates has_many :instant_messengers has_many :phone_numbers has_many :pushes has_many :social_networks has_many :websites has_many :companies, through: :contact_companies has_and_belongs_to_many :languages has_and_belongs_to_many :users accepts_nested_attributes_for :addresses, :reject_if => proc { |attributes| attributes['address_line_1'].blank? }, :allow_destroy => true accepts_nested_attributes_for :attachments, :reject_if => proc { |a| a['file'].blank? }, :allow_destroy => true accepts_nested_attributes_for :children, :reject_if => proc { |a| a['first_name'].blank? }, :allow_destroy => true accepts_nested_attributes_for :comments, :reject_if => proc { |a| a['comment'].blank? }, :allow_destroy => true accepts_nested_attributes_for :email_addresses, :reject_if => proc { |a| a['email'].blank? }, :allow_destroy => true accepts_nested_attributes_for :important_dates accepts_nested_attributes_for :instant_messengers, :reject_if => proc { |a| a['name'].blank? }, :allow_destroy => true accepts_nested_attributes_for :languages, :reject_if => proc { |a| a['iso'].blank? }, :allow_destroy => true accepts_nested_attributes_for :phone_numbers, :reject_if => proc { |a| a['number'].blank? }, :allow_destroy => true accepts_nested_attributes_for :social_networks, :reject_if => proc { |a| a['name'].blank? }, :allow_destroy => true accepts_nested_attributes_for :websites, :reject_if => proc { |a| a['url'].blank? }, :allow_destroy => true validates :first_name, :presence => true validates :last_name, :presence => true validates :active, :presence => true def reference_id "ID-USR-000000#{self.id}" end def fullname "#{first_name.titleize} #{last_name.titleize}" end def set_defaults type_list = "Customer" unless self.type_list.present? language_ids = 1 unless self.language_ids.present? self.update_attributes(language_ids: language_ids, type_list: type_list) end #Postgres fulltext search def self.text_search(query) if query.present? search(query) else scoped end end end 

language.rb

 # == Schema Information # # Table name: languages # # id :integer not null, primary key # name :string(255) # iso :string(255) # contact_id :integer # company_id :integer # created_at :datetime not null # updated_at :datetime not null # class Language < ActiveRecord::Base attr_accessible :name, :iso has_and_belongs_to_many :contacts validates :name, presence: true, uniqueness: true validates :iso, presence: true, uniqueness: true default_scope order("name ASC") end 

我认为以下可能是您最好的选择。 我尝试以更“Rails”的方式进行,但BIP不允许这样做。

视图

  <% @contact.languages.uniq.each_with_index do |lang, index| %> <%= best_in_place lang, :id, type: :select, path: "/contacts/bip/#{@contact.id}/#{lang.id}", collection: @all_languages.map { |i| [i.id, i.name] } %> <% end %> 

contacts_controller

 def bip @contact = Contact.find(params[:c_id]) ContactsLanguage.where({contact_id: params[:c_id],language_id: params[:l_id]}).delete_all ContactsLanguage.create! contact_id: params[:c_id], language_id: params[:language][:id] respond_to do |format| format.json { render json: @contact } end end 

路线

  match '/contacts/bip/:c_id/:l_id' => 'contacts#bip'