Cant update relations on Update action in rails controller - ruby-on-rails-3

When updating a resource called JobsI want to copy some of the values from this update to some resources connected to this resource
Jobs has many Hours each hour has a period with 2 set of times. So if i update the job with these times i want them copied down to the periods
I tried this code in different variants but the periods entities dont get updated.
def update
#job = Job.find(params[:id])
respond_to do |format|
if #job.update_attributes(params[:job])
#job = Job.find(params[:id])
#job.hours.each do |hour|
logger.debug params[:job][:start1]
logger.debug params[:job][:end1]
hour.periods.first.start_time = params[:job][:start1]
hour.periods.first.end_time = params[:job][:end1]
hour.periods.last.start_time = params[:job][:start2]
hour.periods.last.end_time = params[:job][:end2]
end
#job.save
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

This should get you closer to telling which code is failing, but you could have all sorts of things going wrong in there. If this doesn't work, uncomment that binding.pry and make sure the hour attributes have updated Also, looks like you're getting #job twice? Give this a shot:
def update
#job = Job.find(params[:id])
respond_to do |format|
if #job && #job.update_attributes(params[:job])
logger.debug "Job updated attributes"
#job.hours.each do |hour|
hour.periods.first.update_attributes(start_time: params[:job][:start1])
hour.periods.first.update_attributes(end_time: params[:job][:end1])
hour.periods.last.update_attributes(start_time: params[:job][:start2])
hour.periods.last.update_attributes(end_time: params[:job][:end2])
# binding.pry
end
#job.save!
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
You could speed up the updates a little bit by calling update_column on the period records. i.e. hour.periods.first.update_column(:start_time, params[:job][:start_time]), but you would lose any validation or callbacks on your period model by doing so.

Related

Rails: Nested resource and specifying the "nester"

