I have a model called "Profile" and one of the attributes is called "pic". In the console, when I do:
User.first.profile
The following is returned.
=> #<Profile id: 64, created_at: "2014-06-19 15:59:41",
updated_at: "2014-06-19 15:59:41", user_id: 24,
description: "fds aslkjd aslkfjhas dlkjashdf lajkdshf al...",
rate: nil, pic: nil >
As you can see, the "pic" attribute is nil because I never uploaded a picture. I am trying to write several "if statements" to distinguish whether or not the picture exists. For example:
#profile = User.find(24).profile.first
if #profile.pic
I've also tried:
#profile = User.find(24).profile.first
if #profile.pic.exists?
All of these evaluate to true, which should not happen since a picture has never been uploaded.
I've also tried:
#profile = User.find(24).profile.first
if #profile.pic.nil?
and for some reason that evaluates to false.
When I run in the console:
=> #<PicUploader:0x007ff8abeb8560 #model=#<Profile id: 64,
created_at: "2014-06-19 15:59:41", updated_at: "2014-06-19 15:59:41",
user_id: 24, description: "fds aslkjd aslkfjhas dlkjashdf lajkdshf al...",
rate: nil, pic: nil>, #mounted_as=:pic>
I don't know where that is coming from. How do I write an "if statement" for whether or not the image exists that will actually return false like it should?
Thanks.
With carrierwave, you should use either the question-method of your attribute, pic?, or you can use blank?/present?:
#profile.pic.present?
# => false
#profile.pic?
# => false
#profile.pic.blank?
# => true
Related
Using Rails 4 with GraphQL API.
I'm getting some inputs via an object, based on which I'm finding or initializing new ActiveRecord objects that I want to save later.
Sample input is:
[
{:id=>"192", :internalId=>128, :title=>"Editing"},
{:internalId=>130, :title=>"New"}
]
As you can notice, some of the records already exist and have an ID, we need to update those. And the rest we need to save as new records.
Then I have a method that goes through those post values:
def posts=(value)
#posts = value.map do |post|
init_post(post)
end
end
def init_post(post)
Post.find_or_initialize_by(
id: post[:id],
title: post[:title],
internal_id: post[:internalId],
)
end
That will return two instances of the Post model:
[#<Post id: 192, title: "Editing", internal_id: 128, created_at: nil, updated_at: nil>, #<Post id: nil, title: "New", internal_id: 130, created_at: nil, updated_at: nil>]
Finally, I want to save both records:
def save_posts
posts.each(&:save)
end
Which will return:
"#<ActiveRecord::RecordNotUnique: Mysql2::Error: Duplicate entry '192' for key 'PRIMARY': INSERT INTO `posts` ..."
So how do I make sure the instances with ID just update the existing record, and the rest just save as new ones?
You can find, change/create and save it at once
Post.find_or_initialize_by(id: post[:id]).tap do |record|
record.title = post[:title]
record.internal_id = post[:internalId]
record.save
end
Like the title said, I'm trying to get the ID of the record I just created, I tried to get it in the console but the ID is nil.
Here is the print I got of self in the console at the beginning of after_create
<Unit id: nil, uuid: "9f11be13-8d07-4471-a3bb-f87943966bbd", organization_id: 33, property_id: 430, door_number: "3", created_at: "2014-12-05 13:27:57", updated_at: "2014-12-05 13:27:57", deleted_at: nil, size: "5 1/2", door_number_int: 3, leases_count: 0, tasks_count: 0, notes: nil, state_id: 68, state_tasks_count: 2, current_lease_id: nil, next_lease_id: nil, state_tasks_serie: 1, state_tasks_serie_count: 2, price_asked: #<BigDecimal:7fc79162cb80,'0.123E3',9(18)>, availability_date: nil, comments_count: 0>
Is there a way to get access to the record ID?
This is what I tried so far
after_create
self.save
end
before_save
if self.id.present?
# do stuff
end
end
It is not very pretty but it work
To answer #MarekLipka : It doesn't cause an infinite loop because the record is created only once.
I also tried to use :
after_create
reload
# do stuff if self.id
end
but that doesn't seem to work.
Like #PauloFidalgo said, I can't get the id except in the after_save method. Although it is strange to me that I can get it in the second before_save (triggered by the save in after_create).
The id is only assigned on save, on create you are just creating the skeleton object and giving some values.
To get the id of the object just call object.id
If for some reason you want to get the id in the after_* methods, you need to use the after_save:
after_save {id = self.id}
You could also allocate an ID in create, but you need to query the database and set the value in the variable. To achieve this you need to use a sequence in database to set the id's.
I have this request to database
#show = Question.where(:question_status => params[:id])
Then in #show variable I have this: [#<Question id: 38, user_id: 1, question: "hi", question_status: 1, created_at: "2013-06-04 18:32:28", updated_at: "2013-06-04 18:32:28">, #<Question id: 40, user_id: 1, question: "urll", question_status: 1, created_at: "2013-06-04 18:34:57", updated_at: "2013-06-04 18:34:57">, #<Question id: 41, user_id: 1, question: "urll", question_status: 1, created_at: "2013-06-04 18:35:31", updated_at: "2013-06-04 18:35:31">]
How get , for example, question field ?
I trying #show.question but have error no defined method question.
#show = Question.find_by_question_status(params[:id])
and #show.question
If you us where statement then use:
#show.each do |show|
show.question
end
#show is an ActiveRecord::Relation object(Array). It does not belong to Question class.
#show = Question.where(:question_status => params([:id]).first
if you are expecting only one result. Otherwise you have to iterate the array for each element
You want to take an array of all question fields?
questions = Question.where(:question_status => params[:id]).map(&:question)
Then you can simply go like
questions.each{|question| puts question }
Try this code at your rails console
#show = Question.where(:question_status => params[:id])
#show.each_with_index do |ques, index|
p "#{index+1} :: #{ques.question}"
end
With the help of index, you will get the sequence number of rows.
Use #show.map(&:question) . This will give you all the questions in array.
#show.question gives you error no defined method question because you are trying to operate question on array #show.
If you do #show.first.question it will give you question of first object.
And
If you do #show.map(&:question) it will give you array of question.
To get all the information.
#show.each do |show|
puts show.question
puts show.question_status
puts show.user_id
end
You can optimize it as per you requirement.
I made a mistake and accidentally delete all records from Attachment model in production.
I could at least get all the records from the console output (I previously did a simple Attachment.all and get all records hash displayed on screen).
This is a sample of actual output:
=> [#<Attachment id: 50, shortcut: "1eo2", attachment_file_name: "tumblr_lbxifqK2LT1qa0qyy.jpg", attachment_content_type: "image/jpeg", attachment_file_size: 80960, attachment_updated_at: "2010-12-22 07:39:01", created_at: "2010-12-22 07:39:02", updated_at: "2011-03-07 02:14:05", post_id: nil, about_me: nil, is_nsfw: nil, attachable_id: nil, attachable_type: nil, is_default: nil, temp_token: nil, user_id: 1, description: nil, visits: nil>,
#<Attachment id: 51, shortcut: "1fp7", attachment_file_name: "tumblr_lbxig3Qzrg1qa0qyy.jpg", attachment_content_type: "image/jpeg", attachment_file_size: 75532, attachment_updated_at: "2010-12-22 08:04:00", created_at: "2010-12-22 08:04:01", updated_at: "2011-03-07 02:14:05", post_id: nil, about_me: nil, is_nsfw: nil, attachable_id: nil, attachable_type: nil, is_default: nil, temp_token: nil, user_id: 1, description: nil, visits: nil>,
#<Attachment id: 52, shortcut: "1ghq", attachment_file_name: "tumblr_lbh5dvOZMf1qa4bk9o1_500.jpg", attachment_content_type: "image/jpeg", attachment_file_size: 68396, attachment_updated_at: "2010-12-22 08:04:32", created_at: "2010-12-22 08:04:33", updated_at: "2011-03-07 02:14:05", post_id: nil, about_me: nil, is_nsfw: nil, attachable_id: nil, attachable_type: nil, is_default: nil, temp_token: nil, user_id: 1, description: nil, visits: nil>,
Question is how can I parse this log an put them again the database and there a way to also keep the original ID and avoid having a new one? (I got other relationships by ID with other models).
A quick and dirty way that you might be able to do it would be something similar to this:
1) Load all the console input into a string. Take off the brackets at the beginning/end (the square ones). Then, use this Regex to get the contents of each Attachment object:
#<Attachment (.*)>,
So, something like
consolestr.scan(/#<(Attachment .*)>,/).each do |attachment|
which should give you an array consisting of each Attachment object.
2) Split the properties of each Attachment object on comma to get the full property, then on colon to get the key value pair. Something like:
properties = {}
attachment.split(",").each do |property|
s = property.split(":")
key = s[0]
value = s[1]
properties[key] = value
end
3) Re-create the record:
Attachment.create(properties)
Unfortunately I'm not at a place where I can fully test this right now, but I think it should work in theory. You may have to do some additional tinkering with the value that you capture, such as removing the quotes on string values, as well. Hopefully this is at least one way that can get you started recovering that data. I'm sure you are very nerve racked right now!
If you're trying to get the database back to exactly where it was before you nuked it, your best option is to take the console output and transform it into raw SQL INSERT statements.
Creating the objects through a Rails console will re-assign the ID field, which will then break any existing object associations you've got.
This is really stumping me. The process works fine if I go about it with #new and then #save, but #create returns a model instance with all the fields set to nil.
e.g:
Unexpected behavior:
ruby-1.9.2-p0 > EmailDefault.create(:description=>"hi")
=> #<EmailDefault id: nil, description: nil, created_at: nil, updated_at: nil>
Expected behaviour:
ruby-1.9.2-p0 > e = EmailDefault.new
=> #<EmailDefault id: nil, description: nil, created_at: nil, updated_at: nil>
ruby-1.9.2-p0 > e.description = "hi"
=> "hi"
ruby-1.9.2-p0 > e.save
=> true
ruby-1.9.2-p0 > EmailDefault.last
=> #<EmailDefault id: 4, description: "hi", created_at: "2011-02-27 22:25:33", updated_at: "2011-02-27 22:25:33">
What am I doing wrong?
--update--
Turns out I was mis-using attr_accessor. I wanted to add some non-database attributes, so I did it with:
attr_accessible :example_to, :cc_comments
which is wrong, and caused the situation #Heikki mentioned. What I need to do is:
attr_accessor :example_to, :cc_comments
You need to white list those properties with attr_accessible to enable mass-assignment.
http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html#method-i-attr_accessible
--edit
By default all attributes are available for mass-assignment. If attr_accessible is used then mass-assignment will work only for those attributes. Attr_protected works the opposite way ie. those attributes will be protected from mass-assignment. Only one should be used at a time. I prefer the white listing with attr_accessible.