Search code examples
ruby-on-railsrubydevisepolymorphism

Belongs to user association with polymorphic routing


I have a small application where I have downtowns and I have properties. Each downtown has many properties and each property has one downtown.

In my controller I had things set to allow for any new properties to be created under the umbrella of a downtown but now I decided to add users into the mix..... The problem i'm having is getting an existing user the acknowledgements of owning one of the models it created.

My existing controller related methods are below. I was thinking the line by adding @property.user_id = current_user.id would take care of it. However if I then run a Property.last.user

I get a ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: users.property_id:

# GET /downtowns/1/properties/new
def new
  set_downtown
  @property = @downtown.properties.new
end

# POST /downtowns/1/properties
def create
  set_downtown
  @property = @downtown.properties.new(property_params)
  @property.user_id = current_user.id

  if @property.save
    redirect_to @downtown
  else
    render :new
  end
end

private

def set_downtown
  @downtown = Downtown.includes(:properties).find(params[:downtown_id])
end

In my models

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :properties
  has_many :downtowns
end

class Property < ApplicationRecord
  belongs_to :downtown
  belongs_to :user

  has_one :user  
end

Don't know if i need to paste this, but my routes files is

Rails.application.routes.draw do
  devise_for :users
  root :to => "downtowns#index"
  resources :cities

  resources :downtowns do
    resources :properties
  end
end

If anybody would be able to take a look at this, I truly would be grateful! Thank you so much!


Solution

  • class Property < ApplicationRecord
      belongs_to :downtown
      belongs_to :user
    end
    

    You want to use a belongs_to association as the foreign key column is on this model. The inverse of a has_many association is always a belongs_to association.

    If you declare two associations with the same name as you have done the later association will always overwrite the former.

    You also almost never need (or want) to explicitly use the _id= setter. Use the user= setter instead.

    before_action :set_downtown, only: [:new, :create, :index] # DRY
    
    # POST /downtowns/1/properties
    def create
      @property = @downtown.properties.new(property_params) do |p|
        p.user = current_user
      end
      if @property.save
        redirect_to @downtown
      else
        render :new
      end
    end