random_user_0891
random_user_0891

Reputation: 2051

many-to-many with multiple select in Rails

I have a model called Article, another model called Organization, and a join table called ArticleAllowedOrganization that has an article_id and organization_id in it.

When a user creates an article I would like for them to specify which organizations should have access to the article.

When I test in the console it seems to be working correctly, however, when I create an article in the web app the params for the through association allowed_organization_ids is empty.

Article model:

class Article < ActiveRecord::Base
  has_many :article_allowed_organizations, dependent: :destroy
  has_many :allowed_organizations, through: :article_allowed_organizations, source: :organization
end

Organization model:

class Organization < ActiveRecord::Base
    has_many :article_allowed_organizations, dependent: :destroy
    has_many :allowed_articles, through: :article_allowed_organizations, source: :article
end

the join table:

class ArticleAllowedOrganization < ActiveRecord::Base
  belongs_to :article
  belongs_to :organization
end

in the articles_controller.rb I permitted the array for allowed_organization_ids

def article_params
  params.require(:article).permit(:other_stuff, :allowed_organization_ids => [])
end

In the form:

  <%= f.collection_select(:allowed_organization_ids, Organization.order(:name), :id, :name,
                                    {include_blank: true}, {multiple: true}) %> 

In the console I can manually set multiple organization id's to be associated with an article and it works.

     a = Article.last
     a.allowed_organization_ids = [2, 4]

you can see below that it inserts the ids for an organization into the ArticleAlllowedOrganization table when I use the console.

 (0.3ms)  BEGIN
  SQL (1.3ms)  INSERT INTO "article_allowed_organizations" ("article_id", "organization_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["article_id", 95], ["organization_id", 4], ["created_at", "2018-12-12 17:47:25.978487"], ["updated_at", "2018-12-12 17:47:25.978487"]]
   (6.5ms)  COMMIT
=> [2, 4]

when using the web app I get this in the log where the allowed_organization_ids isn't passing anything.

  Parameters: {"....some_other_params" "allowed_organization_ids"=>[""]}

if I try and use collection_check_boxes

  <%= f.collection_check_boxes :allowed_organization_ids, Organization.all, :id, :name do |b| %>
     <div class="collection-check-box">
       <%= b.check_box %>
       <%= b.label %>
     </div>
 <% end %>

I get this in the log when using collection_check_boxes where it says true instead of the organization ids

"allowed_organization_ids"=>["true"]

also what's interesting is that I also get the below in th elog when trying to use checkboxes where it's trying to find an organization that has an id of 0 but can't which prevents the form from submitting.

  [1m[35mOrganization Load (0.5ms)[0m  SELECT  "organizations".* FROM "organizations" WHERE "organizations"."id" = $1 LIMIT 1  [["id", 0]]
Completed 404 Not Found in 67ms (ActiveRecord: 2.4ms)

ActiveRecord::RecordNotFound (Couldn't find Organization with 'id'=0):

Upvotes: 1

Views: 1032

Answers (1)

Kamal Panhwar
Kamal Panhwar

Reputation: 2399

Please check follow are few issues. In your controller, you put

def article_params
  params.require(:article).permit(:other_stuff, :allowed_organization_ids => [])
end

So you are already saying your allowed_organization_ids is empty, please replace with following

def article_params
  params.require(:article).permit(:other_stuff, :allowed_organization_id)
end

I think you are just changing the name, so you have provided the different name of classes but here in the relationship you are mentioning different, but as your console is giving correct relationship this should not be an issue, but in case I am mentioning it.

class ArticleAllowedOrganization < ActiveRecord::Base
  belongs_to :article
  belongs_to :organization
end

should be allowed_article and allowed_organization

I am practicing so I created this in the project to see if it is working with proper names, so following are commands I used in the generator to create this whole project. You can try to see if there is any other error. Note I put permission field in the allowed table, all commands are on command line inside your project first command will create new project.

  rails new SampleProject && cd $_ && bundle 

  rails g model Article title:string description:text
  rails g model Organization name:string
  rails g model Allowed permission:string article:references organization:references

Now make sure your Article model has following.

class Article < ActiveRecord::Base
  has_many :alloweds
  has_many :organizations, through: :alloweds
end

And in your Organization model

class Organization < ActiveRecord::Base has_many :alloweds has_many :articles, through: :alloweds end

And in your allowed model, although I will use permission than allowed table name but it is your naming.

class Allowed < ActiveRecord::Base
 belongs_to :article
 belongs_to :organization
end

Now let us generate views and controllers

rails g scaffold_controller Article title:string description:string
rails g scaffold_controller Organization name:string
rails g scaffold_controller Article title:string description:string

Now put routes in your config/routes.rb

resources :articles
resources :organizations
resources :alloweds

Now you can start your rail server and navigate to /articles , /organization and /alloweds to see it working. Rails auto generator uses text field for relationship ids, so you can put manually ids and it will work.

Hope it is clear.

Upvotes: 1

Related Questions