How could we replace the ? from the rails sql query - ruby-on-rails

scope :accessible_by, -> (current_user) { where("loc_primary_email= ? OR loc_backup_email= ? ",current_user.email, current_user.email) }
How could I replace ? with :email so, that I don't need to pass current_user.email twice in query

You can replace it just like that, for the "?":
scope :accessible_by, -> (current_user) { where("loc_primary_email = :email OR loc_backup_email = :email ", email: current_user.email) }
But then the argument for where must contain a hash, where the email key must be present.
You can check the docs for this, using an array of as argument (of course, you can omit the brackets);
Alternatively, you can use named placeholders in the template, and
pass a hash as the second element of the array. The names in the
template are replaced with the corresponding values from the hash.
User.where(["name = :name and email = :email", { name: "Joe", email: "joe#example.com" }])
# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe#example.com';

Related

How do I access a local variable in Active Record query with SQL

I'm trying some code to find an attribute with a time value that is less than current time.
If I have current_time = Time.now, how do I find it using where such as:
Outage.where("end_time < current_time") # this doesn't work.
There are many ways to do that via placeholder.
Using ? Placeholder
You can use ? as a placeholder in a query condition.
User.where('users.name = ?', 'John')
With multiple placeholders:
User.where('users.name = ? AND users.last_name = ?', 'John', 'Smith')
Using Named Placeholder
User.where('first_name = :first_name', { :first_name => 'John' })
With multiple placeholder:
values = { :first_name => 'John', :last_name => 'Smith'}
conditions = 'first_name = :first_name AND last_name = :last_name'
User.where(conditions , values)
Noted that order does not matters. The following code would work correctly since we have already named those placeholders.
values = { :last_name => 'Smith', :first_name => 'John'}
conditions = 'first_name = :first_name AND last_name = :last_name'
User.where(conditions , values)
References: Using Named Placeholders in Ruby
You can use placeholder - ? and then pass the value, like this:
Outage.where('outages.end_time < ?', current_time)

"Field 'posts' is missing required arguments: id",

I am trying to play around with rails hooked up to graphql and I have the following error trying to display a series of posts by a user
"Field 'posts' is missing required arguments: id"
Here is my query:
query {
posts(user_id: 10, type: "Video") {
title
file
}
}
And in my query_type.rb file I have the following defined:
field :posts, [Types::PostType], null: false do
argument :id, ID, required: true, as: :user_id
argument :type, String, required: true
end
def posts(user_id:, type:)
posts = Post.where("user_id = ? AND type = ?", user_id, type)
end
It is a simple query. I'm new to this technology (GraphQL) and I don't see what the problem is. Can someone pinpoint what is wrong? Thank you.
You need to send the exact name in the parameters when running the query.
In your schema definition you have 2 required arguments called id of type ID and type of type string. So you have 2 options:
Update your query to send in the correct name id:
query {
posts(id: "10", type: "Video") {
title
file
}
}
Or, update your schema definition to receive a user_id:
field :posts, [Types::PostType], null: false do
argument :user_id, ID, required: true, as: :user_id
argument :type, String, required: true
end
def posts(user_id:, type:)
posts = Post.where("user_id = ? AND type = ?", user_id, type)
end

Get other field if this is included in the array object

Title may sound off but below explains more.
I need to know if an item is included in an array object:
[
{ id: 12345, name: "Bob", email: "bob#builder.com" },
...
{ id: 13456, name: "job", email: "joe#farm.com" }
]
In english: If this email present, give me their id
users = User.all
users.any?{|u| u.email == "bob#builder.com"} # true
That will be true. Now, how to get the id of the user which is "12345"? Note, I will not know the id.
Since you seem to be using ActiveRecord, it would be faster to query the database for the email:
# returns the user id or nil, if not found
User.find_by(email: 'bob#builder.com').pluck(:id)
You can try like this if you have array of hashes:
arr.map do |h|
h[:id] if h[:email] == "bob#builder.com"
end.compact
It will return the value of id in an array of all the hashes which satisfies the condition.

update only attributes that are not empty

I have a mass edit form. A user selects multiple existing records. And then clicks on a button which displays a new record form (all values are empty). User enters some data for each attribute and then clicks submit, which then updates all the selected records with the values specified.
The params hash submitted to the server looks like this:
{
'lead_ids' => [2,4]
'lead' => {
'name' => 'donato',
'email' => "",
'phone' => ""
}
}
So in this example, only the name attribute should be updated for lead with an id of 2 and 4.
This is what I came up with:
lead = Lead.new lead_params
leads = Lead.where(id: params[:lead_ids])
changed_attrs = lead_params.select {|param| !param.values.first.blank?}
leads.each do |lead|
lead.update_attributes changed_attrs
end
Is there a more Railsy way to do this?
I would refactor the code into something a bit cleaner, like this:
leads = Lead.where(id: params[:lead_ids])
hash = lead_params.reject { |k, v| v.blank? }
leads.update_all(hash)
You search for the leads, remove the pairs with empty values, then update all the leads with that hash.
Could even make it a two-liner:
hash = lead_params.reject { |k, v| v.blank? }
Lead.where(id: params[:lead_ids]).update_all(hash)

Getting sub strings using other columns in table - Ruby on Rails

Trying to create a table to generate random data using 'faker', for my username column I wanted to concatenate two sub-strings from two other fields in my table.
For example:
First Name: John, Last Name: Abbott, Username: jabbott
I seed my data like so
Post.create!(
Lastname: Faker::Name.last_name,
Firstname: Faker::Name.first_name,
Username: " first letter of first name" + "lastname"
)
Is there a sub string method that does this on Ruby?
Not a "sub string" method, but you can access specific points in strings with []
Example:
username = "#{first_name[0]}#{last_name}".downcase
or you could monkey patch String like this:
class String
def user_name
first_name, last_name = self.split
"#{first_name[0]}#{last_name}".downcase
end
end
And then generate your string like this
name = Faker::Name.name
create_hash = {
:Firstname => name.split.first,
:Lastname => name.split.last,
:Username => name.user_name,
}
Post.create!(create_hash)

Resources