Creating nested attribute with two parent attribute.
Hi,
Been going round in circles for a day or so but still can't seem to find a solution for this. I have project management chat app that on sign up, you create the project and the first chat message too. Here is my code:
user.rb
class User < ApplicationRecord
has_many :projects, inverse_of: :user, dependent: :destroy
has_many :messages, as: :message_owner, dependent: :destroy
accepts_nested_attributes_for :projects
validates :email, presence: true
validates :password, presence: true
validates_associated :projects
end
project.rb
class Project < ApplicationRecord
has_many :messages, inverse_of: :project, dependent: :destroy
belongs_to :user, inverse_of: :projects
accepts_nested_attributes_for :messages
validates :name, presence: true
end
message.rb
class Message < ApplicationRecord
belongs_to :project, inverse_of: :messages
belongs_to :message_owner, polymorphic: true
default_scope { order(:created_at) }
validates :body, presence: true
end
registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def new
build_resource({})
self.resource.build_user_profile
project = self.resource.projects.new
project.messages.new
respond_with self.resource
end
def create
super
end
private
def sign_up_params
params.require(resource_name).permit(:email,
{ user_profile_attributes: [:name],
projects_attributes: [:name, :material, messages_attributes: [:body]]
})
end
end
new.html.haml
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
/ Fields for project
= f.fields_for :projects do |project|
.field
= project.label :name, "Project Name"
= project.text_field :name
/ Fields for message
= project.fields_for :messages do |message|
.fields
= message.label :body, "Your Message"
= message.text_area :body
/ Fields for user registration
.field
= f.label :email
= f.email_field :email
.actions
= f.submit "Sign up"
I get the error that there is no associated message_owner (user). I know that this is because the fields_for is with respect to the project and has no knowledge of the user.
The problem comes as I can only associate the message with either one (project) of the other (user) but not both. I have tried creating messages as a nested attribute of user but this results in the problem of no associated project. I've tried initialising the message with a user in the registrations_controller#new but this does not seem to register either.
Could this be solved with a before_save callback in message.rb? But this will need to ensure that both the user and project are already created.
Hope someone can help. Thanks!
Managed to solve it after much tinkering. If anyone has the same problem, I called a before_validation to associate the message with the project in user.rb.
private
def set_project
self.messages.first.project = self.projects.first
end
Also changed messages to be a nested attribtue to user from projects