Updating an existing entry in my database isn't working - ruby-on-rails

I'm trying to use a list of clients that have been created from my client model in my new model called Jobs.
Basically. A user should be able to view a list of jobs that are currently assigned to any one client and then drill down into further information.
I have inserted a new column into my jobs database called client_id and have inserted the following code in my _form view to be able to see a drop down list of all the clients
<%= f.label :client_id %><br />
<%= f.collection_select :client_id, #clients, :id, :name, :prompt =>
"Select" %>
However. When I hit submit it tries to POST it to jobs/new which according to my resource route. Doesn't exist.
I have also inserted some dummy data into the database and though that is showing up fine when I try to edit it. Pressing save will not do anything to the record.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0ZVYpM9vTgY+BI55Y9yJDwCJwrwSgGL9xjHq8dz5OBE=", "job"=>{"name"=>"Sample Monthly", "client_id"=>"2", "frequency"=>"Monthly", "owner"=>"Me"}, "commit"=>"Save Job", "id"=>"1"}
Job Load (0.3ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."id" = ? LIMIT 1 [["id", "1"]]
(0.1ms) begin transaction
(0.5ms) UPDATE "jobs" SET "name" = 'Sample Monthly', "frequency" = 'Monthly', "updated_at" = '2012-05-12 17:04:23.818967' WHERE "jobs"."id" = 1
(108.3ms) commit transaction
Redirected to http://localhost:3000/jobs/1
Here's my controller..
class JobsController < ApplicationController
before_filter :load_clients, :only => [ :new, :create, :edit ]
def index
#job = Job.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #job }
end
end
def new
#job = Job.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #Job }
end
end
def create
#job = Job.new(params[:job])
respond_to do |format|
if #job.save
format.html { redirect_to #job, notice: 'Job was successfully created.' }
format.json { render json: #job, status: :created, location: #job }
else
format.html { render action: "new" }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
def show
#job = Job.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #job }
end
end
def update
#job = Job.find(params[:id])
respond_to do |format|
if #job.update_attributes(params[:job])
format.html { redirect_to #job, notice: 'Job was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
private
def load_clients
#client = Client.find(:all)
end
end
I suppose to get this working is a relatively easy fix but this is my forst Rails app and i'm not sure where to start.
Edit:
As requested. Here is my jobs form:
<%= form_for(:job) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :client_id %><br />
<%= f.collection_select :client_id, #client, :id, :name, :prompt =>
"Select" %>
</div>
<div class="field">
<%= f.label :frequency %><br />
<%= f.text_field :frequency %>
</div>
<div class="field">
<%= f.label :owner %><br />
<%= f.text_field :owner %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Edit2: Here's my Job model.
class Job < ActiveRecord::Base
belongs_to :clients
end

Try replace :job with #job in your form.
And also looks like you are missing edit action in your controller.

Related

Rails multiple select puts extra blank parameter

I'm trying to create an HTML multiple select using collection_select, to be able to update an entity (a Student) which has a collection of another entity (a SubscriptionList) as a nested attribute. This is backed up by a HABTM ActiveRecord's relation.
I have created the following form for the Student via scaffolding:
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :file_number %><br>
<%= f.text_field :file_number %>
</div>
<div class="field">
<%= f.label :subscription_list %><br>
<%= f.collection_select(:subscription_lists, SubscriptionList.all, :id, :name, {}, {:multiple => true}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
and it draws the multiple select properly.
However, if I fill the form and try to PUT the entity, I'm getting this as the params:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"vXYMRYI1UtX7WJRZM0OPIhHQSSEyNOPyUxkUvScdu45PTL7qVhvlJfQYNvaKG5rw+mvHAAAbf6ViTQ6tE4lV1Q==", "student"=>{"first_name"=>" Mariana", "last_name"=>"González", "file_number"=>"12345678", "subscription_lists"=>["", "3"]}, "commit"=>"Update Student", "controller"=>"students", "action"=>"update", "id"=>"14"}
So, my Student is
"first_name"=>" Mariana", "last_name"=>"González", "file_number"=>"12345678", "subscription_lists"=>["", "3"]}
I find it very strange to be receiving ["", "3"] as the values. Why I'm receiving this first "" value?
I'm also posting here my Controller (actions other that update have been deleted for brevity)
class StudentsController < ApplicationController
before_action :set_student, only: [:show, :edit, :update, :destroy, :enrollments]
# PATCH/PUT /students/1
# PATCH/PUT /students/1.json
def update
puts "\n\n\n\n\n\n\n\n\nThese are the params: #{params.inspect}"
puts "\n\n\n\n\nThis is student_params object: #{student_params.inspect}\n\n\nand its class #{student_params.class}"
#puts "\n\n\n\n\n\n\n\n\nWill look for SL with ID: #{params[:subscription_lists_id]}"
all_ids = student_params.subscription_lists.collect {|sl| sl.id }
#student.subscription_lists = SubscriptionList.find(all_ids)
##student.subscription_lists = SubscriptionList.where(id: all_ids)
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_student
#student = Student.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def student_params
#params[:student]
#params.require(:foo).permit(:bar, {:baz => [:x, :y]})
#params.require(:student).permit(:first_name, :last_name, :file_number, :subscription_lists)
params.require(:student).permit! # No strong parameters...
end
end
In fact, I'd rather receive a Student with a nested collection of SubscriptionList instead of just receving an array of ids, but I'm not sure if this is even possible.
Any help would be really appreciated.
Best regards
About your question has been answered in collection select always adding blank value.
You will get [""] when you did not select anything or you select your options select as default. To avoid this you have to add hidden_field before the collection select.
<div class="field">
<%= f.label :subscription_lists %><br>
<%= f.hidden_field :subscription_lists %>
<%= f.collection_select(:subscription_lists, SubscriptionList.all, :id, :name, {}, {:multiple => true}) %>
</div>
The hidden_field helps you when it's nothing selected. How about when you choose it? Please try this.
def update
if student_params["subscription_lists"].any?
student_params["subscription_lists"].reject!(&:empty?)
end
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
I hope this help you.
This is what I ended up doing, mostly following this tutorial.
For the Controller:
class StudentsController < ApplicationController
before_action :set_student, only: [:show, :edit, :update, :destroy, :enrollments]
# PATCH/PUT /students/1
# PATCH/PUT /students/1.json
def update
puts "\n\n\n\n\n\n\n\n\nThese are the params: #{params.inspect}"
puts "\n\n\n\n\nThis is student_params object: #{student_params.inspect}\n\n\nand its class #{student_params.class}"
#subscription_lists = SubscriptionList.where(:id => params[:subscriptions])
#student.subscription_lists.destroy_all # disassociate the already added
#student.subscription_lists << #subscription_lists
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_student
#student = Student.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def student_params
params.require(:student).permit(:first_name, :last_name, :file_number, subscription_lists: [:id])
end
end
And the form:
<div class="field">
<%= f.label :subscription_list %><br>
<%= select_tag "subscriptions", options_from_collection_for_select(SubscriptionList.all, 'id', 'name',#student.subscription_lists.map { |j| j.id }), :multiple => true %>
</div>
Hope it's useful

NoMethodError in Statuses#new

I'm currently building this website in college for fun. My hope is that it will help the education system. Anyways, I'm still trying to figure out rails. I just set up the devise gem with no problem. However, when I click post a new status it gives me this error:
NoMethodError in Statuses#new
Showing /Users/wyatt/Network/netbook/app/views/statuses/_form.html.erb where line #16 raised:
undefined method `user_name' for #<Status:0x00000101ec36d0>
Extracted source (around line #16):
13:
14: <div class="field">
15: <%= f.label :user_name %><br />
16: <%= f.text_field :user_name %>
17: </div>
18: <div class="field">
19: <%= f.label :content %><br />
So here's what my form looks like:
<%= form_for(#status) do |f| %>
<% if #status.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#status.errors.count, "error") %> prohibited this status from being saved:</h2>
<ul>
<% #status.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_name %><br />
<%= f.text_field :user_name %>
</div>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here's my controller
class StatusesController < ApplicationController
# GET /statuses
# GET /statuses.json
def index
#statuses = Status.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #statuses }
end
end
# GET /statuses/1
# GET /statuses/1.json
def show
#status = Status.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #status }
end
end
# GET /statuses/new
# GET /statuses/new.json
def new
#status = Status.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #status }
end
end
# GET /statuses/1/edit
def edit
#status = Status.find(params[:id])
end
# POST /statuses
# POST /statuses.json
def create
#status = Status.new(params[:status])
respond_to do |format|
if #status.save
format.html { redirect_to #status, notice: 'Status was successfully created.' }
format.json { render json: #status, status: :created, location: #status }
else
format.html { render action: "new" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# PUT /statuses/1
# PUT /statuses/1.json
def update
#status = Status.find(params[:id])
respond_to do |format|
if #status.update_attributes(params[:status])
format.html { redirect_to #status, notice: 'Status was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
# DELETE /statuses/1
# DELETE /statuses/1.json
def destroy
#status = Status.find(params[:id])
#status.destroy
respond_to do |format|
format.html { redirect_to statuses_url }
format.json { head :no_content }
end
end
end
From looking at it, it seems you're wanting to append a user_name to a status
Error
Your error basically means you don't have a user_name column in your statuses data table. The basic fix will be to create a migration to add a user_name column to your statuses db:
$ rails generate migration AddUserNameToStatuses
#db/migrations/AddUserNameToStatuses.rb
class AddUserNameToStatuses < ActiveRecord::Migration
def change
add_column :statuses, :user_name, :string
end
end
$ rake db:migrate
Fix
I would actually ditch that, and do this:
#app/models/status.rb
Class Status < ActiveRecord::Base
belongs_to :user #-> you need user_id column in statuses db
delegate :name, to: :user, prefix: true
end
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :statuses
end
This will allow you to remove the references to user_name from your form - as any #status will be associated with a user
You'd then be able to use the .delegate() method to call user_name in statuses

Issues creating a url form field using action view and form_for

Trying to create a form field where a user can submit a url per: http://apidock.com/rails/v3.2.13/ActionView/Helpers/FormHelper/url_field
I'm getting an error: ActionView::Template::Error (undefined method `homepage' for #
here is the model:
class Idea < ActiveRecord::Base
has_many :comments
mount_uploader :picture, PictureUploader
attr_accessible :description, :name, :picture, :homepage
end
the view in form.html.erb
<%= form_for(#idea) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :link %><br />
<%= url_field("homepage") %><br />
</div>
<div class="actions">
<%= f.submit %>
the view in show.html.erb
<p><b>Name: </b><%= #idea.name %></p>
<p><b>Link:</b><%= #idea.homepage %></p>
ideas_controller
def create
#idea = Idea.new(params[:idea])
respond_to do |format|
if #idea.save
format.html { redirect_to #idea, notice: 'Idea was successfully created.' }
format.json { render json: #idea, status: :created, location: #idea }
else
format.html { render action: "new" }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
end
def show
#idea = Idea.find(params[:id])
#comment = #idea.comments.build
respond_to do |format|
format.html # show.html.erb
format.json { render json: #idea }
end
end
Basically, when you're yielding, and using, a variable to the block in form_for, it already sets the association of the form fields.
ie:
url_field('user', 'homepage')
is equivalent to
f.url_field('homepage')
Check out the url_field, and the form_for documentation
IMHO using url_field in the form builder is antiquated and prone to errors. Eventually I was able to find: rails auto link from tenderlove: https://github.com/tenderlove/rails_autolink coupled with tinymce-rails from spohlenz: https://github.com/spohlenz/tinymce-rails. With these 2 gems you can build a full-featured form field and display the output much more effectively. Hopefully this helps someone else.

(Rails) I have 2 models, Area (parent) & RadioStation (child). How might I pull an Area object's name in a Station form using an :area_id foreign key?

I have two "CRUD" forms generated by the "rails g scaffold ModelName type:attribute1, type2:attribute2" command, which is quite powerful.
I'll try to just show what is relevant. First here are my models (attr_accessible tells the db migration stories for the most part)
class Area < ActiveRecord::Base
attr_accessible :description, :frequency, :name, :area_id
has_many :stations
end
class Station < ActiveRecord::Base
attr_accessible :description, :frequency, :name, :area_id
belongs_to :area
end
Next, here is the _form.html.erb for a Station object (currently I'm using a simple drop down which is OK, but I want those :area_id tags to somehow be able to pull the Area.find(params[:area_id]).name, or something like that. If '1' is Denver and '2' is Boulder, I want '1` to pull 'Denver' and so on on the Station _form.
So here is stations_controller.rb, which was generated by the "generate scaffold" command for the most part.
class StationsController < ApplicationController
def index
#stations = Station.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #stations }
end
end
def show
#station = Station.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #station }
end
end
def new
#area_count = Area.count
#station = Station.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #station }
end
end
def edit
#station = Station.find(params[:id])
end
def create
#station = Station.new(params[:station])
respond_to do |format|
if #station.save
format.html { redirect_to #station, notice: 'Station was successfully created.' }
format.json { render json: #station, status: :created, location: #station }
else
format.html { render action: "new" }
format.json { render json: #station.errors, status: :unprocessable_entity }
end
end
end
def update
#station = Station.find(params[:id])
respond_to do |format|
if #station.update_attributes(params[:station])
format.html { redirect_to #station, notice: 'Station was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #station.errors, status: :unprocessable_entity }
end
end
end
def destroy
#station = Station.find(params[:id])
#station.destroy
respond_to do |format|
format.html { redirect_to stations_url }
format.json { head :no_content }
end
end
end
Lastly, here is the _form.html.erb for Station
<%= form_for(#station) do |f| %>
<% if #station.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#station.errors.count, "error") %> prohibited this station from being saved:</h2>
<ul>
<% #station.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :frequency %><br />
<%= f.text_field :frequency %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :area_id %><br />
<%= f.select(:area_id, 1..#area_count) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
So to reiterate my goal/question, what I have currently for the :area_id selector is a dropdown bar which allows me to select from 1.."Area.count". I would like that drop down bar to list the names of the the different areas given the area_id.
Also, I'd like to be able to see a list of Station objects which are "owned" by a given area on the list of areas or perhaps just on the show.html.erb for a given Area.
For the select box:
You should use the collection_select form helper.
Replace
<%= f.select(:area_id, 1..#area_count) %>
With
<%= f.collection_select :area_id, Area.all, :id, :name %>
For showing the list of stations on the show view of an area:
There are several ways to do this, depending on how you want to display them in the HTML.
Here's one way to obtain a comma separated list of the station names:
<%= #area.stations.pluck(:name).join(", ") %>
If you need additional attributes of the stations besides just :name, you could iterate over the collection rather than using pluck:
<ul>
<% #area.stations.each do |s| %>
<li><%= s.name %> - <%= s.frequency %></li>
<% end %>
</ul>

How do I define client_id?

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 %>

Resources