0

I have a bug, that is driving me crazy for a few days now....I set up a many to many relationship between users (created by devise) and parks through table user_parks. When I want to create a new park with a certain user, I get the error message: "undefined method `user=' for # Did you mean? users= users". Unfortunately, I am not able to find the mistake in my code that prevents me from creating the relationship between user and parks.

Schema

create_table "parks", force: :cascade do |t|
    t.text "name"
end

create_table "user_parks", force: :cascade do |t|
    t.bigint "park_id"
    t.bigint "user_id"
    t.index ["park_id"], name: "index_user_parks_on_park_id"
    t.index ["user_id"], name: "index_user_parks_on_user_id"
end

create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.integer "role"
end

  add_foreign_key "user_parks", "parks"
  add_foreign_key "user_parks", "users"
end

models

class Park < ApplicationRecord
  has_many :user_parks
  has_many :users, :through => :user_parks
end

class UserPark < ApplicationRecord
  belongs_to :park
  belongs_to :user
end

class User < ApplicationRecord
  has_many :user_parks
  has_many :parks, :through =>  :user_parks
  enum role: [:owner, :admin, :employee, :accountant]

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
end

Park policy

class ParkPolicy < ApplicationPolicy
  class Scope < Scope
    def resolve
     if user.admin?
        scope.where(user: user)
      end
    end
  end

  def index?
    user.admin?
  end

  def new?
    user.admin?
  end

  def create?
    user.admin?
  end
end

parks_controller

class ParksController < ApplicationController
  skip_before_action :authenticate_user!

  #create a new park
  def new
    @park = Park.new
    authorize @park
  end

  def create
    @user = current_user
    @park = Park.new(park_params)
    authorize @park
    @park.user = @user
    @park.save
    redirect_to parks_path
  end

  #edit park
  def edit
    @park = Park.find(params[:id])
  end

  def update
    @park = Park.find(params[:id])
    @park = Park.update(park_params)
    redirect_to parks_path
  end

  def index
    @user = current_user
    @parks = policy_scope(Park)
  end

private
  def park_params
    params.require(:park).permit(:name)
  end
end

new.html.erb (for park)

<%= simple_form_for ([@user, @park]) do |f|%>
  <%= f.input :name %>
  <%= f.submit "Add park", class: "btn btn-primary" %>
<% end %>

When I want to create a new park with a certain user, I get the error message: "undefined method `user=' for # Did you mean? users= users".

techquestion
  • 489
  • 5
  • 20
  • The error message is clear, you have many-to-many relationship, yet you try to set `user` instead of `users`. There's no such relationship as `user` in your `Park` model. – Marek Lipka Sep 03 '19 at 09:27

2 Answers2

1

You have has many association. Instead of @user.park you need to use @user.parks

The easiest way is to initialize park object before you initialize form

parks_controller

def new
  @park = current_user.parks.build
  authorize @park
end

def create
  @park = current_user.parks.create(park_params)
  redirect_to parks_path
end

new.html.erb (for park)

<%= simple_form_for(@park) do |f|%>
  <%= f.input :name %>
  <%= f.submit "Add park", class: "btn btn-primary" %>
<% end %>

you can check methods available for object with has many association here: docs

Yury Matusevich
  • 988
  • 12
  • 22
0

This is many-to-many relationship. Park doesn't have one user, it has a collection of them.

# parks_controller.rb

def create
  @user = current_user
  @park = Park.new(park_params)
  authorize @park
  @park.users << @user # here
  @park.save
  redirect_to parks_path
end
Steve Redka
  • 108
  • 1
  • 10