Hi I am trying to run a joins query in rails. I am trying to output specific data from my User model while also getting data from my contactDetails model.. Code:
User.where(user_type: :lender).all.each do |user|
result <<
"#{user.id}, " +
"#{user.contact_details},"
end
The above prints out fine but when I add:
User.where(user_type: :lender).all.each do |user|
result <<
"#{user.id}, " +
"#{user.contact_details}," +
"#{user.contact_details.city}," +
"#{user.contact_details.region}, "
end
Cannot find region or city.
I think what's happening is user.contact_details is returning nil.
That would allow the first interpolation to work, as "#{nil}" just returns an empty string.
However, in the second example, when you call user.contact_details.city and user.contact_details.region, you're calling the methods city and region on nil, hence the error.
You can account for this using the safe operator to return empty strings, i.e.
user.contact_details&.city
# or in older Ruby versions
user.contact_details.try(:city)
Whether you want to have empty strings returned when the association exists is up to you, however, if you don't want them adding you could do something like:
result_string = user.id.to_s
if user.contact_details.present?
result_string += "#{user.contact_details}," +
"#{user.contact_details.city}," +
"#{user.contact_details.region}, "
end
result << result_string
Finally, if you're expecting contact_details to be present, the problem likely lies in their creation and attachment to the user model - if that's the case, I'd suggest having a look at how you're doing this, and opening a new question with the relevant info if you can't get it to work.
Hope that helps - let me know if you've any questions on this at all.
I have solved this using present? method and then placing Ternary operators inside the code to a none applicable message for users who have not provided contact details. There was no need to add includes or joins:
User.where(user_type: :lender).all.each do |user|
result <<
"#{user.id}, " +
"#{user.contact_details.present? ? user.contact_details.country : ' N/A '}," +
"#{user.contact_details.present? ? user.contact_details.region : ' N/A ' }," +
"#{user.contact_details.present? ? user.contact_details.city : ' N/A '}"
end
Related
I am working the the LogMeIn Central API and in the body of my request I need to send some Json. I have this:
host_ids = LmiHost.all.collect {|lmi| lmi.host_id}.join ', '
create_servicetag_report_request.body = {hostIds: host_ids, fields: 'ServiceTag'}.to_json
This turns the body into
{\"hostIds\":\"5888, 6225, 214752\",\"fields\":\"ServiceTag\"}
how can i remove the
\"
from this section:
\"5888, 6225, 214752\"
it is not suppose to have quotes around it.
I am using Ruby on Rails
The reason to_json adds the \" (escaped quotations) is because it is converting hostIds as a string. In your rails console try this to see the difference.
{"hostids":[0,1,2,3]}.to_json
=> "{\"hostids\":[0,1,2,3]}"
{"hostids":"[0,1,2,3]"}.to_json
=> "{\"hostids\":\"[0,1,2,3]\"}"
This can be seen another way by trying: puts [1,2,3,4] vs puts "[1,2,3,4]"
Ultimately I would refer to the LMI Central API to figure out exactly how multiple hostIds can be sent.
You can use JSON.parse(create_servicetag_report_request.body[:hostIds]) to parse it.
Just remove the join part from this line:
host_ids = LmiHost.all.collect { |lmi| lmi.host_id }.join ', '
join joins your array of ids into a comma separated string. This doesn't seems to be what you want.
Btw. you can shorten .collect { |lmi| lmi.host_id } to map(&:host_id):
create_servicetag_report_request.body = {
hostIds: LmiHost.all.map(&:host_id),
fields: 'ServiceTag'
}.to_json
== UPDATE ===
So I realized that Sublime already has a command for adding comments. So if I have code inserted like this:
comment = " ----------------------------------------" + '\n'
comment += " " + title + '\n'
comment += " #author " + author + '\n'
comment += " #url " + url + '\n'
comment += " ---------------------------------------" + '\n'
comment = self.view.run_command('toggle_comment')
code = items['code']
layout = comment + code
self.view.replace(edit, sel[0], layout)
How do I get the command to work so that it comments out the comment variable? Thanks.
Initial Question
I am creating a plugin for Sublime Text 2 and want to make sure that when it inserts/replaces code it inserts comments as well, but to do this I need for it to insert the correct comment types for the various languages. I know that I can run the following command:
view.settings().get('syntax')
And that will return something like this:
Packages/Python/Python.tmLanguage
Is there a way to have it return just PHP, Python, C++, etc.
I'm sure I could do a substring command in Python, but since I can see an easy way of seeing all file settings I wanted to make sure there wasn't a quick easy way of doing this. Thanks for the help.
Are you looking for scope_name ?
scope_name(point) | String | Returns the syntax name assigned to the character at the given point.
How can I do this, without risking an SQL injection attack?
nearest = Site.minimum('abs(latitude - ' + params[:lat] + ') - abs(longitude - ' + params[:lon] + ')', group: :id)
I've tried:
nearest = Site.minimum(['abs(latitude - ?) - abs(longitude - ?)', params[:lat], params[:lon]], group: :id)
But that doesn't seem to work. The documentation isn't very clear how to achieve this.
Thanks in advance!
Rails uses sanitize_sql_for_conditions internally for dealing with placeholders. Of course, that method is protected so you can't (cleanly) use it outside of an ActiveRecord model. You can get around the protectedness using send:
nearest = Site.minimum(
Site.send(:sanitize_sql_for_conditions, [
'abs(latitude - ?) - abs(longitude - ?)',
params[:lat].to_f, params[:lon].to_f
]
)
Or you could put that logic inside a Site class method so that you'd be allowed to use sanitize_sql_for_conditions without trickery:
class Site < ActiveRecord::Base
def self.whatever_this_is(lat, lon)
minimum(
sanitize_sql([
'abs(latitude - ?) - abs(longitude - ?)',
lat, lon
])
)
end
end
and then in your controller:
nearest = Site.whatever_this_is(params[:lat].to_f, params[:lon].to_f)
Take note of the to_f calls. If you don't include those then params[:lat] and params[:lon] will be Strings and sanitize_sql_for_conditions will quote them as such:
abs(latitude - '11.23') - abs(longitude - '42.6')
Your database may or may not be happy to see you trying to subtract a string from a number so it is best to say exactly what you mean and do the type conversion yourself.
Granted I can't tell what you're trying to accomplish from the example above, but it looks like you might be improperly using the minimum method which takes a method name as its first argument. For example:
Site.minimum(:latitude)
If you want to add conditions to it, I think you would want to use:
Site.where(country: 'USA').group(:id).minimum(:latitude)
Again, this example won't return the result you're expecting, but it should explain better how the API is used.
I would like to output a string from a helper like '30 Meters2' (but with a superscript 2).
The HTML entity for a superscript 2 is ² so I thought something like this would work:
"30 Meters " + raw("²")
But it doesn't work.
How can I do this?
Here's the entire method:
def area_conversion(feet, project)
if project.metric
"#{(feet * 0.0929).round} Meters" + raw("²")
else
"#{feet} sq. ft. "
end
end
Using html_safe doens't seem to work either:
def area_conversion(feet, project)
if project.metric
"#{(feet * 0.0929).round} Meters" + "²".html_safe
else
"#{feet} sq. ft. "
end
end
I think you need to declare the whole string as html_safe because a safe string merged with a unsafe string gets unsafe again. In your case it should be save because a string multiplied by a float is empty, so nobody can not put dangerous code into your string here.
So this:
"#{(feet * 0.0929).round} Meters²".html_safe
should be fine.
I have a quick question. I am currently writing a Nokogiri/Ruby script and have the following code:
fullId = doc.xpath("/success/data/annotatorResultBean/annotations/annotationBean/concept/fullId")
fullId.each do |e|
e = e.to_s()
g.write(e + "\n")
end
This spits out the following text:
<fullId>D001792</fullId>
<fullId>D001792</fullId>
<fullId>D001792</fullId>
<fullId>D008715</fullId>
I wanted the just the numbers text in between the "< fullid>" saved, without the < fullId>,< /fullId> markup. What am I missing?
Bobby
I think you want to use the text() accessor (which returns the child text values), rather than to_s() (which serializes the entire node, as you see here).
I'm not sure what the g object you're calling write on is, but the following code should give you an array containing all of the text in the fullId nodes:
doc.xpath(your_xpath).map {|e| e.text}