Ruby创建Job时「company must exist」报错及参数传递问题求助
Hey there! Let's break down this problem step by step—since you're new to Ruby on Rails, I'll keep things clear and actionable so you can fix this quickly.
The company must exist error usually starts here. Rails uses associations to link models, so we need to make sure your Job belongs to a Company, and vice versa.
In app/models/job.rb:
class Job < ApplicationRecord # Rails 5+ requires belongs_to associations to be present by default belongs_to :company # Add optional: true here only if you want jobs to exist without a company (not recommended for your current error) # belongs_to :company, optional: true # Add any other validations or methods here end
In app/models/company.rb:
class Company < ApplicationRecord has_many :jobs # This lets a company have multiple jobs end
company_id Your Job table needs a company_id field to store the link to a Company. Let's confirm that's set up:
Look at your Job migration file (located in db/migrate/ with a name like xxxxxx_create_jobs.rb). It should include:
class CreateJobs < ActiveRecord::Migration[6.1] def change create_table :jobs do |t| t.string :title t.text :description # This line creates the company_id field, sets it to NOT NULL, and adds a foreign key t.references :company, null: false, foreign_key: true t.timestamps end end end
If you don't have this field, generate a new migration to add it:
rails generate migration AddCompanyIdToJobs company:references rails db:migrate
This is probably the main issue causing company_id/c_name not to reach your form. Rails requires you to explicitly allow parameters that get passed to your model (called "strong parameters").
In app/controllers/jobs_controller.rb:
First, update your create action to handle the parameters correctly:
def create # Initialize a new job with permitted parameters @job = Job.new(job_params) # If you're creating a job from a Company's show page (using nested routes), uncomment these lines: # @company = Company.find(params[:company_id]) # @job.company = @company # Try to save the job if @job.save redirect_to @job, notice: 'Job was successfully created!' else # If save fails, re-render the form with error messages render :new end end
Then add/update the private job_params method to allow the fields you need:
private def job_params # Permit all fields you're using in your form—add :c_name here if you're passing it params.require(:job).permit(:title, :description, :company_id, :c_name) end
Note About c_name:
If c_name is the name of a Company (not a field on the Job model), you can't pass it directly to the Job. Instead, you need to find the Company by name first in the create action:
def create # Extract c_name from params and remove it from job_params company_name = params[:job][:c_name] @job = Job.new(job_params.except(:c_name)) # Find the company by name @company = Company.find_by(name: company_name) if @company @job.company = @company else @job.errors.add(:company, "can't be found with that name") end if @job.save redirect_to @job, notice: 'Job was successfully created!' else render :new end end
jobs/_form.html.erb Make sure your form is sending the correct parameters. Here are two common scenarios:
Scenario 1: Let users select an existing Company (recommended)
<%= form_with(model: @job, local: true) do |form| %> <% if @job.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@job.errors.count, "error") %> prevented this job from saving:</h2> <ul> <% @job.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= form.label :title %> <%= form.text_field :title %> </div> <div class="field"> <%= form.label :description %> <%= form.text_area :description %> </div> <!-- Dropdown to select a company --> <div class="field"> <%= form.label :company_id %> <%= form.collection_select :company_id, Company.all, :id, :name, prompt: "Choose a company" %> </div> <div class="actions"> <%= form.submit %> </div> <% end %>
Scenario 2: Let users enter a Company name (if you're using c_name)
<%= form_with(model: @job, local: true) do |form| %> <!-- ... other form fields ... --> <div class="field"> <%= form.label :c_name, "Company Name" %> <%= form.text_field :c_name %> </div> <div class="actions"> <%= form.submit %> </div> <% end %>
- Check server logs: When you submit the form, look at your Rails server console. You'll see the parameters being sent—make sure
company_idorc_nameis inside thejobhash (e.g.,Parameters: {"job"=>{"title"=>"Dev Job", "company_id"=>"1"}, ...}). - Use browser dev tools: Go to the Network tab in your browser's dev tools, find the POST request to
/jobs, and check the Form Data section to confirm parameters are being sent correctly.
内容的提问来源于stack exchange,提问作者kethianu

