I would like to edit a supplier name in my heroku database. I'm having trouble accessing the name attribute:
irb(main):015:0> Supplier.where(:name => "Test")
=> #<ActiveRecord::Relation [#<Supplier id: 3070, name: "Test", email: "test#me.com", phone: "555555", website: "http://www.test.co.uk", region_id: 3, category_id: 8, created_at: "2015-02-20 13:28:59", updated_at: "2015-02-20 13:28:59", rating: 0.0, address: nil, facebook_url: nil, twitter_url: nil, google_url: nil, video_url: nil, slug: "test", logo_url: nil, image_one_url: nil, image_two_url: nil, image_three_url: nil, image_four_url: nil, description: nil, reviews_count: 0, source: nil, source_other: nil>]>
irb(main):016:0> _.name
=> "Supplier"
I'm not clear why _.name is resulting in "Supplier" rather than "Test".
Can anyone tell me what I'm missing?
Supplier.where(:name => "Test") returns multiple records. Use
supplier = Supplier.where(:name => "Test").first
supplier.name
Related
Mongodb and rails
Parent object has_many :children
Child has a parent_id of class BSON::ObjectId
Child.first.parent_id
=> BSON::ObjectId('59031cd92936094d04000d31')
I can not find the Parent with that _id
Parent.where(_id: '59031cd92936094d04000d31').first
=> nil
The Parent object looks like this
=> #<Parent _id: 5a959865c8aedf03c1000007, _type: nil, created_at: nil, updated_at: nil, id: nil, name: nil, description: nil, type: nil, starts_at: nil, children_hash: nil>
I was setting up Devise & Omniauth as per railscasts like I usually do, only now I'm using Rails 5.0.1 and ruby 2.3.3
When I go to add a user, not even using Omniauth, just using a basic email + password + confirmation the page reloads with an error of "Email can't be blank". I can see the parameters include the email.
I used Pry to investigate - things get weird here.
[1] pry(#<RegistrationsController>)> params
=> <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"[removed this!]", "user"=><ActionController::Parameters {"email"=>"test#test.com", "password"=>"testtest", "password_confirmation"=>"testtest"} permitted: false>, "commit"=>"Sign up", "controller"=>"registrations", "action"=>"create"} permitted: false>
[3] pry(#<RegistrationsController>)> #user
=> #<User id: nil, email: "test#test.com", created_at: nil, updated_at: nil, first_name: nil, last_name: nil, image_url: nil, headline: nil, dob: nil, gender: nil, webpage_url: nil, twitter: nil, linkedin: nil, blog_url: nil, description: nil, country: nil, state: nil, city: nil, phone: nil, full_bio: nil, profile_claimed: nil>
[4] pry(#<RegistrationsController>)> #user.class
=> User(id: integer, email: string, encrypted_password: string, reset_password_token: string, reset_password_sent_at: datetime, remember_created_at: datetime, sign_in_count: integer, current_sign_in_at: datetime, last_sign_in_at: datetime, current_sign_in_ip: string, last_sign_in_ip: string, created_at: datetime, updated_at: datetime, first_name: string, last_name: string, image_url: string, headline: string, dob: date, gender: string, webpage_url: string, twitter: string, linkedin: string, blog_url: string, description: text, country: string, state: string, city: string, phone: string, full_bio: text, type: string, profile_claimed: boolean)
[5] pry(#<RegistrationsController>)> #user.email
=> nil
[7] pry(#<RegistrationsController>)> #user.errors
=> #<ActiveModel::Errors:0x007f9de2c82da0
#base=
#<User id: nil, email: "test#test.com", created_at: nil, updated_at: nil, first_name: nil, last_name: nil, image_url: nil, headline: nil, dob: nil, gender: nil, webpage_url: nil, twitter: nil, linkedin: nil, blog_url: nil, description: nil, country: nil, state: nil, city: nil, phone: nil, full_bio: nil, profile_claimed: nil>,
#details={:email=>[{:error=>:blank}, {:error=>:blank}]},
#messages={:email=>["can't be blank"], :password=>[], :password_confirmation=>[]}>
[8] pry(#<RegistrationsController>)> #user.email.class
=> NilClass
You can see that if I access #user it returns the hash containing the email. However if I try #user.email I get nil. And when I ask for #user.errors the message says email can't be blank.
I've been hunting a while on this one. Thanks in advance for any help!
--
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:email])
end
end
Puma server.
Started POST "/users" for ::1 at 2017-01-07 20:42:57 -0500
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"tfBeZtXEFdZV9Rx3dJgCQJ+9hHuvgFcbc3dD9D7Q6yKki4GmlVw17/qlDm2squ3hKngX3Juu12iaM1Dki9qXig==", "user"=>{"email"=>"test#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendering registrations/new.html.erb within layouts/application
Rendered devise/shared/_links.html.erb (0.7ms)
Rendered registrations/new.html.erb within layouts/application (4.6ms)
--
rails console
Running via Spring preloader in process 12578
Loading development environment (Rails 5.0.1)
2.3.3 :001 > u = User.new
=> #<User id: nil, email: "", created_at: nil, updated_at: nil, first_name: nil, last_name: nil, image_url: nil, headline: nil, dob: nil, gender: nil, webpage_url: nil, twitter: nil, linkedin: nil, blog_url: nil, description: nil, country: nil, state: nil, city: nil, phone: nil, full_bio: nil, profile_claimed: nil>
2.3.3 :002 > u.email = "test#test.com"
=> "test#test.com"
2.3.3 :003 > u.password = "password"
=> "password"
2.3.3 :004 > u.password_confirmation = "password"
=> "password"
2.3.3 :005 > u.save
(0.2ms) begin transaction
(0.1ms) rollback transaction
=> false
2.3.3 :006 > u.errors
=> #<ActiveModel::Errors:0x007f87163eeac8 #base=#<User id: nil, email: "test#test.com", created_at: nil, updated_at: nil, first_name: nil, last_name: nil, image_url: nil, headline: nil, dob: nil, gender: nil, webpage_url: nil, twitter: nil, linkedin: nil, blog_url: nil, description: nil, country: nil, state: nil, city: nil, phone: nil, full_bio: nil, profile_claimed: nil>, #messages={:email=>["can't be blank"]}, #details={:email=>[{:error=>:blank}, {:error=>:blank}]}>
I believe permitted: false says that your parameters are not permitted and can't be saved. Did you set up strong parameters for Users controller?
How can I delete or destroy an object located in memory, but not in the database?
irb(main):034:0> mentor.registered_students.build(:user_id => 20)
=> #<RegisteredStudent id: nil, user_id: 20, assigned_mentor_id: 1, description: nil, created_at: nil, updated_at: nil>
irb(main):035:0> mentor.registered_students.last
=> #<RegisteredStudent id: nil, user_id: 20, assigned_mentor_id: 1, description: nil, created_at: nil, updated_at: nil>
irb(main):036:0> mentor.registered_students.last.destroy
(0.3ms) BEGIN
(0.2ms) COMMIT
=> #<RegisteredStudent id: nil, user_id: 20, assigned_mentor_id: 1, description: nil, created_at: nil, updated_at: nil>
irb(main):037:0> mentor.registered_students.last.delete
=> #<RegisteredStudent id: nil, user_id: 20, assigned_mentor_id: 1, description: nil, created_at: nil, updated_at: nil>
irb(main):038:0> mentor.registered_students.last
=> #<RegisteredStudent id: nil, user_id: 20, assigned_mentor_id: 1, description: nil, created_at: nil, updated_at: nil>
I already used destroy or delete but they look for records in database.
CONTROLER ACTION:
def mix
unless params[:mentor_id].nil? || params[:students_id].nil?
#mentor = AssignedMentor.find params[:mentor_id]
#students = params[:students_id]
#students.each do |student|
if student[1] == "0"
registered_student = RegisteredStudent.where("assigned_mentor_id = ? AND user_id = ?", #mentor.id, student[0] ).first
registered_student.destroy
end
if student[1] == "1"
#mentor.registered_students.build(:user_id => student[0])
#mentor.save
if #mentor.errors.size > 0
#mentor.registered_students.reload
end
end
end
#redirect_to bind_admin_users_path
end
#flash[:alert] = t("labels.no_students")
redirect_to bind_admin_users_path
end
mentor.registered_students.reload
does the trick
I've used the execute around design pattern that is articulated in the book Eloquent Ruby to log validation errors in my rails application.
I'm capturing the errors using:
#o.errors.full_messages #{:first_name=>["can't be blank"]}
and then persisting them to a logs table, but I'd also like to capture the actual method/code that caused the error. For example:
User.create(:last_name => "Doe")
How would capture the method that caused the errors so I can log it to my validation log table.
not really sure if this is what you need, for rails 3.2:
irb(main):008:0> user = User.create()
then getting errors from it:
irb(main):009:0> user.errors
=> #<ActiveModel::Errors:0xaa84c60 #base=#<User id: nil, email: "", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: nil, updated_at: nil, first_name: nil, last_name: nil, role: "user", approved: false>, #messages={:email=>["can't be blank"], :password=>["can't be blank"]}>
they are at the end of the response.
And also you can call errors on create action without saving the user into a variable:
irb(main):010:0> User.create().errors
(0.3ms) BEGIN
(0.1ms) ROLLBACK
=> #<ActiveModel::Errors:0xa390d78 #base=#<User id: nil, email: "", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: nil, updated_at: nil, first_name: nil, last_name: nil, role: "user", approved: false>, #messages={:email=>["can't be blank"], :password=>["can't be blank"]}>
at the end you get the same hash with errors:
#messages={:email=>["can't be blank"], :password=>["can't be blank"]}
When I comment out my after_save call back, my ActiveRecord associations work just fine. In Rails Console, you'd see:
> #report = Report.create :name => "foo"
=> #<Report id: 9, name: "foo", created_at: "2013-03-05 09:51:55", updated_at: "2013-03-05 09:51:55">
> #question = #report.questions.create :description => "bar"
=> #<Question id: 18, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 09:52:32", updated_at: "2013-03-05 09:52:32", additive: false, instructions: nil>
> #report.questions
=> [#<Question id: 18, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 09:52:32", updated_at: "2013-03-05 09:52:32", additive: false, instructions: nil>]
> #question.reports
=> [#<Report id: 9, name: "foo", created_at: "2013-03-05 09:51:55", updated_at: "2013-03-05 09:51:55">]
However, the associations stop working when I add the following after_save callback to question.rb:
def create_matching_surveys
self.reports.each do |report|
report.reviews.each do |review|
review.competitors.each do |competitor|
competitor.surveys.find_or_create_by_question_id(self.id)
end
end
end
end
Then, in Rails Console, you get:
> #report = Report.create :name => "foo"
=> #<Report id: 13, name: "foo", created_at: "2013-03-05 10:20:51", updated_at: "2013-03-05 10:20:51">
> #question = #report.questions.create :description => "bar"
=> #<Question id: 24, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 10:21:02", updated_at: "2013-03-05 10:21:02", additive: false, instructions: nil>
> #report.questions
=> [#<Question id: 24, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 10:21:02", updated_at: "2013-03-05 10:21:02", additive: false, instructions: nil>]
> #question.reports
=> []
This happens whether or not the report has reviews that have competitors.
The strange thing is I thought the callback was meant to happen after the question was saved? So by rights the association should save too before any of this happens, right?
How do I fix it?
UPDATE
I think I have to call the callback in the right spot in the object's life cycle, but I can't find that spot. Here's why I think this:
> #report = Report.create :name => "foo"
=> #<Report id: 20, name: "foo", created_at: "2013-03-05 12:29:35", updated_at: "2013-03-05 12:29:35">
> #question = #report.questions.create :description => "bar"
=> #<Question id: 31, standard_id: nil, description: "bar", element_id: nil, condition_id: nil, blueprint_name: nil, blueprint_url: nil, created_at: "2013-03-05 12:30:14", updated_at: "2013-03-05 12:30:14", additive: false, instructions: nil>
> #question.reports
=> []
> #question.update_attributes :description => "foo"
=> true
> #question.reports
=> [#<Report id: 20, name: "foo", created_at: "2013-03-05 12:29:35", updated_at: "2013-03-05 12:29:35">]
BTW, the method is now in question_observer.rb:
class QuestionObserver < ActiveRecord::Observer
def after_save(model)
model.reload
model.reports.reload
model.reports.each do |report|
report.reviews.each do |review|
review.competitors.each do |competitor|
competitor.surveys.find_or_create_by_question_id(model.id)
end
end
end
return true
end
end
The answer was to use a neat new callback hook called after_commit which was introduced with Rails 3.
See http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html#method-i-after_commit.
The only issue is after_commit doesn't work "out of the box" with transactional fixtures, but there are plenty of solutions out there, and I found this one worked well for me: https://supportbee.com/devblog/2012/01/14/testing-after_commitafter_transaction-with-rspec/