Brief overview of my app.
It's quite basic in that the User first of all creates a set A client on one page and then uses another to create and assign jobs to the user.
My Client model and view are working as expected but im unable to link my jobs model.
Here is my jobs model.
class Client < ActiveRecord::Base
has_and_belongs_to_many :jobs
end
class Job < ActiveRecord::Base
has_and_belongs_to_many :clients
end
Here is also my clients controller.
class JobsController < ApplicationController
def index
#jobs = Job.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #job }
end
end
def new
#jobs = Job.new
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #job }
end
end
def create
#jobs = Job.new(params[:job])
respond_to do |format|
if #jobs.save
format.html { redirect_to #jobs, notice: 'Job was successfully created.' }
format.json { render json: #jobs, status: :created, location: #jobs }
else
format.html { render action: "new" }
format.json { render json: #jobs.errors, status: :unprocessable_entity }
end
end
end
def show
#jobs = Job.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #jobs }
end
end
end
In my form I have two fields. One for the job name and another which is a drop down on all the clients listed in the database.
When fill this out however and I press save im getting the following error.
ActiveRecord::UnknownAttributeError in JobsController#create
**unknown attribute: client_id**
Application Trace | Framework Trace | Full Trace
app/controllers/jobs_controller.rb:22:in `new'
app/controllers/jobs_controller.rb:22:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"0ZVYpM9vTgY+BI55Y9yJDwCJwrwSgGL9xjHq8dz5OBE=",
"job"=>{"name"=>"Sample Monthly",
"client_id"=>"1"},
"commit"=>"Save Job"}
I have a junction table setup called clients_jobs also..
class AddClientsJobsTable < ActiveRecord::Migration
def up
create_table :clients_jobs, :id => false do |t|
t.belongs_to :job, :client
t.integer :client_id
t.integer :job_id
end
end
def down
drop_table :clients_jobs
end
end
I assume I need to declare client_id
somewhere but this is my first Rails app and im not sure where.
Any help would be greatly appreciated.
Edit: Here's my Job's form.
<%= simple_form_for :job do |f| %>
<%= f.input :name %>
<%= select("job", "client_id", Client.all.collect {|c| [ c.name, c.id ] }, {:include_blank => 'None'})%>
<%= f.button :submit %>
<% end %>
Your model states that job - client is a habtm association, but your form implements as if job belongs to (one) client. If indeed your intention is to be able to assign a job to multiple clients, your for should look something like:
<%= collection_select(:job, :client_ids, Client.all, :id, :name, {:include_blank => 'None'}, { :multiple => true }) %>
note plural 'client_ids' and allowing multiple in the input.
If a job belongs to only one user, you should not use has_and_belongs_to_many :clients.
Related
I'm relatively new to Rails. I'm trying to create an application that can allow users to create video game items and store them under their own users. I'm using the latest version of Rails and Devise.
Using scaffolding as a base, I created the Videogame model/controller within my application. After linking the video game models to the user who created them, it seems that any attributes that are entered into the creation form are not saving, or at the very least just not showing up on the videogames/index page. After trying to search around on Google and StackOverflow, I couldn't find any similar questions/guides to work with.
Any ideas on how to fix this? Any help for a Rails newbie would be greatly appreciated.
Below I've posted all files that may be relevant. Please let me know if anything else is needed. To see the whole project, see http://github.com/bmmart2/collection-manager
Image after item creation
Index page of two created items
Here is my controller:
class VideogamesController < ApplicationController
before_action :set_videogame, only: [:show, :edit, :update, :destroy]
# GET /videogames
# GET /videogames.json
def index
if user_signed_in?
#videogame = current_user.videogames.all
else
redirect_to :root
end
end
# GET /videogames/1
# GET /videogames/1.json
def show
end
# GET /videogames/new
def new
#videogame = current_user.videogames.new
end
# GET /videogames/1/edit
def edit
end
# POST /videogames
# POST /videogames.json
def create
#videogame = current_user.videogames.create(videogame_params)
respond_to do |format|
if #videogame.save
format.html { redirect_to #videogame, notice: 'Videogame was successfully created.' }
format.json { render :show, status: :created, location: #videogame }
else
format.html { render :new }
format.json { render json: #videogame.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /videogames/1
# PATCH/PUT /videogames/1.json
def update
respond_to do |format|
if #videogame.update(videogame_params)
format.html { redirect_to #videogame, notice: 'Videogame was successfully updated.' }
format.json { render :show, status: :ok, location: #videogame }
else
format.html { render :edit }
format.json { render json: #videogame.errors, status: :unprocessable_entity }
end
end
end
# DELETE /videogames/1
# DELETE /videogames/1.json
def destroy
#videogame.destroy
respond_to do |format|
format.html { redirect_to videogames_url, notice: 'Videogame was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_videogame
#videogame = Videogame.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def videogame_params
params.require(:videogame).permit(:title, :publisher, :platform, :year, :condition, :upc)
end
end
Videogame model:
class Videogame < ApplicationRecord
belongs_to :user
attr_accessor :title, :platform, :upc, :condition, :publisher, :year
end
Videogame db migration file:
class CreateVideogames < ActiveRecord::Migration[5.2]
def change
create_table :videogames do |t|
t.string :title
t.string :publisher
t.integer :condition
t.string :platform
t.string :year
t.string :upc
t.timestamps
end
add_index :videogames, :user_id
end
end
add_user_refs_to_videogame migration:
class AddUserRefsToVideogame < ActiveRecord::Migration[5.2]
def change
add_reference :videogames, :user, foreign_key: true
end
end
Edit: show view for video game
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= #videogame.title %>
</p>
<p>
<strong>Publisher:</strong>
<%= #videogame.publisher %>
</p>
<p>
<strong>Platform:</strong>
<%= #videogame.platform %>
</p>
<p>
<strong>Year:</strong>
<%= #videogame.year %>
</p>
<p>
<strong>Condition:</strong>
<%= #videogame.condition %>
</p>
<p>
<strong>Upc:</strong>
<%= #videogame.upc %>
</p>
<%= link_to 'Edit', edit_videogame_path(#videogame) %> |
<%= link_to 'Back', videogames_path %>
I believe the attr_accessor line in your videogame.rb file is causing the problem. Try deleting it and see if that fixes the problem.
I am new to rails and am trying to create multiple entries in a table through my Test and TestQuestions models without success. Ultimately I would like to select 50 questions based on their category. I am stuck at this step, trying to pass category_id parameters to update my test_questions table from the TestController / Test Model.
The commented out line in the controller below: "#test.test_questions.build(:question_id => 5).save" works to make one question number 5, but when I call #test.build_category_test!(category_params).save instead to call a method and pass an array,I get the error undefined method `build_category_test!' for #Test:0x000000047f0928
Models
class TestQuestions < ActiveRecord::Base
belongs_to :test
end
class Test < ActiveRecord::Base
has_many :test_questions, class_name: "TestQuestions",
foreign_key: "test_id"
def self.build_category_test!(category_ids)
unless category_ids.blank?
category_ids.each do |u|
test_questions.build!(:question_id => 5)
end
end
end
end
Controller
class TestsController < ApplicationController
def create
#test = Test.new(test_params)
respond_to do |format|
if #test.save
##test.test_questions.build(:question_id => 5).save
#test.build_category_test!(category_params).save
format.html { redirect_to #test, notice: 'Test was successfully created.' }
format.json { render action: 'show', status: :created, location: #test }
else
format.html { render action: 'new' }
format.json { render json: #test.errors, status: :unprocessable_entity }
end
end
def category_params
params[:category][:category_ids]
end
end
View of test/new.html.erb
<%= form_tag tests_path, :method => :post do %>
<%= hidden_field_tag "user_id", #user_id %>
<ul>
<% for c in #categories %>
<li>
<%= check_box_tag "category[category_ids][]", c.id %>
<%= c.category %>
</li>
<% end %>
</ul>
<%= submit_tag "Create Test" %>
Log of parameters: "user_id"=>"1", "category"=>{"category_ids"=>["1", "2"]}, "commit"=>"Create Test"}
The method build_category_test! should be an instance method:
def build_category_test!(category_ids) # #test.build_category_test!
Instead of a class method:
def self.build_category_test!(category_ids) # Test.build_category_test!
I have a formfield in my form like this:
<div class="tags">
<%= f.label :tags %>
<%= f.text_area :tags %>
</div>
I ran a migration like this:
class AddTagsToIssues < ActiveRecord::Migration
def change
add_column :issues, :tags, :text
end
end
When i save, the new row is added to db, but tags = nil, although I typed something like 'test' in de text_area
in my development log I have:
Unpermitted parameters: tags
I have tried whitelisting in my controller:
def create
#issue = Issue.new(issue_params)
Issue.new(params.permit(:tags))
but this doesn't work.
Update for follow up question:
Full create method:
def create
def issue_params
params.require(:issue).permit(:tags)
end
#issue = Issue.new(issue_params)
Issue.new(params.permit(:tags))
respond_to do |format|
if #issue.save
format.html { redirect_to #issue, notice: 'Issue was successfully created.' }
format.json { render action: 'show', status: :created, location: #issue }
else
format.html { render action: 'new' }
format.json { render json: #issue.errors, status: :unprocessable_entity }
end
end
end
The model:
class Issue < ActiveRecord::Base
belongs_to :project
end
The table create query:
class CreateIssues < ActiveRecord::Migration
def change
create_table :issues do |t|
t.string :title
t.text :description
t.integer :no_followers
t.timestamps
end
end
end
So with this I don't have permission problems, that only happened with the later adding of the tags, and then only with the tags.
tags is being set as nil because you have not permitted it.
Permit tags in the issue_params method as below:
def issue_params
params.require(:issue).permit(:tags,...)
end
where, ... refers to other fields in model Issue.
Your create action should look something like this,
def create
#issue = Issue.new(issue_params) ## issue_params called
if #issue.save ## save the record
redirect_to #issue, notice: 'Issue was successfully created.'
else
render action: 'new'
end
end
I have two models jobs and clients.
A user can simple create a client and then assign them a number of jobs.
Here's my models for both.
job.rb
class Job < ActiveRecord::Base
has_and_belongs_to_many :clients
end
client.rb
class Client < ActiveRecord::Base
has_and_belongs_to_many :jobs
end
My form for creating a new job looks like this:
<%= simple_form_for :job do |f| %>
<%= f.input :name %>
<%= <%= collection_select(:job, :client_ids, Client.all, :id, :name, {:include_blank => 'None'}, { :multiple => true }) %>%>
<%= f.button :submit %>
<% end %>
So as you can see there is a drop down box on the form which contains all of the clients.
When try to save it however, I recieve this messed:
ActiveRecord::UnknownAttributeError in JobsController#create
unknown attribute: client_id
Application Trace | Framework Trace | Full Trace
app/controllers/jobs_controller.rb:22:in `new'
app/controllers/jobs_controller.rb:22:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"0ZVYpM9vTgY+BI55Y9yJDwCJwrwSgGL9xjHq8dz5OBE=",
"job"=>{"name"=>"Sample Monthly",
"client_id"=>"1"},
"commit"=>"Save Job"}
My job controller is quite basic and looks like this:
class JobsController < ApplicationController
def index
#jobs = Job.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #job }
end
end
def new
#jobs = Job.new
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #job }
end
end
def create
#jobs = Job.new(params[:job])
respond_to do |format|
if #jobs.save
format.html { redirect_to #jobs, notice: 'Job was successfully created.' }
format.json { render json: #jobs, status: :created, location: #jobs }
else
format.html { render action: "new" }
format.json { render json: #jobs.errors, status: :unprocessable_entity }
end
end
end
def show
#jobs = Job.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #jobs }
end
end
end
I have a junction table setup with both job_id and client_id as a integer value in them.
So I think its just a case of defining them in my controller under the new and create action like the error message suggests.
This is my first Rails app though sand im not quite sure how.
Any help would be greatly appreciated!
Problem might be in your form. Try to replace this
<%= <%= collection_select(:job, :client_ids, Client.all, :id, :name, {:include_blank => 'None'}, { :multiple => true }) %>%>
with
<%= f.association :clients %>
so the form will look like this
<%= simple_form_for #job do |f| %>
<%= f.input :name %>
<%= f.association :clients %>
<%= f.button :submit %>
<% end %>
I'm saving nested objects within the objects they belong to, but when i do that they do not use the controller im saving but the parents controller.
class Project < ActiveRecord::Base
belongs_to :company
belongs_to :user
has_many :tasks
accepts_nested_attributes_for :tasks, :allow_destroy => true
end
in the views i have something like this
<% form_for #project do |c| %>
<% c.fields_for :tasks, #project.tasks.last do |p| %>
<%= p.text_field :name %>
<% end %>
<%= submit_tag '+' %>
<% end %>
so what i'm trying to do, is update the user field with the fields for, that last field is specified in the controller.
def show
#project = Project.find(params[:id])
#project.tasks.build
#project.tasks.last.user = current_user # this should pass to the show.html.erb, to be saved back
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #project }
end
end
I'm thinking maybe the solution would be to check if the username is set in the nested objects, and if not to populate it with the current user in:
def update
#project = Project.find(params[:id])
#project.user = current_user
#find anything #project.....user blank and set to current user
respond_to do |format|
if #project.update_attributes(params[:project])
format.html { redirect_to(#project, :notice => 'Project was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #project.errors, :status => :unprocessable_entity }
end
end
end
I'm hoping that is the solution, and how do it do it?
an example of it running currently is at http://severe-fire-37.heroku.com