A company has many properties. A property has one company.
In my routes file I got:
resources :companies do
resources :property_managers
end
In the property_manager_controller, my create action looks like this (default scaffold implementation slightly modified to accommodate the company):
def create
#property_manager = PropertyManager.new(params[:property_manager])
#property_manager.company_id = params[:company_id]
respond_to do |format|
if #property_manager.save
format.html { redirect_to company_property_managers_path, notice: 'Property manager was successfully created.' }
format.json { render json: #property_manager, status: :created, location: #property_manager }
else
format.html { render action: "new" }
format.json { render json: #property_manager.errors, status: :unprocessable_entity }
end
end
end
Is there a way in which I do not have to explicitly set the company_id, since it is known within the context of the URL/route?
I guess you could do something like the following, not sure if it's better or not:
class PropertyManagersController < ApplicationController
before_filter :find_company
def new
#property_manager = #company.property_managers.build
end
def create
#property_manager = #company.property_managers.build(params[:property_manager])
respond_to do |format|
...
end
end
private
def find_company
#company ||= Company.find(params[:company_id])
end
end

Rails 3 No Route Matches Error

My application uses tickets and call_logs. I have these nested in each other, so that tickets can have many call_logs.
I am getting the error with [GET] "/call_logs"
I don't know what I am missing here.
I do have my routes nested in routes.rb
resources :tickets do
resources :call_logs
end
rake routes:
ticket_call_logs GET /tickets/:ticket_id/call_logs(.:format) call_logs#index
POST /tickets/:ticket_id/call_logs(.:format) call_logs#create
new_ticket_call_log GET /tickets/:ticket_id/call_logs/new(.:format) call_logs#new
edit_ticket_call_log GET /tickets/:ticket_id/call_logs/:id/edit(.:format) call_logs#edit
ticket_call_log GET /tickets/:ticket_id/call_logs/:id(.:format) call_logs#show
PUT /tickets/:ticket_id/call_logs/:id(.:format) call_logs#update
DELETE /tickets/:ticket_id/call_logs/:id(.:format) call_logs#destroy
tickets GET /tickets(.:format) tickets#index
POST /tickets(.:format) tickets#create
new_ticket GET /tickets/new(.:format) tickets#new
edit_ticket GET /tickets/:id/edit(.:format) tickets#edit
ticket GET /tickets/:id(.:format) tickets#show
PUT /tickets/:id(.:format) tickets#update
DELETE /tickets/:id(.:format) tickets#destroy
call_logs controller:
class CallLogsController < ApplicationController
before_filter :get_ticket
# GET /call_logs
# GET /call_logs.json
def index
#call_logs = #ticket.call_logs.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #call_logs }
end
# GET /call_logs/1
# GET /call_logs/1.json
def show
#call_log = #ticket.call_logs.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #call_log }
end
end
# GET /call_logs/new
# GET /call_logs/new.json
def new
#call_log = #ticket.call_logs.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #call_log }
end
end
# GET /call_logs/1/edit
def edit
#call_log = #ticket.call_logs.find(params[:id])
end
# POST /call_logs
# POST /call_logs.json
def create
#call_log = CallLog.new(params[:call_log])
respond_to do |format|
if #call_log.save
format.html { redirect_to ticket_call_logs_url(#ticket), notice: 'Call log was successfully created.' }
format.json { render json: #call_log, status: :created, location: #call_log }
else
format.html { render action: "new" }
format.json { render json: #call_log.errors, status: :unprocessable_entity }
end
end
end
# PUT /call_logs/1
# PUT /call_logs/1.json
def update
#call_log = #ticket.call_logs.find(params[:id])
respond_to do |format|
if #call_log.update_attributes(params[:call_log])
format.html { redirect_to ticket_call_logs_url(#ticket), notice: 'Call log was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #call_log.errors, status: :unprocessable_entity }
end
end
end
# DELETE /call_logs/1
# DELETE /call_logs/1.json
def destroy
#call_log = #ticket.call_log.find(params[:id])
#call_log.destroy
respond_to do |format|
format.html { redirect_to ticket_call_logs_path(#call_log)}
format.json { head :no_content }
end
end
end
end
private
def get_ticket
#ticket = Ticket.find(params[:ticket_id])
end
I believe I have an error in my url paths when directing to the call_log page, but I can't seem to find it. Any advice or tips would be appreciated, as I am a noob.
Thank you.
As you can see from the output of rake routes, You don't have a route that matches /call_logs. Since this is a nested resource route you have to prepend the tickets and ticket id: /tickets/<id>/call_logs.
Looks like you have done changes in routes.rb but not maintaining relation in Models. As rake routes say
ticket_call_logs GET /tickets/:ticket_id/call_logs(.:format)
Should be accessible by /ticket/id/call_logs , Now here "id" is ticket id. This will list all call logs for that particular ticket_id.

Avoid index url after failing create

When you create a User in rails through the create action, the url is changed to
http://myapplication.com/users with POST
before being redirected elsewhere. If validation fails, it appears that the above URL is retained. If you then refresh, you end up on the index page (as it's now a GET).
I would expect if validation was failed the url would remain as
http://myapplication.com/users/new
As i don't have an index page, this is causing me problems. Is there a way to resolve this please?
This depends on the logic in the respond_to block in your controller.
This is a typical example of the create action in users_controller.rb:
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
So if the save fails, the new action is rendered again.
In your UsersController, do like this:
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to root_url # save success will return to root page
else
render 'new'
end
end

Parse JSON HTTP post in Rails 3 app?

I have a simple Rails 3 example application that I'm trying to work out how to parse a JSON POST and insert the data into my applications database.
I have a basic Activities controller and model, the controller is as follows:
class ActivitiesController < ApplicationController
# GET /activities
# GET /activities.json
def index
#activities = Activity.order('created_at DESC').limit(10)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #activities }
end
end
# GET /activities/1
# GET /activities/1.json
def show
#activity = Activity.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #activity }
end
end
# GET /activities/new
# GET /activities/new.json
def new
#activity = Activity.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #activity }
end
end
# GET /activities/1/edit
def edit
#activity = Activity.find(params[:id])
end
# POST /activities
# POST /activities.json
def create
#activity = Activity.new(params[:activity])
respond_to do |format|
if #activity.save
format.html { redirect_to #activity, notice: 'Activity was successfully created.' }
format.json { render json: #activity, status: :created, location: #activity }
else
format.html { render action: "new" }
format.json { render json: #activity.errors, status: :unprocessable_entity }
end
end
end
# PUT /activities/1
# PUT /activities/1.json
def update
#activity = Activity.find(params[:id])
respond_to do |format|
if #activity.update_attributes(params[:activity])
format.html { redirect_to #activity, notice: 'Activity was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #activity.errors, status: :unprocessable_entity }
end
end
end
# DELETE /activities/1
# DELETE /activities/1.json
def destroy
#activity = Activity.find(params[:id])
#activity.destroy
respond_to do |format|
format.html { redirect_to activities_url }
format.json { head :no_content }
end
end
end
I have also got an example JSON payload from the application I'm trying to receive the POST from:
payload {"files":{"changed":[],"removed":[".gitmodules","extensions","extensions/markdown"]},"project":{"permalink":"dans-stuff-2","public_key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuB80S+kMN1266LvCEXoU5hmjugcuXko61Hl7uD9VVgMgEOrLSkeYktOPshgCOwjQgGhSMVEHWrSuOddOi+V3rOu3v91jiU3vycRM3nK9GMaOFf+tTn0/4ReUvGOFHeir1vluHCmOAmpqsVhGWkCJY6eJE37muvGdTG4nW/VnpWYCTLfSOeaq5MVx5LU+zYLntvB5PXd7h1k5ROO8lW+5QzGVyHHEvilzJOqESIAWpNtcXGBt7clWpFH4lg2AT7JebYFuHl8Sl4LYzIRegcpg718CWJjrck9/xV6CBTGP520ifU6K0x4JOn/qFzVlqwnxmrPXwawptmCiYiJt3X8Oz DeployHQ.com Key for dans-stuff-2","name":"Dans Stuff","repository":{"port":null,"username":null,"branch":"master","url":"git#codebasehq.com:atech/deploytest/test1.git","scm_type":"git","cached":true,"hosting_service":{"name":"Codebase","url":"http://www.codebasehq.com","commits_url":"http://atech.codebasehq.com/projects/deploytest/repositories/test1/commits/master","tree_url":"http://atech.codebasehq.com/projects/deploytest/repositories/test1/tree/master"}}},"server":{"name":"cybele","server_path":"/home/dan/deploytest","port":22,"username":"dan","use_ssh_keys":true,"last_revision":"2ad223b9dd6d006d69909407ac7df322e35b009b","hostname":"cybele.phoenixdev.co.uk","identifier":"de99437e-da4a-0986-a7ab-e55805261a96","protocol_type":"ssh"},"start_revision":{"timestamp":"2011-11-30T13:48:22+00:00","author":"Dan Wentworth","ref":"a1c1073b85d1662c075d77f5d88be3fd291abd12","message":"nested markdown pathg","email":"dan#atechmedia.com"},"identifier":"9d0f9c21-f242-3966-fcd3-e821a65acd45","end_revision":{"timestamp":"2011-08-30T16:41:32+01:00","author":"Dan Wentworth","ref":"2ad223b9dd6d006d69909407ac7df322e35b009b","message":"arses","email":"dan#atechmedia.com"},"configuration":{"email_notify":true,"notification_addresses":"dan#atechmedia.com","copy_config_files":true},"timestamps":{"completed_at":"2012-01-17T09:22:15Z","duration":null,"queued_at":"2012-01-17T09:22:07Z","started_at":"2012-01-17T09:22:10Z"},"status":"completed"} -------------------------------------------------------------------------------- signature TMjVYhk/+lQigy3hdkgTZjAaaroxAi126XaDzrQ1xWGyMji9oR0F5nfE73Mo kNs7Hk7aY1GQgtDRdBjgPE+C/6etF9nPFXPacWobaxSP35TGOrpoSACNQDAQ Q0wvn0Bm/jMvhBKoQ6YYUSx8KP8nd7VkgQmv4S0cakgixA4LHfg=
Because the POST will need to be made to a URL, I would imagine I need to define a new method:
def deploy_receive
data = JSON.parse(request.body)
end
What I am unsure of, is where to go from here. How would I cherry pick the attributes from the JSON and put them into various attributes in the Activities table?
Something like this?
def deploy_receive
data = JSON.parse(request.body)
#activity = Activity.new(params[:fault])
#activity.who = data.author
end
Any pointers would be appreciated!
If I understand correctly I think you're looking for something like what's below:
Routes File
match '/api/activity/new' => 'activity#deploy_receive', :via => [:post]
Activity Controller (assuming the POSTed data is in correct format)
def deploy_receive
#activity = Activity.new(params[:fault])
if #activity.save
render json: #activity
else
#activity = "error"
render json: #activity
end
end
If I understand it correctly; Rails will already do this for you if the right headers are set. Checkout: POST json to rails server

Rails URL Access

I'm new to Ruby on Rails, so please pardon my ignorance. My issue is that I cannot access the Rails project from the browser. I assume it has something to do with the Rails config, but I am having no luck so far.
State of the Project
I have existing logic (controllers, models, migrations, ...).
If I leave index.html in place, I see the Rails welcome page because it is apparently rendered before Rails tries to parse the URL.
If I disable index.html, I get the 'Something went wrong' message which is generated by Rails.
If I have the httpd.conf document root set to 'my.domain.com/public' I get the Rails error, but if I have it set to 'my.domain.com/', I get an error served up by Apache instead. (So that seems to be correctly configured.)
The error logs show this error: File does not exist: /var/www/html/my.domain.com/zombies when I hit the URL.
My Environment
Rails 3.2.6
Ruby 1.9.3
Apache 2.2.3
CentOS
If it matters, I'm simply following the tutorial at Rails for Zombies 2.
Thanks in advance!
Reference
zombies_controller.rb
class ZombiesController < ApplicationController
# GET /zombies
# GET /zombies.json
def index
#zombies = Zombie.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #zombies }
end
end
# GET /zombies/1
# GET /zombies/1.json
def show
#zombie = Zombie.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #zombie }
end
end
# GET /zombies/new
# GET /zombies/new.json
def new
#zombie = Zombie.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #zombie }
end
end
# GET /zombies/1/edit
def edit
#zombie = Zombie.find(params[:id])
end
# POST /zombies
# POST /zombies.json
def create
#zombie = Zombie.new(params[:zombie])
respond_to do |format|
if #zombie.save
format.html { redirect_to #zombie, notice: 'Zombie was successfully created.' }
format.json { render json: #zombie, status: :created, location: #zombie }
else
format.html { render action: "new" }
format.json { render json: #zombie.errors, status: :unprocessable_entity }
end
end
end
# PUT /zombies/1
# PUT /zombies/1.json
def update
#zombie = Zombie.find(params[:id])
respond_to do |format|
if #zombie.update_attributes(params[:zombie])
format.html { redirect_to #zombie, notice: 'Zombie was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #zombie.errors, status: :unprocessable_entity }
end
end
end
# DELETE /zombies/1
# DELETE /zombies/1.json
def destroy
#zombie = Zombie.find(params[:id])
#zombie.destroy
respond_to do |format|
format.html { redirect_to zombies_url }
format.json { head :no_content }
end
end
end
Running rake assets:precompile seems to have fixed my issue. Thanks all.