Setting an addional attribute on the join model in a has_many through relationship

I have User, Account, and Role models. The Account model accepts nested
properties for users. This way users can create their account and user
records at the same time.

class AccountsController < ApplicationController
def new
@account = Account.new
@user = @account.users.build
end
end

The above will work, but the user.roles.type defaults to member. At the
time of registration, I needuser.roles.type to default to admin. This
does
not work:

class AccountsController < ApplicationController
def new
@account = Account.new
@role = @account.role.build
# Role.type is protected; assign manually
@role.type = “admin”
@user = @account.users.build
end
end

I thought about inheritance, but it really complicate things. I need
roles
to be dynamic so users can add their own admins and mods, and so on. I
think I’m running into these issues because I’m not modeling my data
modeling correctly.
Accounts#new

<%= simple_form_for(@account, html: { class: ‘form-horizontal’ }) do |f|
%>

Account Details <%= render 'account_fields', f: f %>

<%= f.simple_fields_for :users do |user_form| %>
Personal Details
<%= render ‘users/user_fields’, f: user_form %>
<% end %>

<%= f.submit t(‘views.accounts.post.create’), class: ‘btn btn-large
btn-primary’ %>
<% end %>

Models:

class User < ActiveRecord::Base
has_many :roles
has_many :accounts, through: :roles
end

class Account < ActiveRecord::Base
has_many :roles
has_many :users, through: :roles
accepts_nested_attributes_for :users
end

user_id, account_id, type [admin|moderator|member]

class Role < ActiveRecord::Base
belongs_to :user
belongs_to :account
after_initialize :init

ROLES = %w[owner admin moderator member]

private
def init
self.role = “member” if self.new_record?
end
end

My question can be succinctly put: Is it possible to set an additional
attribute on the join model when usingaccepts_nested_attributes_for?

On 1 May 2012 17:05, Mohamad El-Husseini [email protected] wrote:

@user = @account.users.build
end
end

It depends what you mean by ‘work’. It will assign the type of @role
to “admin” but the problem is that you have not saved it to the
database after changing the type. By the way, I advise against using
type as an attribute name, that is a reserved attribute name for use
with STI.

self.role = “member” if self.new_record?
end
end

Should that not be self.type (apart from the fact that type is not a
good name)? But if you want a default value for a column why not just
set the default in the database?

Colin

It depends what you mean by ‘work’. It will assign the type of @role
to “admin” but the problem is that you have not saved it to the
database after changing the type. By the way, I advise against using
type as an attribute name, that is a reserved attribute name for use
with STI.

I did change type to role. I get this rather mysterious error: Roles
en-US, activerecord.errors.models.account.attributes.roles.invalid

def create
@account = Account.new(params[:account]) # we don’t need @user
since
it’s in params[:account]
@role = @account.roles.build
@role.role = “owner”
end

Should that not be self.type (apart from the fact that type is not a
good name)? But if you want a default value for a column why not just
set the default in the database?

It should, I made the changes in the middle of typing my question. I can
add a default value to the db. But I want the be able to set the value
depending on content: when a user registers with a new account; when an
existing user adds a moderator to his account, etc…

On 1 May 2012 22:53, Mohamad El-Husseini [email protected] wrote:

It depends what you mean by ‘work’. It will assign the type of @role
to “admin” but the problem is that you have not saved it to the
database after changing the type.

You have not responded to the point above

By the way, I advise against using
type as an attribute name, that is a reserved attribute name for use
with STI.

I did change type to role. I get this rather mysterious error:Roles en-US,
activerecord.errors.models.account.attributes.roles.invalid

Come back with more detail on this problem if it still exists. Post
the full error message and show which line of code it relates to.

Colin

On Wednesday, May 2, 2012 2:35:02 AM UTC-4, Colin L. wrote:

On 1 May 2012 22:53, Mohamad El-Husseini [email protected] wrote:

It depends what you mean by ‘work’. It will assign the type of @role
to “admin” but the problem is that you have not saved it to the
database after changing the type.

You have not responded to the point above

After another day wasted, I figured out what is happening, but not why.
I
was misled by the false impression that Rails always saved the joiner
model automatically. This is not the case. With this following code
snippet
Rails automatically creates the Role (joiner) record. But the snippet
below
it Rails does not. And although I don’t know why, this is how Rails
works.

def new
@account = Account.new(params[:account])
@user = @account.users.build
end
def new
@account = Account.new(params[:account])
@account.save
end

This here does not save the Role record: (Interestingly, replace
current_user.accounts.build with current_user.accounts.create and Rails
will save the Role record)

def new
@account = current_user.accounts.build
end
def create
@account = current_user.accounts.build(params[:account])
@account.save
end

It’s not a validation issue either. I created a blank application to
test
this and the results were consistent.