Rails Saving Models in Wrong Order - ruby-on-rails

i've been searching around for some time now and can't seem to figure out what is causing this, I had a model working saving a volunteer and his home and work addresses. I changed something (cant seem to figure out what for the life of me) and now the address isnt being set.
This is my main model:
class HumanVolunteer < ActiveRecord::Base
has_one :primaryPhone, :class_name => "PhoneNumber", :foreign_key => "id", :primary_key => "phone_id"
has_one :primaryEmail, :class_name => "Email", :foreign_key => "id", :primary_key => "email_id"
has_one :work_adr, :class_name => "Address", :foreign_key => "id", :primary_key => "workaddressid"
has_one :home_adr, :class_name => "Address", :foreign_key => "id", :primary_key => "homeaddressid"
attr_accessible :firstName, :lastName, :homeaddressid, :notes, :status, :workaddressid, :home_adr, :work_adr,
:primaryPhone, :primaryEmail, :home_adr_attributes, :work_adr_attributes, :primaryPhone_attributes,
:primaryEmail_attributes
accepts_nested_attributes_for :home_adr
accepts_nested_attributes_for :work_adr
accepts_nested_attributes_for :primaryPhone
accepts_nested_attributes_for :primaryEmail
end
and the address model:
class Address < ActiveRecord::Base
attr_accessible :city, :line1, :line2, :notes, :state, :zipcode
belongs_to :human_volunteer
end
Heres a snippet from the human_volunteers_controller
# GET /human_volunteers/new
# GET /human_volunteers/new.json
def new
#human_volunteer = HumanVolunteer.new
#human_volunteer.build_home_adr
#human_volunteer.build_work_adr
#human_volunteer.build_primaryPhone
#human_volunteer.build_primaryEmail
# Set the Breadcrumbs for this page
#breadcrumbs = { "Dashboard" => "/", "Human Volunteers" => "/human_volunteers"}
#current_page = "New Volunteer"
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #human_volunteer }
end
end
# GET /human_volunteers/1/edit
def edit
#human_volunteer = HumanVolunteer.find(params[:id])
if(#human_volunteer.home_adr.nil?)
#human_volunteer.build_home_adr
end
if(#human_volunteer.work_adr.nil?)
#human_volunteer.build_work_adr
end
if(#human_volunteer.primaryPhone.nil?)
#human_volunteer.build_primaryPhone
end
if(#human_volunteer.primaryEmail.nil?)
#human_volunteer.build_primaryEmail
end
#breadcrumbs = { "Dashboard" => "/", "Human Volunteers" => "/human_volunteers"}
#current_page = "Edit Volunteer: <em>" + #human_volunteer.firstName + " " + #human_volunteer.lastName + "</em>";
end
# POST /human_volunteers
# POST /human_volunteers.json
def create
# create the volunteer
#human_volunteer = HumanVolunteer.new(params[:human_volunteer])
respond_to do |format|
if #human_volunteer.save
format.html { redirect_to #human_volunteer, :notice => #human_volunteer.firstName + ' ' + #human_volunteer.lastName + ' was successfully created.' }
format.json { render :json => #human_volunteer, :status => :created, :location => #human_volunteer }
else
format.html { render :action => "new" }
format.json { render :json => #human_volunteer.errors, :status => :unprocessable_entity }
end
end
end
# PUT /human_volunteers/1
# PUT /human_volunteers/1.json
def update
#human_volunteer = HumanVolunteer.find(params[:id])
respond_to do |format|
if #human_volunteer.update_attributes(params[:human_volunteer])
format.html { redirect_to #human_volunteer, :notice => #human_volunteer.firstName + ' ' + #human_volunteer.lastName + ' was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => #human_volunteer.errors, :status => :unprocessable_entity }
end
end
end
I can see what i think the problem is by looking at the logs, the human volunteer get saved first, using nulls for the address keys, then the addresses are saved ( also same problem with phone number and email models, they are set up identically to the addresses ) then the addresses are saved, and then the human volunteer is never updated again with the new values:
Parameters: {"authenticity_token"=>"dD+ut6noFPw8mJHq4rUJpuNBD1o+q0Hi8a+qOeetzMc=", "utf8"=>"✓", "human_volunteer"=>{"lastName"=>"Koch", "work_adr_attributes"=>{"line1"=>"", "line2"=>"", "zipcode"=>"", "state"=>"", "city"=>""}, "primaryEmail_attributes"=>{"email"=>""}, "primaryPhone_attributes"=>{"number"=>""}, "notes"=>"", "home_adr_attributes"=>{"line1"=>"123 Who Knows land", "line2"=>"", "zipcode"=>"11741", "state"=>"TS", "city"=>"testville"}, "firstName"=>"Ken", "status"=>"Investigative Candidate"}}
(0.2ms) BEGIN
(0.2ms) COMMIT
(0.2ms) BEGIN
(0.1ms) COMMIT
(0.1ms) BEGIN
(0.1ms) COMMIT
(0.1ms) BEGIN
(0.1ms) COMMIT
(0.1ms) BEGIN
SQL (2.3ms) INSERT INTO "human_volunteers" ("created_at", "email_id", "firstName", "homeaddressid", "lastName", "notes", "phone_id", "status", "updated_at", "workaddressid") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id" [["created_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["email_id", nil], ["firstName", "Ken"], ["homeaddressid", nil], ["lastName", "Koch"], ["notes", ""], ["phone_id", nil], ["status", "Investigative Candidate"], ["updated_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["workaddressid", nil]]
SQL (0.8ms) INSERT INTO "phone_numbers" ("created_at", "notes", "number", "phone_id", "phone_type", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["created_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["notes", nil], ["number", ""], ["phone_id", nil], ["phone_type", nil], ["updated_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00]]
SQL (0.7ms) INSERT INTO "emails" ("created_at", "email", "notes", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["email", ""], ["notes", nil], ["updated_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00]]
SQL (0.9ms) INSERT INTO "addresses" ("city", "created_at", "line1", "line2", "notes", "state", "updated_at", "zipcode") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["city", ""], ["created_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["line1", ""], ["line2", ""], ["notes", nil], ["state", ""], ["updated_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["zipcode", nil]]
SQL (0.5ms) INSERT INTO "addresses" ("city", "created_at", "line1", "line2", "notes", "state", "updated_at", "zipcode") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["city", "testville"], ["created_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["line1", "123 Who Knows land"], ["line2", ""], ["notes", nil], ["state", "TS"], ["updated_at", Tue, 07 Aug 2012 16:47:16 UTC +00:00], ["zipcode", 11741]]
(17.8ms) COMMIT
EDIT: If this is any help here is an example of the old entry in the log:
Started POST "/human_volunteers" for 127.0.0.1 at Sat Jul 28 09:08:59 -0400 2012
Processing by HumanVolunteersController#create as HTML
Parameters: {"human_volunteer"=>{"firstName"=>"Ken", "work_adr"=>{"city"=>"", "state"=>"", "zipcode"=>"", "line1"=>"", "line2"=>""}, "status"=>"Trainee", "home_adr"=>{"city"=>"fdsa", "state"=>"Nasdf", "zipcode"=>"11729", "line1"=>"asdf fdsafd", "line2"=>""}, "primaryEmail"=>"ken.koch#essencedesigns.net", "primaryPhone"=>"6316813806", "lastName"=>"Koch", "notes"=>"\r\nHes a good guy"}, "authenticity_token"=>"bgbecE+nMxNrPtleNOLfO/MqRib0cXmDMqL5JaPyC10=", "utf8"=>"✓"}
[1m[36m (0.1ms)[0m [1mBEGIN[0m
[1m[35mSQL (0.5ms)[0m INSERT INTO "emails" ("created_at", "email", "notes", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["email", "ken.koch#essencedesigns.net"], ["notes", nil], ["updated_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00]]
[1m[36m (19.1ms)[0m [1mCOMMIT[0m
[1m[35m (0.1ms)[0m BEGIN
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "phone_numbers" ("created_at", "notes", "number", "phone_id", "phone_type", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"[0m [["created_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["notes", nil], ["number", "6316813806"], ["phone_id", nil], ["phone_type", nil], ["updated_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00]]
[1m[35m (56.9ms)[0m COMMIT
[1m[36m (0.1ms)[0m [1mBEGIN[0m
[1m[35mSQL (2.5ms)[0m INSERT INTO "addresses" ("city", "created_at", "line1", "line2", "notes", "state", "updated_at", "zipcode") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["city", ""], ["created_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["line1", ""], ["line2", ""], ["notes", nil], ["state", ""], ["updated_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["zipcode", nil]]
[1m[36m (9.4ms)[0m [1mCOMMIT[0m
[1m[35m (0.1ms)[0m BEGIN
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "addresses" ("city", "created_at", "line1", "line2", "notes", "state", "updated_at", "zipcode") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"[0m [["city", "Deer Park"], ["created_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["line1", "294 West 15th St"], ["line2", ""], ["notes", nil], ["state", "NY"], ["updated_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["zipcode", 11729]]
[1m[35m (7.0ms)[0m COMMIT
[1m[36m (0.1ms)[0m [1mBEGIN[0m
[1m[35mSQL (1.1ms)[0m INSERT INTO "human_volunteers" ("created_at", "email_id", "firstName", "homeaddressid", "lastName", "notes", "phone_id", "status", "updated_at", "workaddressid") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id" [["created_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["email_id", 5], ["firstName", "Ken"], ["homeaddressid", 14], ["lastName", "Koch"], ["notes", "\r\nHes a good guy"], ["phone_id", 11], ["status", "Trainee"], ["updated_at", Sat, 28 Jul 2012 13:08:59 UTC +00:00], ["workaddressid", 13]]
[1m[36m (6.1ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/human_volunteers/1
Completed 302 Found in 178ms (ActiveRecord: 112.1ms)
I was able to look back into the log and find one that worked, and the human_volunteer was the last thing inserted. It inserted addresses, emails, phones first, then used those id's when inserting the volunteer.
EDIT: I can also report that I am not getting any errors, everything goes through, just the data isnt connected.
Any ideas what could cause the change in the order? I can't see that i changed anything that affected this.
UPDATE: I tried changing the has_one lines and was able to at least produce an error (for better or worse), when i cahnged the lines to:
has_one :workaddress, :class_name => "Address", :foreign_key => "id", :primary_key => "workaddress"
has_one :homeaddress, :class_name => "Address", :foreign_key => "id", :primary_key => "homeaddress"
It tries to use the addressid 1 everytime and i get
ActiveRecord::RecordNotUnique (PG::Error: ERROR: duplicate key value violates unique constraint "addresses_pkey"
DETAIL: Key (id)=(1) already exists.
Also if i take out the primary_key field, it seems to work, but it tries to set them both to the same address and i get the same error except with the next id (22, 23, 24 etc each time i try it)
Maybe that sheds some light on the problem? I'm going to keep prodding around.
Thank you very much,
- Ken

I came up with what seems to be a viable solution.
Since once the id was initially set, everything seemed to work, i just manually linked it up in the controller under the create action:
#human_volunteer.homeaddress.save
#human_volunteer.homeaddressid = #human_volunteer.homeaddress.id
#human_volunteer.workaddress.save
#human_volunteer.workaddressid = #human_volunteer.workaddress.id
Now the address gets set when the volunteer is created and everything else should carry out nicely.
The only additional consideration i can see would be making sure that when i add validators to the address that the addresses can actually validate before allowing the creation of the entire thing.
Thanks everyone,
-Ken

Related

Using Papertrail's attribute_name_was

I have a request that makes several changes to the same record, however I only need to store a version when one of the attributes changes from false to true. I tried the following:
has_paper_trail on: [:update],
only: {
redone: Proc.new { |srv|
srv.redone == true && srv.redone_was == false
},
}
But I am still getting versions on changes that do not involve the redone attribute changing from false to true... This is an excerpt from the log:
(0.7ms) BEGIN
SQL (11.3ms) UPDATE "servicings" SET "redone" = $1, "redo_reason" = $2, "updated_at" = $3 WHERE "servicings"."id" = $4 [["redone", false], ["redo_reason", nil], ["updated_at", 2018-07-19 22:46:15 UTC], ["id", 218762]]
SQL (9.7ms) INSERT INTO "versions" ("item_type", "item_id", "event", "object", "object_changes", "created_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["item_type", "Servicing"], ["item_id", 218762], ["event", "update"], ["object", "---\nid: 218762\nwork_order_id: 7462\narea_id: 16563\nhigh_priority: false\ncompleted_at: \ncreated_at: 2018-07-10 19:45:36.245612000 Z\nupdated_at: 2018-07-19 22:14:11.143007000 Z\nassignee_id: 90\nclaimed_by_id: \ncompleted_by_id: 90\noccupied_at: \ndeleted_at: \nstatus: open\napproval_status: \nredone: true\nunable_reason: \nredo_reason: testing paper_trail\napproving_user_id: \napproving_user_name: \napproved_at: \n"], ["object_changes", "---\nredone:\n- true\n- false\nredo_reason:\n- testing paper_trail\n- \nupdated_at:\n- 2018-07-19 22:14:11.143007000 Z\n- 2018-07-19 22:46:15.680447100 Z\n"], ["created_at", 2018-07-19 22:46:15 UTC]]
(5.6ms) COMMIT
(2.0ms) BEGIN
(0.8ms) COMMIT
(1.5ms) BEGIN
SQL (9.1ms) UPDATE "servicings" SET "updated_at" = $1, "status" = $2 WHERE "servicings"."id" = $3 [["updated_at", 2018-07-19 22:46:15 UTC], ["status", "completed"], ["id", 218762]]
SQL (2.8ms) INSERT INTO "versions" ("item_type", "item_id", "event", "object", "object_changes", "created_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["item_type", "Servicing"], ["item_id", 218762], ["event", "update"], ["object", "---\nid: 218762\nredone: false\nredo_reason: \nwork_order_id: 7462\narea_id: 16563\nhigh_priority: false\ncompleted_at: \ncreated_at: 2018-07-10 19:45:36.245612000 Z\nupdated_at: 2018-07-19 22:46:15.680447100 Z\nassignee_id: 90\nclaimed_by_id: \ncompleted_by_id: 90\noccupied_at: \ndeleted_at: \nstatus: open\napproval_status: \nunable_reason: \napproving_user_id: \napproving_user_name: \napproved_at: \n"], ["object_changes", "---\nupdated_at:\n- 2018-07-19 22:46:15.680447100 Z\n- 2018-07-19 22:46:15.981721300 Z\nstatus:\n- open\n- completed\n"], ["created_at", 2018-07-19 22:46:15 UTC]]
(8.7ms) COMMIT
WorkOrder Load (15.1ms) SELECT "work_orders".* FROM "work_orders" WHERE "work_orders"."deleted_at" IS NULL AND "work_orders"."id" = $1 LIMIT $2 [["id", 7462], ["LIMIT", 1]]
(1.2ms) BEGIN
SQL (16.3ms) UPDATE "servicings" SET "completed_at" = $1, "updated_at" = $2 WHERE "servicings"."id" = $3 [["completed_at", 2018-07-19 22:46:16 UTC], ["updated_at", 2018-07-19 22:46:16 UTC], ["id", 218762]]
SQL (7.5ms) INSERT INTO "versions" ("item_type", "item_id", "event", "object", "object_changes", "created_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["item_type", "Servicing"], ["item_id", 218762], ["event", "update"], ["object", "---\nid: 218762\nredone: false\nredo_reason: \nwork_order_id: 7462\narea_id: 16563\nhigh_priority: false\ncompleted_at: \ncreated_at: 2018-07-10 19:45:36.245612000 Z\nupdated_at: 2018-07-19 22:46:15.981721300 Z\nassignee_id: 90\nclaimed_by_id: \ncompleted_by_id: 90\noccupied_at: \ndeleted_at: \nstatus: completed\napproval_status: \nunable_reason: \napproving_user_id: \napproving_user_name: \napproved_at: \n"], ["object_changes", "---\ncompleted_at:\n- \n- 2018-07-19 22:46:16.111954100 Z\nupdated_at:\n- 2018-07-19 22:46:15.981721300 Z\n- 2018-07-19 22:46:16.150183500 Z\n"], ["created_at", 2018-07-19 22:46:16 UTC]]
(2.7ms) COMMIT
What could I be doing wrong?
It's probably because PaperTrail's callback executes after the update. If that's the case, redone_was will always be equal to the current redone value.
You should store your redone_was value somewhere before updating.
class Klass
attr_accessor :old_redone_value
before_save :store_old_redone_value
has_paper_trail on: [:update],
only: {
redone: Proc.new { |srv|
srv.redone == true && srv.old_redone_value == false
},
}
def store_old_redone_value
self.old_redone_value = redone_was
end
end
That's the idea. It's not the best solution, and might not work -- but, it'll lead you somewhere.

How to pass time_select in controller params?

<%= f.time_select :exact, {ampm: true, :discard_minute=> true} %> # t.time "exact"
How do I pass the above in params?
session[:challenge_exact] = params[:exact].parse_time_select! # got nil error
session[:challenge_exact] = challenge_params[:exact]
session[:challenge_exact] = [params["challenge"]["exact(1i)"], params["challenge"]["exact(2i)"], params["challenge"]["exact(3i)"], params["challenge"]["exact(4i)"], params["challenge"]["exact(5i)"]].join(',')
None of the above work. After the challenge is created I see that exact: nil even though it was populated in the form.
Started POST "/challenges" for ::1 at 2017-05-02 08:28:31 -0400
Processing by ChallengesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"oN+DzJK+/GGmpTOOVYMUJQdywuENwxhmX/EVeW6NSZ3w1MctoMd/VHS39d+JasEjHujO88nLPSB2qUKEhet5yA==", "challenge"=>{"name"=>"Write 3 Gratitudes", "categorization"=>"health", "category"=>"goal", "deadline(2i)"=>"6", "deadline(3i)"=>"2", "deadline(1i)"=>"2017", "push"=>"0", "message"=>"1", "mail"=>"0", "remind"=>["mon", "thu", ""], "exact(1i)"=>"2017", "exact(2i)"=>"5", "exact(3i)"=>"2", "exact(4i)"=>"08", "exact(5i)"=>"27", "conceal"=>"0"}, "number"=>"", "email"=>"", "button"=>""}
Redirected to http://localhost:3000/signup
Completed 302 Found in 47ms (ActiveRecord: 0.0ms)
After POST challenge a person then creates a user account...
Started POST "/users" for ::1 at 2017-05-03 01:02:13 -0400
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"4Lv5NSfH9tMnC9+t5bVC5x1d571y0jhwsgvYU3t2sp85XAnNOsHk+FCmtGcj2wJVysV6IlAIzF4jCx1hIofwsNg==", "user"=>{"name"=>"test", "last_name"=>"daddy", "email"=>"testdaddy#gmail.com", "password"=>"[FILTERED]", "time_zone"=>"Eastern Time (US & Canada)", "subscribe"=>"0"}, "button"=>""}
(0.2ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('testdaddy#gmail.com') LIMIT 1
SQL (2.3ms) INSERT INTO "users" ("time_zone", "name", "last_name", "subscribe", "email", "password_digest", "number", "created_at", "updated_at", "activation_digest", "activated") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id" [["time_zone", "Eastern Time (US & Canada)"], ["name", "test"], ["last_name", "daddy"], ["subscribe", "f"], ["email", "testdaddy#gmail.com"], ["password_digest", "$2a$10$JSSPUl0JDnUXybnAuSnEO.q5DgZscaU3hRpcM4C5L0a0aEtflzb7ne"], ["number", "15169499507"], ["created_at", "2017-05-03 05:02:14.144232"], ["updated_at", "2017-05-03 05:02:14.144232"], ["activation_digest", "$2a$10$NDtWKvxuJm/Hb9YIOzuVIuPpttCZwjsgYws6HhEcbHc.PukxXNpeLa"], ["activated", "t"]]
(18.8ms) COMMIT
(0.2ms) BEGIN
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 16]]
# AS YOU CAN SEE WITH INSERT INTO CHALLENGES FOR SOME REASON THE SESSION PARAMS FOR EXACT ISN'T PASSING FOR EXACT
SQL (0.6ms) INSERT INTO "challenges" ("committed", "name", "categorization", "category", "deadline", "remind", "message", "user_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id" [["committed", nil], ["name", "Write 3 Gratitudes"], ["categorization", "health"], ["category", "goal"], ["deadline", "2017-06-03"], ["remind", "---\n- mon\n- thu\n- ''\n"], ["message", "t"], ["user_id", 16], ["created_at", "2017-05-03 05:02:14.434251"], ["updated_at", "2017-05-03 05:02:14.434251"]]
ActsAsTaggableOn::Tag Load (0.6ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL) [["taggable_id", 40], ["taggable_type", "Challenge"]]
ActsAsTaggableOn::Tag Load (0.8ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND
taggings.tagger_id = 16 AND
taggings.tagger_type = 'User') [["taggable_id", 40], ["taggable_type", "Challenge"]]
(17.2ms) COMMIT
Redirected to http://localhost:3000/
How it appears in console...
exact: 2000-01-01 02:32:00 UTC>
You can access exact params like:
> params[:challenge]["exact(1i)"]
#=> "2017"
> params[:challenge]["exact(2i)"]
#=> "5"
> params[:challenge]["exact(3i)"]
#=> "2"
> params[:challenge]["exact(4i)"]
#=> "08"
> params[:challenge]["exact(5i)"]
#=> "27"
You can parse time like this:
exact_time = "#{params[:challenge]['exact(4i)']}:#{params[:challenge]['exact(5i)']}"
#=> "08:27"
> session[:challenge_exact] = Time.parse(exact_time)
#=> 2017-05-03 08:27:00 +0530
I would do:
session[:challenge_exact] = components_to_absolute(params[:exact])
def components_to_absolute(components)
DateTime.new(components['exact(1i)'].to_i,
components['exact(2i)'].to_i,
components['exact(3i)'].to_i,
components['exact(4i)'].to_i,
components['exact(5i)'].to_i)
end

Postgresql database query to Ruby active record

There are tables audits and audit_statuses, and need to fetch the data which are not common in both. I already have a query that works in postgresql , how to convert convert it into Ruby active record .
the following is the Psql query
SELECT a.name as status,count(b.audit_status_id) as count
FROM audit_statuses as a,audits as b
WHERE a.id=b.audit_status_id
GROUP BY a.name;
Your association models are Audit belongs_to Audit_status, and Audit_status has_many Audits, aren't there? And You want to get counts how many Audit_statuses owned by Audit, won't you?
If yes, you should use counter_cache read this about belongs_to Association Reference #counter_cache
Although the :counter_cache option is specified on the model that
includes the belongs_to declaration, the actual column must be added
to the associated model. In the case above, you would need to add a
column named count_audit to the Audit_status model
Add count_audit attribute to audit_statuses table by running :
rails g migration AddCountAuditToAuditStatuses count_audit:integer
and run rake db:migrate
On your models looks like :
class Audit < ActiveRecord::Base
attr_accessible :audit_status_id, :status
belongs_to :audit_status, :counter_cache => :count_audit
end
class AuditStatus < ActiveRecord::Base
attr_accessible :count_audit, :name
has_many :audits
end
Example create one record of audit_status
irb(main):001:0> audit_status = AuditStatus.create!(:name => "John Noe")
←[1m←[36m (0.0ms)←[0m ←[1mBEGIN←[0m
←[1m←[35mSQL (114.0ms)←[0m INSERT INTO "audit_statuses" ("count_audit", "created_at", "name", "up
dated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["count_audit", nil], ["created_at", Fri, 06 Jun
2014 15:17:49 WIB +07:00], ["name", "John Noe"], ["updated_at", Fri, 06 Jun 2014 15:17:49 WIB +07:0
0]]
←[1m←[36m (17.0ms)←[0m ←[1mCOMMIT←[0m
=> #<AuditStatus id: 1, name: "John Noe", count_audit: nil, created_at: "2014-06-06 08:17:49", updat
ed_at: "2014-06-06 08:17:49">
And create two records of audit, and get audit_status.id for audit_status_id
irb(main):002:0> audit = Audit.create!({:audit_status_id => audit_status.id, :status => true})
←[1m←[35m (0.0ms)←[0m BEGIN
←[1m←[36mSQL (6.0ms)←[0m ←[1mINSERT INTO "audits" ("audit_status_id", "created_at", "status", "up
dated_at") VALUES ($1, $2, $3, $4) RETURNING "id"←[0m [["audit_status_id", 1], ["created_at", Fri,
06 Jun 2014 15:19:00 WIB +07:00], ["status", true], ["updated_at", Fri, 06 Jun 2014 15:19:00 WIB +07
:00]]
←[1m←[35mAuditStatus Load (1.0ms)←[0m SELECT "audit_statuses".* FROM "audit_statuses" WHERE "audi
t_statuses"."id" = 1 LIMIT 1
←[1m←[36mSQL (2.0ms)←[0m ←[1mUPDATE "audit_statuses" SET "count_audit" = COALESCE("count_audit",
0) + 1 WHERE "audit_statuses"."id" = 1←[0m
←[1m←[35m (1.0ms)←[0m COMMIT
=> #<Audit id: 1, audit_status_id: 1, status: true, created_at: "2014-06-06 08:19:00", updated_at: "
2014-06-06 08:19:00">
irb(main):003:0> audit = Audit.create!({:audit_status_id => audit_status.id, :status => false})
←[1m←[36m (1.0ms)←[0m ←[1mBEGIN←[0m
←[1m←[35mSQL (1.0ms)←[0m INSERT INTO "audits" ("audit_status_id", "created_at", "status", "update
d_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["audit_status_id", 1], ["created_at", Fri, 06 Jun 2
014 15:19:23 WIB +07:00], ["status", false], ["updated_at", Fri, 06 Jun 2014 15:19:23 WIB +07:00]]
←[1m←[36mAuditStatus Load (1.0ms)←[0m ←[1mSELECT "audit_statuses".* FROM "audit_statuses" WHERE "
audit_statuses"."id" = 1 LIMIT 1←[0m
←[1m←[35mSQL (0.0ms)←[0m UPDATE "audit_statuses" SET "count_audit" = COALESCE("count_audit", 0) +
1 WHERE "audit_statuses"."id" = 1
←[1m←[36m (0.0ms)←[0m ←[1mCOMMIT←[0m
=> #<Audit id: 2, audit_status_id: 1, status: false, created_at: "2014-06-06 08:19:23", updated_at:
"2014-06-06 08:19:23">
So, you only call audit_status's records looks like :
irb(main):004:0> #audit_statuses = AuditStatus.all
←[1m←[35mAuditStatus Load (1.0ms)←[0m SELECT "audit_statuses".* FROM "audit_statuses"
=> [#<AuditStatus id: 1, name: "John Noe", count_audit: 2, created_at: "2014-06-06 08:17:49", update
d_at: "2014-06-06 08:17:49">]
#audit_status = Audit.joins( :audit_status).select("name as status,count(audit_status_id) as count").group(:name)

TypeError: can't cast Array to json strong parameters

I have a rails 4 app with strong parameters like:
def product_params
params.require(:product).permit(:title, :user_id, :info => [:color, :size])
end
But I'm getting the following error:
INSERT INTO "products" ("created_at", "info","title", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Tue, 15 Apr 2014 01:30:31 UTC +00:00], ["info", [{"color"=>"Blue"}]], ["title", "Shoes"], ["updated_at", Tue, 15 Apr 2014 01:30:31 UTC +00:00]]
TypeError: can't cast Array to json: INSERT INTO "products" ("created_at", "info", "title", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"

Why isn't my Ruby on Rails model's attribute being set with before_save?

I am making a Ruby on Rails app and am having trouble setting some attributes of my model. The problem is that I have a :before_save method, yet for some reason the encrypted_password and salt aren't getting saved to the database. Here's the model:
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :username, :email, :password
before_save :encrypt_password
...
private
def encrypt_password
logger.debug "Got to encrypt_password 1"
logger.debug "encrypted_password is #{ #encrypted_password }"
if #encrypted_password != nil and #encrypted_password != ""
return # #encrypted_password was already set
end
logger.debug "Got to encrypt_password 2"
#salt = make_salt if new_record?
logger.debug "New salt = #{ #salt }"
#encrypted_password = encrypt(#password)
logger.debug "New encrypted_password = #{ #encrypted_password }"
#password = "(encrypted)"
logger.debug "Got to encrypt_password 3"
end
In the log file, I see the following:
Started POST "/users" for 127.0.0.1 at Wed May 02 22:55:20 -0500 2012
Processing by UsersController#create as HTML
Parameters: {"commit"=>"Submit", "authenticity_token"=>"RY9fSMqb2+tdQ0fIjiEz8cfMTWTi012vCWdCvbxACLk=", "utf8"=>"\342\234\223", "user"=>{"username"=>"test6", "password"=>"[FILTERED]", "email"=>"test6#gmail.com"}}
[1m[36m (0.1ms)[0m [1mbegin transaction[0m
[1m[35mUser Exists (0.2ms)[0m SELECT 1 FROM "users" WHERE LOWER("users"."email") = LOWER('test6#gmail.com') LIMIT 1
Got to encrypt_password 1
encrypted_password is
Got to encrypt_password 2
New salt = 4f3464029393829aa562e533773f668c8471c51231611f6f214e654275f37184
New encrypted_password = 0dafcff2fe75bb6f2b53afda79789cfe13bd3f733b817a0e2e30df98af5829bc
Got to encrypt_password 3
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "users" ("created_at", "email", "encrypted_password", "is_done", "last_seen", "salt", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?)[0m [["created_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["email", "test6#gmail.com"], ["encrypted_password", nil], ["is_done", false], ["last_seen", nil], ["salt", nil], ["updated_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["username", "test6"]]
[1m[35m (0.7ms)[0m commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 7ms (ActiveRecord: 1.4ms)
So it's definitely making the salt and the encrypted password. Yet the database isn't getting updated?!
>> User.find(6)
=> #<User id: 6, username: "test6", email: "test6#gmail.com", encrypted_password: nil, is_done: false, salt: nil, last_seen: nil, created_at: "2012-05-03 03:55:20", updated_at: "2012-05-03 03:55:20">
Try using self.encrypted_password.
ActiveRecord makes getter/setter methods for your attributes, i.e.
def encrypted_password
...
# return something from the db
end
def encrypted_password=(x)
...
# set something in the db to x
end
And when you write #encrypted_password, you're not actually using these methods, so the database doesn't get updated.
You can see this in your log:
[1m[36mSQL (0.5ms)[0m [1mINSERT INTO "users" ("created_at", "email", "encrypted_password", "is_done", "last_seen", "salt", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?)[0m [["created_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["email", "test6#gmail.com"], ["encrypted_password", nil], ["is_done", false], ["last_seen", nil], ["salt", nil], ["updated_at", Thu, 03 May 2012 03:55:20 UTC +00:00], ["username", "test6"]]
salt and encrpyed_password is being set to nil, because you didn't update the attribute, you updated a class member variable.
I think you forgot self.encrypted_password = #encrypted_password at the end of def encrypt_password.

Resources