I have been (hours) trouble with associations in Rails. I found a lot of similar problems, but I couldn't apply for my case:
City's class:
class City < ApplicationRecord
  has_many :users
end
User's class:
class User < ApplicationRecord
  belongs_to :city
  validates :name, presence: true, length: { maximum: 80 }
  validates :city_id, presence: true
end
Users Controller:
def create
    Rails.logger.debug user_params.inspect
    @user = User.new(user_params)
    if @user.save!
      flash[:success] = "Works!"
      redirect_to '/index'
    else
      render 'new'
    end
 end
def user_params
  params.require(:user).permit(:name, :citys_id)
end
Users View:
<%= form_for(:user, url: '/user/new') do |f| %>
  <%= render 'shared/error_messages' %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.label :citys_id, "City" %>
  <select name="city">
    <% @city.all.each do |t| %>
      <option value="<%= t.id %>"><%= t.city %></option>
    <% end %>
  </select>
end
Migrate:
class CreateUser < ActiveRecord::Migration[5.0]
  def change
    create_table :user do |t|
      t.string :name, limit: 80, null: false
      t.belongs_to :citys, null: false
      t.timestamps
  end
end
Message from console and browser:
ActiveRecord::RecordInvalid (Validation failed: City must exist):
Well, the problem is, the attributes from User's model that aren't FK they are accept by User.save method, and the FK attributes like citys_id are not. Then it gives me error message in browser saying that "Validation failed City must exist".
Thanks
Try the following:
belongs_to :city, optional: true
According to the new docs:
4.1.2.11 :optional
If you set the :optional option to true, then the presence of the associated object won't be validated. By default, this option is set to false.
This comes a bit late but this is how to turn off this by default in rails 5:
config/initializers/new_framework_defaults.rb
Rails.application.config.active_record.belongs_to_required_by_default = false
In case you don't want to add optional: true to all your belongs_to.
I hope this helps!
You need to add the following to the end of the belongs_to relationship statement:
optional: true
It is possible to set this on a global level so that it works in the same way as older versions of rails, but I would recommend taking the time to manually add it to the relationships that really need it as this will cause less pain in the future.
I found out a solution to the problem "Validation failed: Class must exist" and it's better than use:
belongs_to :city, optional: true
4.1.2.11 :optional
If you set the :optional option to true, then the presence of the associated object won't be validated. By default, this option is set to false.
cause you still make a validation in application level. I solve the problem making my own validation in create method and changing user_params method:
def create
  @city = City.find(params[:city_id])
  Rails.logger.debug user_params.inspect
  @user = User.new(user_params)
  @user.city_id = @city.id
  if @user.save!
    flash[:success] = "Works!"
    redirect_to '/index'
  else
    render 'new'
  end
end
def user_params
  params.require(:user).permit(:name)
end
I didn't test this code, but it works in another project mine. I hope it can help others!
Rails 5
If you have a belongs_to relationship to :parent then you have to pass an existing parent object or create a new one then assign to children object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With