Search multiple entries (hash values) in controller - ruby-on-rails-3

Here's what I'm trying to do:
I've got three tables:
Appointments Users and Shares -
I'd like to assign users to an appointment.
So what I did until now is that I created a table in between appointment and user which
stores the user_id and appointment_id which a user is assigned to.
I'm able to search the shares for a specific appointment in my appointments_controller
with
#shares = Shares.find(:all, :conditions => { :appointment_id => #appointment.id })
After that I get a hash #shares which looks like this:
[#<Shares id: 10, user_id: 3, appointment_id: 1, created_at: "2012-12-04 10:24:16", updated_at: "2012-12-04 10:24:17">, #<Shares id: 12, user_id: 2, appointment_id: 1, created_at: "2012-12-04 10:28:38", updated_at: "2012-12-04 10:28:39">]
What I'd like to do now is a query in the users table to find the usernames that belong to the user_ids i found in the shares hash.
I tried that with something like this:
#shares.each do |s|
#participants = User.all(:conditions => {:id => s.user_id})
end
But it doesn't work because the participants hash gets overwritten every time the loop starts...
Thanks for your help

#shares = Shares.find(:all, :conditions => { :appointment_id => #appointment.id })
#participants = User.all(:conditions => ["id IN (?)", #shares.map{|s| s.user_id}.compact])

Related

I want to show the user name that user has booked to slot using laravel

I want to show user name that user has booked to slot on calender and i have already made relation how can i show username please help me thanks.
Booking Model
public function users(){
return $this->hasOne('App\Models\User','id','user_id');
}
Controller
public function getBookingSlot(Request $request){
$userBookings = Booking::with('users')->where('room_id',$request->room_id)->where('booking_holding_status',1)->get();
foreach($userBookings as $booking){
$events [] = [
'id' => $booking->id,
'calendarId' => $booking->id,
'title' => 'user name',
'category' => 'time',
'dueDateClass' => '',
'bgColor' => "#e6515f",
'color' => "#ffffff",
'isPending' => 'false',
'isFocused' =>'false',
'start' => $booking->start_datetime,
'end' => $booking->end_datetime,
];
}
return \Response::json([
'events' => $events ?? null
]);
}
$booking->users[0]->username;
booking object contains booking details in it along with the object of users which it selects from the user table... I am not sure about hasOne() relationship. I have used it with belongsToMany().
so you get the user object from the booking object than for the first user [0] get its username.
If this does not work then the booking object may have only 1 user object, not an array of objects.. then access it like this...
$booking->users->username;

select vs distinct vs uniq?

I am confused by Ruby's ActiveRecord uniq method. I am using it to try to get back an array of complete objects, not just a particular field.
In my Padrino app script, which saves newspaper names and scores as Score objects, the uniq method by attribute on an ActiveRecord Relation is not working, and neither is distinct, with or without SQL syntax. Can anyone explain what is going on?
class Score < ActiveRecord::Base
def self.from_today
self.where('created_at > ?', Date.today)
end
end
scores = Score.from_today
scores.class
=> Score::ActiveRecord_Relation
scores.first
=> #<Score id: 123, score: -2.55, source: "Mail", created_at: "2016-08-11 04:29:24", updated_at: "2016-08-11 04:29:24">
scores.map(&:source)
=> ["Mail", "Guardian", "Telegraph", "Independent", "Express", "Mail"]
scores.uniq(:source).count
=> 6
scores.distinct(:source).count
=> 6
scores.select('distinct (SOURCE)').count
=> 5 #AHA, it works!
scores.select(:source).distinct
=> #<ActiveRecord::Relation [#<Score id: nil, source: "Telegraph">, #<Score id: nil, source: "Mail">, #<Score id: nil, source: "Independent">, #<Score id: nil, source: "Express">, #<Score id: nil, source: "Guardian">]>
#oops, no it doesn't
In Rails 5 distinct has no parameter. In Rails 4.2 the parameter is only true or false. When true, return distinct records, when false return none distinct records. uniq is in this case only an alias for distinct
So for Rails 4
scores.select(:source).distinct.count is what you want. This restricts distinct to column source

Joining Unrelated Tables in Rails

Bottom line - I want to join two database tables together that do not "belong to" each other but do have a common field.
After some research on StackOverflow, I found some solutions to similar problems that use SQL directly, like so:
Address.joins('INNER JOIN phones on addresses.person_id = phones.person_id').select("addresses.*, phones.*").limit(1)
When I use the above statement in my rails console, however, it performs the following SQL query:
Address Load (0.3ms) SELECT addresses.*, phones.* FROM `addresses` INNER JOIN phones on addresses.person_id = phones.person_id LIMIT 1
and returns the following data (censored for privacy reasons):
=> #<ActiveRecord::Relation [#<Address id: 0001, created_at: "YYYY-MM-DD hh:mm:ss", updated_at: "YYYY-MM-DD hh:mm:ss", description: nil, line1: "123 Evergreen Terrace", line2: "", line3: "", city: "Springfield", state: "IL", country: "USA", zip: "11111", building_number: "001", person_id: 1, address_type: "Home", primary: false, show: nil, job_id: nil, room_number: "001", source: "HR", effective_date: "YYYY-MM-DD">]>
Not a single field from the Phone table made it into the final record.
Do I have to make these unrelated tables "belong to" each other to make them work? Like -
class Address < ActiveRecord::Base
belongs_to :person
end
class Phone < ActiveRecord::Base
belongs_to :person
belongs_to :address
end
Or can I do what I want without modifying my models' relationships?
The data might not be visible in the query, but the record will respond to those fields that were fetched by the query, meaining if the phone record has a number attribute for example, doing a call to .number will respond with the fetched number
address = Address.joins(....).select('*').first
address.number # => this will print the phone number of the phone record.

rails - find with condition in rails 4

I recently upgraded my rails to Rails 4.1.6.
This query used to work :
#user = User.find(:all, :conditions => { :name => 'batman' })
Now I get this error message:
Couldn't find all Users with 'id': (all, {:conditions=>{:name=>"batman"}}) (found 0 results, but was looking for 2)
When I check the logs I can see that rails is trying to do a completely different query :
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IN ('all', '---
:conditions:
:name: batman
')
It looks like, it's trying to get all the users with the id "all" and "{:conditions=>{:name=>"batman"}}". Please help.
UPDATE:
My real question behind that was I want to get a specific user and add to it his cars, only the cars that are blue. For example this is my query, the user id is 20.
#user = User.joins(:cars).find(20, :cars => {:color => "blue"})
But I get this error:
Couldn't find all Users with 'id': (20, {:cars=>{:color=>"blue"}})
(found 41 results, but was looking for 2)
You should definitely read this ActiveRecord Query Interface quide
User.where(name: "batman")
Some others already pointed out: The query syntax changed. Try this:
#user = User.joins(:cars).where(:cars => { :color => "blue" }).find(20)
Note that this will raise an exception if that record is not found, to return an array empty instead call:
#user = User.joins(:cars).where(:id => 20, :cars => { :color => "blue" })
I suggest to read: http://guides.rubyonrails.org/active_record_querying.html
If you want to load the user even if he does not have any cars and than display only his blue cars, I would do it like this:
#user = User.find(20) # returns the user
#user.cars.where(:color => 'blue') # returns the user's blue cars (or an empty array)
The find method is deprecated in this version of Rails (see the reference).
Instead, you must use the where method.
In your case, you should write #user = User(:name => 'batman') or #user = User(name: 'batman')

Find top scored from parent and all their children in Rails

I have a model called User, which has self-join association as this:
has_many :children, class_name: "User",
foreign_key: "parent_id"
belongs_to :parent, class_name: "User"
And it also has an association with a Post model:
User has_many post
Each Post object has a score attribute, and I am trying to find the posts for a given user and their children which have a highest score, which score is bigger than 0, and which satisfy a particular attribute. So right now, I have this method in my Post model:
def self.top_related_scored_by_user_id(user_id, max)
where(:user_id => user_id).
where(:related_image => true).
where('score > 0').
order(score: :desc).
first(max)
end
But, I would like to be able to look not just for the User with user_id, but also for their children. How can I do that?
Thanks
Its very simple:
def self.top_related_scored_by_user_id(user_ids, max = nil)
user_ids = user_ids.kind_of?(Array) ? user_ids : [user_ids]
scope = where(:user_id => user_ids)
scope = scope.where(:related_image => true)
scope = scope.where('score > 0')
scope = scope.order(score: :desc)
scope = scope.limit(max) if max.present?
scope
end
You can give an array of ids to the where clause, it will generate a condition like this:
WHERE id IN (1, 2, 3, 4)
A little improvement of your method, to make it more flexible:
def self.top_related_scored_by_user_id(user_ids, options = {})
options = { limit: 10, order: 'score DESC',
score: 0, related_image: true }.merge(options)
user_ids = user_ids.kind_of?(Array) ? user_ids : [user_ids]
scope = where(:user_id => user_ids)
scope = scope.where(:related_image => options[:related_image])
scope = scope.where('score > ?', options[:score])
scope = scope.order(options[:order])
scope = scope.limit(options[:limit])
scope
end
This way you can easily set options with the same function, and it has default values that can be overridden if needed.