user4541806
user4541806

Reputation:

Rails - has_many :through association

I’ve setup a has_many :through association between a User and Organisation model, using a Membership model as the join.

class Organisation < ActiveRecord::Base
    has_many :memberships
    has_many :users, :through => :memberships
end

class User < ActiveRecord::Base
    . . .
    has_many :memberships
    has_many :organisations, :through => memberships
end

class Membership < ActiveRecord::Base
    belongs_to :user
    belongs_to :organisation
end

When a User creates an organisation, I want a membership to automatically be created linking the user to that organisation.

Where is the best place to attack this?

Options I’ve been investigating:

  1. Use an after_create callback on the organisation

  2. Move this process into a separate Ruby class.

  3. In the organisations Controller, create action.

  4. ?

How would you recommend I go about it?

Is there somewhere in the Rails Guides where it outlines best practices for this kind of thing?

Rails 4.2.5.

Upvotes: 1

Views: 1294

Answers (5)

Gupta
Gupta

Reputation: 10398

Where is the best place to attack this?

I would like to say you should write this in OrganisationsController's create action to make a DRY on update action as well(use strong parameter) .Because form attribute that you are getting is from outer worlds and it is best to use permit method on required params using Strong Parametre concept.

def create
   @organisation = Organisation.new(organisation_params)
   ...
end

def organisation_params
    # here you could write all the params which you want to permit from outer worlds
end

Nore more info about Strong Parameters

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76784

#config/routes.rb
resources :organizations #-> url.com/organizations/new

#app/controllers/organizations_controller.rb
class OrganizationsController < ApplicationController
   before_action :authenticate_user!

   def new
      @organization = current_user.organizations.new
   end

   def create
      @organization = current_user.organizations.new organization_params
      @organization.save
   end

   private

   def organization_params
      params.require(:organization).permit(:x, :y, :z) #-> membership automatically created
   end
end

The above will automatically create the associated membership; assuming you're using Devise & have access to the current_user method.

--

The best practice is the most succinct; there is no way you're "meant" to do it.

One of the biggest fallacies I see in Rails is people trying to find the most acceptable way to do something (as if there's a rulebook). The best thing you can do is get it working then refactor the code.

As you progress through your app, you'll find that certain patterns can be changed, some removed and many combined. The more "DRY" you make your code, the better it is (as a rule).

Upvotes: 1

T. M.
T. M.

Reputation: 58

If there isn't any additional logic other than creating an organization and membership, I would just do #3. However, if you are planning on adding more logic for creating a new organization in the future, I would create a new service (#2).

Upvotes: 0

Fiid
Fiid

Reputation: 1840

I think you should just be able to do something like:

org = Organisation.new
org.otherstuff = "populate other stuff"
org.users = [user_who_created]
org.save

After that the two should be related...? If you wanted to encapsulate this behavior you could do something like have a class method on Organization like create_org_for_user(name, user) and then do this logic in there, or you could do it in the controller action that handles the creation.

Upvotes: 0

huyhoang-vn
huyhoang-vn

Reputation: 335

My idea is way 3. Normaly, when set up many - many association in models, we should do creating temp table record auto through controller.
For example in controller you can write:

@organisation = current_user.organisations.build organisation_params
if @organisation.save
  ....

So that if @organisation is save then after that memberships record auto generate.
You can see this tutorial to see that:
http://blog.teamtreehouse.com/what-is-a-has_many-through-association-in-ruby-on-rails-treehouse-quick-tip

Upvotes: 0

Related Questions