Activeadmin, polymorphic relationship and nested attributes - ruby-on-rails

I have 2 models: Provider and Delivery. The Note model belongs to either of the two, by polymorphism (belongs_to).
The Provider model looks like this:
class Provider < ActiveRecord::Base
attr_accessible :name, :site_url, :brand_ids, :note_attributes
validates :name, presence: true
has_one :note
accepts_nested_attributes_for :note, allow_destroy: true
end
The form to create a new provider renders with no problem, but when I try to save it I get the following error:
unknown attribute: provider_id
How can I fix this?

The Note model should have attr_accessible :provider_id

Related

Rails - how to ignore validations for a nested object?

I have a form to collect information about a Physician. Each Physician can have at least one Address but it's ok for a physician not to have any address.
Below is the relevant code from my physician.rb and model.rb files that define the respective models.
class Physician < ApplicationRecord
belongs_to :address, optional: true
accepts_nested_attributes_for :address
class Address < ApplicationRecord
validates :line_1, presence: true
validates :city, presence: true
Address has some required fields, line_1, and city
I would like to ignore the presence requirement on these fields ONLY for the Physician form.
I tried using the optional: true tag (shown in the code above) but that didn't do it.
You probably need to change the following line
accepts_nested_attributes_for :address
to
accepts_nested_attributes_for :address, reject_if: :all_blank
so the associated Address object will be completely ignored if all of its attributes are left blank.

Attr_accessor use table name

Hi i have a problem with "attr_accessor" in rails 4
I have a model with many associations and when I use attr_accessor I put the field_name but with my association i have many table with the same field name.
For exemple
class User < ActiveRecord::Base
has_one :agent
has_one :language
attr_accessor :code
end
But i have a field :code in agent table and in language table.
I'm trying to find a solution on internet but without success
Is there a way to specify the table name ?
You can use these way to get model speicific code from user model
class User < ActiveRecord::Base
has_one :agent
has_one :language
delegate :code, to: :agent, prefix: true, allow_nil: true
delegate :code, to: :language, prefix: true, allow_nil: true
end
As an example:
Now you can access it User.first.agent_code for agent model Also you can access it User.first.language_code for language model
You can access the specific code by specific model wise
To specify table name expicitly use
class User < ActiveRecord::Base
self.table_name = "table_name"
end

How to validate presence of associated fields in Ruby on Rails

