I am trying to modify nested attributes before they are saved in my database. The idea is that if someone has already submitted a costume with a given cid in the costume database, we should pull that one and use it for the current agreement. However, through debugging, I've found that the nested attributes array doesn't change at all. Any thoughts?
Thanks!
Matt
app/models/agreement.rb
class Agreement < ActiveRecord::Base
before_save :get_costumes
has_and_belongs_to_many :costumes, join_table: :agreement_costumes
accepts_nested_attributes_for :costumes, reject_if: proc { |attributes| attributes['cid'].blank? }
has_many :drycleans
accepts_nested_attributes_for :drycleans, allow_destroy: true, reject_if: :all_blank
def get_costumes
self.costumes.map! { |costume|
unless Costume.where(cid: costume.cid).nil?
Costume.where(cid: costume.cid).first
end
}
end
end
Your unless-condition is never true. With a where-statement you get always an ActiveRecord. And also a empty ActiveRecord is not nil.
Try to change that condition to:
unless Costume.where(cid: costume.cid).count == 0
Or to:
unless Costume.find_by_cid(costume.cid).nil?
Related
I got the following models:
class Course < ApplicationRecord
has_many :external_ids, as: :identifiable, dependent: :destroy, validate: true
accepts_nested_attributes_for :external_ids
end
and this one:
class ExternalId < ApplicationRecord
belongs_to :identifiable, polymorphic: true
validates :name, presence: true, uniqueness: true
validates :identifiable, presence: true, on: :create
end
Because of a nested form in the course form-view it's possible that a blank object of an external id will be saved. I'd like to remove these blank objects. With "blank object" I mean an ExternalId which is a new record and has a blank name. Currently I do that as follows:
#course.attributes = course_params
## SNIP - workaround to fix validations
external_ids = []
#course.external_ids.each do |ext_id|
external_ids << ext_id unless(ext_id.new_record? && ext_id.name.blank?)
end
#course.external_ids = external_ids
## SNAP - workaround to fix validations
#course.save
But this is a lot of code for a very simple task. Is there any function for that? destroy_if doesn't exists for an association, only for arrays.
Thanks you!
You can use accepts_nested_attributes_for with such key
accepts_nested_attributes_for :external_ids, reject_if: proc { |attributes| attributes['name'].blank? }
From docs:
You may also set a :reject_if proc to silently ignore any new record hashes if they fail to pass your criteria
I have model (container) that accepts nested attributes (including allow_destroy) for a has_one relationship to another model (reuse_request). There is a before_validation callback in the container model that I don't want to run if the the reuse_request is about to be destroyed in the same update.
Is there a way to check if the _destroy attribute has been passed from within the container model before_validation callback?
#container.rb
before_validation :set_code
has_one :reuse_request_as_previous, class_name: 'ReuseRequest', foreign_key: 'previous_container_id', dependent: :destroy, inverse_of: :previous_container
accepts_nested_attributes_for :reuse_request_as_new, :allow_destroy => true
def set_code
if reuse_request_as_new && reuse_request_as_new.previous_container
self.code = reuse_request_as_new.previous_container.code
end
end
How about using .marked_for_destruction??
def set_code
return if reuse_request_as_new.marked_for_destruction?
...
end
I can't delete nested attributes child record.
Article with Article_series is the model.
Here's the code.
Model
class Article < ApplicationRecord
has_many :articles_article_series
has_many :article_series, through: :articles_article_series
accepts_nested_attributes_for :articles_article_series, allow_destroy: true, reject_if: proc { |attributes| attributes['article_id'].blank? && attributes['series_id'].blank? && attributes['num'].blank? }
Controller
def update
#article = Article.find(params[:article][:id])
# article_series delete
#article.articles_article_series.each do |series|
series.mark_for_destruction
end
#article.save
Does anyone tell me why & how?
I believe you may be looking for
has_many :articles_article_series, dependent: :destroy
It looks like only array works 'mark_for_destruction'.
#article.articles_article_series.to_a.first.mark_for_destruction
Before, I did like below. It's so difficult to find the way to fix.
#article.articles_article_series.first.mark_for_destruction
Thanks for all contributes :)
So I have many polymorphic children for a Profile object. The models are designed to destroy after_save if the specific Object's field is blank.
But for accept_nested_attributes I don't want to create the child object in the first place if it's blank. But if I leave the reject_if statement then the user no longer has the ability to empty the field on UPDATE because the reject_if rejects their blank input.
accepts_nested_attributes_for :socials, reject_if: proc { |att| att['username'].blank? }
accepts_nested_attributes_for :phones, reject_if: proc {|att| att['number'].blank? }
accepts_nested_attributes_for :websites, reject_if: proc {|att| att['url'].blank? }
So I want to reject_if: { ... }, on: :create. But that doesn't seem to work.
You can create a method and instead of sending a proc into the reject_if option, which is the same, it is just more readable, so the code would look like:
accepts_nested_attributes_for :socials, reject_if: :social_rejectable?
private
def social_rejectable?(att)
att['username'].blank? && new_record?
end
You can just repeat the methods and then clean it up with some metaprogramming or add the new_record? method on the proc
accepts_nested_attributes_for :socials, reject_if: proc { |att| att['username'].blank? && new_record?}
I have a problem.
I have a Content model that has a polymorphic association, Sponsorship.
In my content form I have a nested form with some sponsorship details. These sponsorship details aren't mandatory, but now every time that I edit a content the sponsorship table is filled with blank data.
I will simplify my code here:
class Content < ActiveRecord::Base
include Sponsorable
end
class Sponsorship < ActiveRecord::Base
belongs_to :sponsorable, polymorphic: true
end
module Sponsorable
extend ActiveSupport::Concern
included do
has_one :sponsorship, as: :sponsorable
accepts_nested_attributes_for :sponsorship
end
end
I need to clarify that I create an auto-saving feature on my content model, so in my content controller I put a Content.create in the "new" method.
def new
#content = Content.create(author: current_user)
redirect_to edit_admin_content_path(#content)
end
And to fill the sponsorship detail
def edit
content.build_sponsorship unless content.sponsorship
end
Every time I create and save a content the sponsorship details are created also if I leave the form fields empty. My content table has a boolean "sponsor": is there a way to save association only if sponsor == true?
You may want to look at the reject_if: option for accepts_nested_attributes_for:
accepts_nested_attributes_for :sponsorship, reject_if: proc { |attributes| attributes['title'].blank? }
Looking up other questions on this matter seem to confirm this.
--
There is also reject_if: :all_blank -
accepts_nested_attributes_for :sponsorship, reject_if: :all_blank