Reputation: 12179
There is the following code:
def create
@business = user.businesses.build(business_params)
if @business.save
business.set_logo_url
redirect_to admin_businesses_path, flash: { notification: 'New business has been created successfully' }
else
render 'new'
end
end
Before this code works; user "has_many" businesses and all worked good, but now user "has_many :through" and this code created a new business but not relatiionship! How can I fix this code saving this business-logic? THanks in advance.
Upvotes: 2
Views: 2179
Reputation: 76774
but now user "has_many :through"
This is the core of the issue here - Rails does many things well, but it cannot read minds yet
The problem you have is that you're trying to build an association which either doesn't exist, or is part of another association (the :through
) argument. Let me explain:
has_many
When you .build
an object - it has to be associated to the "parent" object you're working with. The has_many
association is directly associated with the parent object, allowing you to .build
it singularly:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :businesses
end
This will give you the ability to perform the following: @user.businesses.build
The problem you have now is that using through
means your businesses
object is not directly associated to your parent User
- it's related through another object. This means that in order to build this deeper dependent object, you have first build the through
object:
through
You've not given us your associations, but say they were like so:
#app/models/user.rb
class User < ActiveRecord::Base
has_many :business_users
has_many :businesses, through: : business_users
end
#app/models/business.rb
class Business < ActiveRecord::Base
has_many :business_users
has_many :users, through: :business_users
end
#app/models/business_user.rb
class BusinessUser < ActiveRecord::Base
belongs_to :business
belongs_to :user
end
Now you'll have to build the associations slightly differently:
@user.business_users.build.build_business
See how you not have to call the "join" model?
Before, you could just call the businesses
association directly. But as you are going through another model, this will have to be built as well.
Form
Translating into a form, you'll end up with this setup:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
@user = User.new
@user.business_users.build.build_business
end
def create
@user = User.new user_params
@user.save
end
private
def user_params
params.require(:user).permit(:user, :params, business_users_attributes: [business_attributes: []])
end
end
#app/views/users/new.html.erb
<%= form_for @user do |f| %>
<%= f.fields_for :business_users do |bu| %>
<%= bu.fields_for :user do |u| %>
<%= u.text_field ... %>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
Upvotes: 4
Reputation: 7366
Try use create instead of build like this:
def create
@business = user.businesses.create(business_params)
if @business.save
business.set_logo_url
redirect_to admin_businesses_path, flash: { notification: 'New business has been created successfully' }
else
render 'new'
end
end
Upvotes: 0
Reputation: 1416
Try to add :inverse_of
in your User
model
class User < ActiveRecord::Base
has_many :business_types, inverse_of: :user #let your relationship model to be BusinessType
has_many :businesses, :through => :business_types
...
end
Also don't forget to add accepts_nested_attributes_for
in your relationship model too
Upvotes: 0