I have tables applications and business.
Applications
has_many :business
Business
belongs_to :applications
If I will create an Application, I should have at least one Business. I used link_to_add in the same form where I create applications.
I used validate_association :applciations but it didn't work.
You may be better to use validates_associated:
#app/models/business.rb
class Business < ActiveRecord::Base
belongs_to :application
validates :name, :other, param, presence: true
end
#app/models/application.rb
class Application < ActiveRecord::Base
has_many :businesses
validates_associated :businesses
end
This gives you the ability to check the validity of any associated data you pass through the model. However, this will not determine if there is at least one associated business passed through your model.
--
Numerical Validation
You'll want to look at the following
The reject_if method in Rails will not give you the ability to check the number of associated items which have been sent. This will have to be custom coded, which the author of the above post has addressed (in 2012) by setting a custom constant:
#app/models/company.rb
class Company < ActiveRecord::Base
OFFICES_COUNT_MIN = 1
validates :name, presence: true
validate do
check_offices_number
end
has_many :offices
accepts_nested_attributes_for :offices, allow_destroy: true
private
def offices_count_valid?
offices.count >= OFFICES_COUNT_MIN
end
def check_offices_number
unless offices_count_valid?
errors.add(:base, :offices_too_short, :count => OFFICES_COUNT_MIN)
end
end
end
I have not tested this myself, but to explain how it works, you'll basically have a custom validator, which allows you to check whether the number of associated objects is less than or equal to the CONSTANT you assign in the class.
You can, of course, achieve this without a constant, but the above example should demonstrate how you're able to create the functionality where at least 1 associated item should be sent
Not sure if this is what you meant but you could do the following in your models e.g.
has_many :businesses, dependent: :destroy
validates :title, presence: true
and in the other model:
belongs_to :application
validates :name, presence: true
You can use validates_presence_of
Validates that the specified attributes are not blank (as defined by Object#blank?), and, if the attribute is an association, that the associated object is not marked for destruction. Happens by default on save.
Example:
Applications
has_many :businesses
validates_presence_of :business
Business
belongs_to :applications
Update:
I think you will be better to using accepts_nested_attributes_for
Nested attributes allow you to save attributes on associated records through the parent. By default nested attribute updating is turned off and you can enable it using the accepts_nested_attributes_for class method. When you enable nested attributes an attribute writer is defined on the model.
app/models/application.rb
Class Application < ActiveRecord::Base
has_many :businesses
accepts_nested_attributes_for :businesses, reject_if: :all_blank
end
#app/models/business.rb
Class Business < ActiveRecord::Base
belongs_to :application
end
This will give you the ability to call the reject_if: :all_blank method -
:reject_if
Allows you to specify a Proc or a Symbol pointing to a method that checks whether a record should be built for a certain attribute hash. The hash is passed to the supplied Proc or the method and it should return either true or false. When no :reject_if is specified, a record will be built for all attribute hashes that do not have a _destroy value that evaluates to true. Passing :all_blank instead of a Proc will create a proc that will reject a record where all the attributes are blank excluding any value for _destroy.

Rails belongs_to same model in multiple attributes

There is a model called Student and has an attribute called :studies_level.
studies_level can have one of the following values: ['school_graduate', 'undergraduate', 'graduate', 'postgraduate', 'doctoral', 'postdoctoral']
There is also another model called University
If :studies_level is postgraduate then Student must fill the following attributes :undergraduate_university and :postgraduate_university with a University_id
Is there any way to achieve this with Rails model relations (belongs_to, etc) ?
belongs_to :undergraduate_university, class_name: :University
belongs_to :postgraduate_university, class_name: :University
validates :undergraduate_university, presence: true, if: :studies_level=='postgrad'
validates :postgraduate_university, presence: true, if: :studies_level=='postgrad'
validates_associated :undergraduate_university
validates_associated :postgraduate_university

Trouble with accepts_nested_attributes_for on validating foreign key

I am using Ruby on Rails v3.2.2. I would like to solve the issue related to the validation of a foreign key when using accepts_nested_attributes_for and validates_associated RoR methods. That is, I have following model classes:
class Article < ActiveRecord::Base
has_many :category_associations, :foreign_key => 'category_id'
accepts_nested_attributes_for :category_associations, :reject_if => lambda { |attributes| attributes[:category_id].blank? }
validates_associated :category_associations
end
class CategoryAssociation < ActiveRecord::Base
belongs_to :article, :foreign_key => 'article_id'
belongs_to :category, :foreign_key => 'category_id'
validates :article_id, :presence => true
validates :category_id, :presence => true
end
... and I have following controller actions:
class ArticlesController < ApplicationController
def new
#article = Article.new
5.times { #article.category_associations.build }
# ...
end
def create
#article = Article.new(params[:article])
if #article.save
# ...
else
# ...
end
end
end
With the above code ("inspired" by the Nested Model Form Part 1 Rails Cast) my intent is to store category associations when creating an article (note: category objects are already present in the database; in my case, I would like just storing-creating category associations). However, when I submit the related form from the related view file, I get the following error (I am logging error messages):
{:"category_associations.article_id"=>["can't be blank"], :category_associations=>["is invalid"]}
Why it happens since validates_associated seems to run the method article.category_association.valid? but only if the article.category_association.article_id is not nil? How can I solve the problem with the presence validation of the article_id foreign key?
However, if I comment out the validates :article_id, :presence => true in the CategoryAssociation model class, it works as expected but it seems to be not a right approach to do not validate foreign keys.
If I comment out the validates_associated :category_associations in the Article model class, I still get the error:
{:"category_associations.article_id"=>["can't be blank"]}
Use inverse_of to link the associations and then validate the presence of the associated object, not the presence of the actual foreign key.
Example from the docs:
class Member < ActiveRecord::Base
has_many :posts, inverse_of: :member
accepts_nested_attributes_for :posts
end
class Post < ActiveRecord::Base
belongs_to :member, inverse_of: :posts
validates_presence_of :member
end
Since you have a possible nested form with accepts_nested_attributes_for, therefore in CategoryAssociation you need to make the validation conditional, requiring presence for only for only updates:
validates :article_id, presence: true, on: :update
Aside from Active Record associations, you should have a foreign key constraints at the db level.
If you're stucked with this kind of errors too, try to replace:
validates :article_id, :presence => true
validates :category_id, :presence => true
with:
validates :article, :presence => true
validates :category, :presence => true
worked for me.
Validations will run on create or save (as you'd expect), so ask yourself, "at each one of those is there a saved instance being referred to?", because without a save an instance won't have an id as it's the database that assigns the id.
Edit: Like I've said in the comments, if you're going to downvote then leave a comment as to why.

Resources