Rails 4-best_in_place宝石和多对多关联 [英] Rails 4 - best_in_place gem and many-to-many association
问题描述
我正在努力使用 best_in_place 来更新联系人语言的功能. >(一个jQuery本地编辑器gem).
I am struggling to add the ability to update a contact languages using best_in_place (a jQuery inplace-editor gem).
我有一个联系人对象,一个语言对象以及联系人和语言之间的 has_and_belongs_to_many:languages 关系.因此,has_and_belongs_to_many隐含了联系人和语言表之间的联接表.总结一下,我有这样的东西:
I have a contact object, a language object and a has_and_belongs_to_many :languages relationship between contacts and languages. Therefore, a has_and_belongs_to_many implied a join table between the contacts and the languages tables. To sum up quickly, I have something like this:
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 |
+------------+-------------+ +------+------------+
现在,要显示和编辑联系人语言,我使用的表单是:
Now, to display and edit a contact languages, I am using a form in which I have:
- @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?}"
请注意,我在这里使用的是苗条模板引擎.
@contact设置为Contact.find(params[:id])
@ contact.languages返回#language对象的ActiveRecord
在控制器中将@all_languages设置为Language.order("name ASC")
@contact is set in the controller to Contact.find(params[:id])
@contact.languages return an ActiveRecord of #language objects
@all_languages is set in the controller to Language.order("name ASC")
另外,请注意,@contact.language_ids
将打印@contact
的language_id
数组,而我正在使用@contact.update_attributes(language_ids: [1, 2, 3])
设置联系语言.
Also, note that @contact.language_ids
would print an array the language_id
of @contact
and I am using @contact.update_attributes(language_ids: [1, 2, 3])
to set a contact languages.
上面的当前源代码可以显示语言,但是在更新它们时不起作用,因为best_in_place将lang
用作对象.因此,我最终将不会更新* contacts_languages *表,而是更新 languages 表,如下所示:
The current source code above works to display languages, but do not work when it comes to update them as lang
is used as an object by best_in_place. Therefore, I will end up not updating the *contacts_languages* table but the languages table instead like this:
languages
+------+------------+
| id | name |
+------+------------+
| 1 | 1 |
| 2 | FR |
| 3 | DE |
| 4 | ES |
| 5 | ZH |
| 6 | JP |
+------+------------+
其中 name 已被替换为应该设置为contacts_languages表的语言的ID.
where name has been replaced by the id of the language that was supposed to be set to the contacts_languages table.
您是否知道如何更新* contacts_languages *表而不是已编辑语言?并尽可能使用best_in_place.
Do you have any idea how could I update the *contacts_languages* table instead for the edited language? And everything using best_in_place if possible.
谢谢!
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 < ActiveRecord::Base
include PublicActivity::Model
tracked except: :destroy,
owner: Proc.new{ |controller, model| controller.current_user },
recipient: ->(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不允许这样做.
I think the following could be your best bet. I tried doing it in a more "Rails" way, but BIP won't allow it.
查看
<% @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'
这篇关于Rails 4-best_in_place宝石和多对多关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!