I'm using model with two belongs_to associations with Rails Admin.
belongs_to :product, inverse_of: :services
belongs_to :user, inverse_of: :services
accepts_nested_attributes_for :product, allow_destroy: true
accepts_nested_attributes_for :user, allow_destroy: true
Adding accepts_nested_attributes_for makes generated form look like this without select for search in existing records.
Without accepts_nested_attributes_for it looks exacly as I want it to
Is there a way to force Rails Admin use search select?
field :user do
nested_form false
end
doesn't work as I expected.
Well
field :user do
nested_form false
end
actually works fine. I was just using it in list block instead of edit... sigh
Related
Rails newbie here. I am having trouble with ensuring the presence of at least one "has_many :through" relationship in my users model.
I have:
class User < ApplicationRecord
has_many :company_users, dependent: :destroy
has_many :companies, through: :company_users
#validates :company_users, presence: true
end
class Company < ApplicationRecord
has_many :company_users, dependent: :destroy
has_many :users, through: :company_users
end
class CompanyUser < ApplicationRecord
belongs_to :user
belongs_to :company
end
I got the commented validates line from the excellent answers at:
Validate that an object has one or more associated objects
Rails 3: validate presence of at least one has many through association item
However when I implement this line, then doing the following in rails console:
c = Company.create
c.users.create!(email: "test#example.com")
gives
`raise_validation_error': Validation failed: Company users can't be blank (ActiveRecord::RecordInvalid)
From my newbie perspective, it seems like the HMT entry isn't created until after the user is created, which creates a validation error preventing the user in the first place! It's probably a very simple error, but how do I get the above behaviour to work with that validation in place?
I have tried setting inverse_of in a couple place, without any success.
And before it's mentioned, I'm purposefully using HMT instead of HABTM because I have additional attributes on the company_users model that will be set.
One option would be to change the validation to
validates :companies, presence: true
and then create the user with
User.create(companies: [Company.create])
Edit:
Adding inverse_of to the CompanyUser model should also work. The validation would be left as validate :company_users, presence: true:
class CompanyUser
belongs_to :user, inverse_of: :company_users
belongs_to :company
end
I have 2 models, order and owner, which are joined together by an order_owner model using a has_many through association. Each order must have at least 1 owner associated to it but since each order or owner can have many of the other, a many-to-many relationship is required.
I've set up my order model with validates :owners, presence: true which works great if I attempt to create an order without associating any owners to it. However, the issue I'm encountering is that the validation still fails regardless of associating an owner at the time of creation via nested attributes and I don't know how to fix it.
Models - Rails 5.0.2
##order.rb
has_many :order_owners, inverse_of: :order, dependent: :destroy
has_many :owners, through: :order_owners
accepts_nested_attributes_for :owners, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :order_owners, reject_if: :all_blank, allow_destroy: true
validates :owners, presence: true
##owner.rb
has_many :order_owners, inverse_of: :owner, dependent: :destroy
has_many :orders, through: :order_owners
##order_owner.rb
belongs_to :owner
belongs_to :order
accepts_nested_attributes_for :owner
I've tried using custom validation methods like
validate :must_have_owner
...
def must_have_owner
if owners.empty? or owners.all? { |owner| owner.marked_for_destruction? }
errors.add(:base, 'Order must have at least one owner')
end
end
But the same thing occurs.
The way that I'm associating owners to an order upon creation is via nested attributes and using the Cocoon gem. So a user fills out the order form, then adds the appropriate owners (either via a Owners.all select or adding a new owner to be created), then submits the form. Without the aforementioned validation the whole process works fine but it also allows an order to be created without an owner which defeats the purpose.
Any ideas would be helpful, thanks!
A report_template has_many report_template_columns, which each have a
name and an index attribute.
class ReportTemplateColumn < ApplicationRecord
belongs_to :report_template
validates :name, presence: true
end
class ReportTemplate < ApplicationRecord
has_many :report_template_columns, -> { order(index: :asc) }, dependent: :destroy
accepts_nested_attributes_for :report_template_columns, allow_destroy: true
end
The report_template_columns need to be ordered by the index column. I'm applying this with a scope on the has_many association, however doing so causes the following error:
> ReportTemplate.create!(report_template_columns: [ReportTemplateColumn.new(name: 'id', index: '1')])
ActiveRecord::RecordInvalid: Validation failed: Report template columns report template must exist
from /usr/local/bundle/gems/activerecord-5.1.4/lib/active_record/validations.rb:78:in `raise_validation_error'
If I remove the scope the same command succeeds.
If I replace the order scope with where scope that command fails in the same way, so it seems to be the presence of the scope rather than the use of order specifically.
How can I apply a scope to the has_many without breaking the nested creation?
I believe you need the :inverse_of option added to the has_many association.
class ReportTemplate < ApplicationRecord
has_many :report_template_columns, -> { order(index: :asc) },
dependent: :destroy, inverse_of: :report_template
end
The api states that :inverse_of:
Specifies the name of the belongs_to association on the associated object that is the inverse of this has_many association. Does not work in combination with :through or :as options. See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
I also like how the cocoon gem words their reason for using it:
Rails 5 Note: since rails 5 a belongs_to relation is by default required. While this absolutely makes sense, this also means associations have to be declared more explicitly. When saving nested items, theoretically the parent is not yet saved on validation, so rails needs help to know the link between relations. There are two ways: either declare the belongs_to as optional: false, but the cleanest way is to specify the inverse_of: on the has_many. That is why we write: has_many :tasks, inverse_of: :project
I have two models that both accept_nested_attributes_for each other. I know this is causing issues with rails_admin but can't seem to figure out the appropriate command to exclude nested attributes in my configuration. Ideally I would like to exclude nested attributes for all models so that this problem does not happen again.
Branden,
You need to inform the bi-direction association using inverse_of:
Ex:
class User < ActiveRecord::Base
belongs_to :company, :inverse_of => :users
accepts_nested_attributes_for :company
end
For both sides of association:
class Company < ActiveRecord::Base
has_many :users, inverse_of: :company
accepts_nested_attributes_for :users, :allow_destroy => true
end
More information in the docs: http://guides.rubyonrails.org/association_basics.html#bi-directional-associations
I have two Models
class Entity < ActiveRecord::Base
# Associations
has_many :contacts
accepts_nested_attributes_for :contacts, :allow_destroy => true
end
class Contact < ActiveRecord::Base
# Associations
belongs_to :entity
end
Now in rails admin I am getting below options.
Add new Contact Form
Add new Entity Form
I need to hide Entity field in contact form , while adding new entity.
Any help will be useful.
You can automatically hide the fields using inverse_of like this
class Entity < ActiveRecord::Base
# Associations
has_many :contacts, inverse_of: :entity
accepts_nested_attributes_for :contacts, allow_destroy: true
end
class Contact < ActiveRecord::Base
# Associations
belongs_to :entity, inverse_of: :contacts
end
If you set the :inverse_of option on your relations, RailsAdmin will
automatically populate the inverse relationship in the modal creation
window. (link next to :belongs_to and :has_many multi-select widgets)
Source: https://github.com/sferik/rails_admin/wiki/Associations-basics
Let me know how it went
For the sake of completness and because i had this problem too and solved it, if you want to you can configure a model when it is used inside a nested form just like you do with edit, update, create and nested
class Contact < ActiveRecord::Base
# Associations
belongs_to :entity
rails_admin do
nested do
configure :entity do
hide
end
end
end
end
Visit the official wiki for more info