I have this problem. I need to validate the attributes of two models in the same form in Rails. One is the parent of the other.
The form is like this:
<%= semantic_form_for #professional do |pro| %>
<%= pro.inputs :id => "information" do %>
<%= pro.input :name, label: t("Artistic Name") %>
<%= pro.semantic_fields_for #user do |user| %>
<%= user.inputs :id => "register" do %>
<%= user.input :email, :placeholder=>"email#example.com" %>
<%= user.input :password, label: t('Password') %>
<%end%>
<% end %>
<% end %>
<% end %>
The models I am using are like this:
User:
class User < ActiveRecord::Base
belongs_to :role, polymorphic: true
validates :email, :password, presence: true
end
Professionals:
class Professional < ActiveRecord::Base
has_one :user, as: :role, dependent: :destroy
accepts_nested_attributes_for :user
validates :date_birthday, :gender, :height, :name, :description, :Weight, :address, :languages,:services, :category, :phonenumber, :fullname, :hair_color, :age, :orientation, presence: true
end
So, what is the problem?
When I clicked in the submit button the professional attributes are marked but not the users attributes.
Like this:
The fields marked in red belongs to the professional model but the fields email and password belongs to the user model aren't marked in red when it should be because they are empty.
What can i do? I need the warning message for the user is attributes too
Thanks in advances.
We've achieved what you need before.
We had to use inverse_of so that the object was a singular piece of data (rather than multiple pieces as is the case by default):
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :role, polymorphic: true, inverse_of: :user
validates :email, :password, presence: true
end
#app/models/professional.rb
class Professional < ActiveRecord::Base
has_one :user, as: :role, dependent: :destroy, inverse_of: :role
accepts_nested_attributes_for :user
end
This will help.
You also need to make sure you're passing these objects correctly (I see so many people not doing this).
You need to tell Professional to validate the associated User:
class Professional < ActiveRecord::Base
...
validates_associated :user
Related
I would like to ask how to customize active admin.
I`m making my own blog and creating admin page using active admin gem.
This has many to many relationship with article and tag through article_tag table.
What I want to do is to add tag from article panel and I was able to show tag view in article panel, but it is not working fine.(I can`t update or remove tag after save once)
http://localhost:3000/admin/articles/new
image
I made the many to many relation with Article and Tag model like this.
article.rb
class Article < ActiveRecord::Base
has_many :article_tags
has_many :tags, through: :article_tags
accepts_nested_attributes_for :article_tags, :allow_destroy => true
end
tag.rb
class Tag < ActiveRecord::Base
has_many :article_tags
has_many :articles, through: :article_tags
end
article_tag.rb
class ArticleTag < ActiveRecord::Base
belongs_to :article
belongs_to :tag
end
And I customized active admin like this.
ActiveAdmin.register Article do
permit_params :title, :description, :url, :image_url, :media, article_tags_attributes: [:article_id, :tag_id, :name, :_destroy, :_edit]
form do |f|
# f.semantic_errors *f.object.errors.keys
f.inputs "Admin Details" do
f.input :title
f.input :description
f.input :url
f.input :image_url
f.input :media
f.input :publish
end
f.inputs "Articles" do
f.has_many :article_tags do |t|
t.input :tag
end
end
f.actions
end
end
But after I saved the article with tag once I can`t update tag or delete tag...
Does anyone know how to fix this?
You forgot to permit :id attribute of article_tag object. It is passed when updating/deleting existing nested object.
ActiveAdmin.register Article do
permit_params :title, :description, :url, :image_url, :media, article_tags_attributes: [:id, :article_id, :tag_id, :name, :_destroy, :_edit]
...
end
I have a many-to-many relationship set up between blog posts and blog categories using the has_many :through relationship and I am having trouble creating a blog post resource through active admin.
class BlogPost < ActiveRecord::Base
attr_accessible :body, :created_at, :updated_at, :image_url, :title
validates :body, :image_url, :title, presence: true
validates :title, uniqueness: true
has_many :blog_post_categorizations
has_many :blog_categories, :through => :blog_post_categorizations
accepts_nested_attributes_for :blog_categories, allow_destroy: true
end
class BlogCategory < ActiveRecord::Base
attr_accessible :id, :name, :created_at, :updated_at
validates :name, presence: true, uniqueness: true
has_many :blog_post_categorizations
has_many :blog_posts, :through => :blog_post_categorizations
accepts_nested_attributes_for :blog_posts, allow_destroy: true
end
class BlogPostCategorization < ActiveRecord::Base
belongs_to :blog_post
belongs_to :blog_category
end
Now as for my activeadmin formtastic setup, I have:
ActiveAdmin.register BlogPost do
form do |f|
f.inputs "Blog Post" do
f.input :title
f.input :body, as: :html_editor
f.input :image_url
end
f.inputs "Blog Categories" do
f.has_many :blog_categories do |s|
s.input :name
end
end
f.actions
end
end
This allows the new blog post page to load successfully, but when I attempt to submit the new post with categories attached, it results in a "Can't mass-assign protected attributes: blog_categories_attributes" error.
I suspect that my models are set up properly, but the form in ActiveAdmin is not. Any ideas as to how I can correctly set up the form?
Additionally, included below is the blog_category data that's being sent in the params hash of the POST request
"blog_categories_attributes"=>{"1408936652467"=>{"name"=>"cooking"}, "1408936656066"=>{"name"=>"eat"}}
Using Rails version 3.2
I have 3 models
User
Business (acts_as_commentable using acts_as_commentable gem)
Comment (belongs to user)
On the Business show page I display all the comments associated with that business:
Name:<%= #business.name %>
<%= render #business.comments %>
comments partial
Comment: <%= comment.comment %><br >
By: <%= User.find(comment.user_id).name %>
Is there a better way to display the name of the user instead of using User.find?
Here are my models
User
class User < ActiveRecord::Base
attr_accessible :email, :name
end
Business
class Business < ActiveRecord::Base
attr_accessible :name, :category
has_reputation :votes, source: :user, aggregated_by: :sum
acts_as_commentable
end
Comment
class Comment < ActiveRecord::Base
include ActsAsCommentable::Comment
attr_accessible :comment, :user_id
belongs_to :commentable, :polymorphic => true
default_scope :order => 'created_at ASC'
belongs_to :user
validates :user_id, presence: true
end
I believe you can just use this:
<%= comment.user.name %>
Rails will handle loading for you.
Each comment belongs to a user. So, you just have to get the user this way
comment.user.name
I think the best way is:
<%= comment.user.try(:name) %>
I see you have validates :user_id, presence: true to have user. But if the use has deleted, comment.user.name will put the error.
Or you can use:
<%= comment.user.blank? ? "Visitor" : comment.user.name %>
I have two models, Artist and User that are connected through a third model, ArtistMembership.
From the edit/new Artist form, I want to be able to edit the role of any User in an existing ArtistMembership relationship for that Artist, delete ArtistMemberships, and add new AtistMembership relationships, which would include a User and :role.
Here's my Artist model:
class Artist < ActiveRecord::Base
has_many :artist_memberships, foreign_key: "artist_id", dependent: :destroy
attr_accessible :bio, :created_at, :email, :location, :name, :updated_at, :website, :pic
accepts_nested_attributes_for :artist_memberships, :allow_destroy => :true
...
end
Here's my User model:
class User < ActiveRecord::Base
...
has_many :artist_memberships, foreign_key: "user_id"
...
end
Here's my ArtistMembership model:
class ArtistMembership < ActiveRecord::Base
belongs_to :artist, class_name: "Artist"
belongs_to :user, class_name: "User"
attr_accessible :artist_id, :created_at, :role, :user_id
end
If I have a _form.hml.erb too, for editing Artists that starts:
<%= form_for #artist do |artist_form| %>
<div class="field">
<%= artist_form.label :name %>
<%= artist_form.text_field :name %>
</div>
..
<div class="actions">
<%= artist_form.submit %>
</div>
<% end %>
how can I create the related ArtistMembership forms for the aforementioned functionality?
May be this is helpful for you, see this field_for
you can use accepts_nested_attributes_for(*attr_names)
Maybe you are looking for this method.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
Refer to the "One-to-many" section.
But if I were you, I would rather use the "Nested Resource" technic.
http://guides.rubyonrails.org/routing.html#nested-resources
In my Rails application, I am attempting to set up creation form for a TrainingClass model. I want this form to allow the user to create multiple ClassMeeting models (which have a belongs_to relationship with the TrainingClass model) within the same form, and I am using accepts_nested_attributes_for to do this. Unfortunately, whenever I submit the form I get the error message: Meetings class can't be blank.
I realize that this is because ClassMeeting has validates :class_id, presence: true, and because TrainingClass can't have an id until after it is saved, but I'm not sure of the right way to get around this. (I can think of a few possible ways, but they aren't exactly elegant solutions.) Any ideas? I'd appreciate any help you can give me.
Note: I realize quite a few questions similar to this have been asked in the past. However, most of those questions are old and have outdated answers, and none of them solved my problem.
Here is my code. Keep in mind that although I have simplified some aspects of it for brevity, the relationship between the ClassMeeting and TrainingClass models was left untouched:
ClassMeeting Model:
# == Schema Information
#
# Table name: class_meetings
#
# id :integer not null, primary key
# class_id :integer
# start :datetime
# end :datetime
# location :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class ClassMeeting < ActiveRecord::Base
attr_accessible :start, :end, :location
validates :class_id, presence: true
validates :start, presence: true
validates :end, presence: true
validates :location, presence: true, length: {maximum: 255}
belongs_to :training_class, foreign_key: :class_id, inverse_of: :meetings
end
TrainingClass Model:
# == Schema Information
#
# Table name: training_classes
#
# id :integer not null, primary key
# description :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class TrainingClass < ActiveRecord::Base
attr_accessible :description, :meetings_attributes
validates :description, length: {maximum: 255}
has_many :meetings, class_name: :ClassMeeting, foreign_key: :class_id, inverse_of: :training_class
accepts_nested_attributes_for :meetings, allow_destroy: true
end
TrainingClasses Controller:
class TrainingClassesController < ApplicationController
def new
#training_class = TrainingClass.new()
#training_class.meetings.build
end
def create
#training_class = TrainingClass.new()
if #training_class.update_attributes(params[:training_class])
redirect_to #training_class, notice: 'Class was successfully created.'
else
render "new"
end
end
end
TrainingClass Form (View):
<%= form_for #training_class do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_area :description %>
<h2>Schedule</h2>
<%= f.fields_for :meetings do |meeting| %>
<%= meeting.label :start, "Start of Meeting:" %>
<%= meeting.text_field :start %>
<%= meeting.label :end, "End of Meeting:" %>
<%= meeting.text_field :end %>
<%= meeting.label :location, "Location:" %>
<%= meeting.text_field :location %>
<% end %>
<%= f.submit class:"btn btn-large btn-primary" %>
<% end %>
All right, I found the solution to my problem. All I need to do is validate the presence of training_class instead of class_id in the ClassMeeting model. That way the existence of a training class is still validated, but the validator doesn't interfere with accepts_nested_attributes_for's method of saving the model:
class ClassMeeting < ActiveRecord::Base
attr_accessible :start, :end, :location
validates :training_class, presence: true # :training_class instead of :class_id
validates :start, presence: true
validates :end, presence: true
validates :location, presence: true, length: {maximum: 255}
belongs_to :training_class, foreign_key: :class_id, inverse_of: :meetings
end
I pored over this example, trying out the differences with my code, but in the end my problem was fixed by using :inverse_of.
See accepts_nested_attributes_for child association validation failing