Rails 3 listing all users by week of created_at - ruby-on-rails

This works on the rails console (rails c) but when seen from browser it does not, it just not shows the results, no errors.
on controler i have:
def weekly_user_stats
#created_users = User.where("username IS NOT NULL")
#created_users_by_week = Hash.new{ |h,k| h[k] = [] }
#created_users.each do |u|
unless u.nil?
#created_users_by_week[u.created_at.beginning_of_week.strftime("%Y-%m-%d")].push("#{u.username}")
end
end
end
on views I have:
%ul
= #created_users_by_week.keys.sort.each do |k|
%li
= puts "#{k} : #{#created_users_by_week[k]}"
on the page results I only see the keys but not the values inside the keys that shoul be an array of users..
on the console works just fine..
what im doing wrong?

Shouldn't the view look more like this?
%ul
- #created_users_by_week.keys.sort.each do |k|
%li #{k} : #{#created_users_by_week[k]}
See: http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html

I'm not familiar with haml so I don't know about your specific issue. However I would suggest you to store a different date in your database in order to retreive quickly your created users by week (or even month if you wanted).
You could do that by storing an array as an attribute containing this things:
dates = ['20120307', '201203', '2012', '201210']
With
dates[0] # (yyyymmdd)
dates[1] # (yyyymm)
dates[2] # (yyyy)
dates[3] # (yyyyww) ww = week number
Then you could retreive users by querying on the dates attributes that includes '201210'.

Related

OR search with ActiveRecord

Overview
I want to do an OR search with one that is AND search in ActiveRecord
Detail
I want to change the table to be searched by conditional branching depending on the data stored in the record (whether the status value of the item model is accepted this time).
So, I tried conditional branching as shown below, but it ended up being an AND search.
What kind of description should I write if I want to search here by OR?
Code
items_controller.rb
#items.each do |item|
if item.status != 'accepted'
# search for Item model
#items = #items.where(name: search_params[:name])
else
# search for Master model
#items = #items.merge(Master.where(name: search_params[:name]))
end
end
def search_params
params.permit(
:name
)
end
↓
Generated SQL
AND `items`.`name` = 'test'
AND `masters`.`name` = 'test'
I want this SQL
`items`.`name` = 'test'
OR `masters`.`name` = 'test'
Environment
rails 6.0
Support for "or" was added in Rails 5 you can read more about it here. The syntax works like...
#items = Item.joins(:masters) # or some way to join in the other table
#items.where(name: search_params[:name]).or(Master.where(name: search_params[:name]))

Group by ruby on rails

I need to group the users based on created_at column by year and month,
User.all.group_by{ |q| [q.created_at.year, q.created_at.month]},
where I am getting hash with key [year, month], Is there any way to group the records which results like
{
year1 =>{ month1 =>[array of records], month2=>[array]},
year2 =>{ month1 =>[array of records], month2=>[array]}
}
Try to the following:
User.all
.group_by { |user| user.created_at.year }
.transform_values { |users| users.group_by { |user| user.created_at.month } }
you can get by
result = {}
User.all.each do |user|
result[user.created_at.year] = {} if !result[user.created_at.year].present?
result[user.created_at.year][user.create_at.month] = [] if !result[user.created_at.year][user.create_at.month].present?
result[user.created_at.year][user.create_at.month].push(user.attributes)
end
There are many ways to do this. Although the suggested duplicate does propose a solution, there are other ways to achieve it. One of them is using the code below (it's a refactor of one of the first answers).
{}.tap do |hash|
User.all.find_each do |user|
year = user.created_at.year
month = user.created_at.month
hash[year] ||= {}
hash[year][month] ||= []
hash[year][month] << user
end
end
What's good about this code is that you are not loading all user records into memory (bad if you have, let's say, 1M user records) because it uses find_each which, by default, fetches users by 1000.
It also only goes through each item once, unlike the accepted answer in the duplicate suggested above.
Overall, there's a lot of ways to tackle your problem in ruby. It's up to you to discover what you think is clean code. But make sure that what you decide to use is efficient.

building a simple search form in Rails?

I'm trying to build a simple search form in Ruby on Rails, my form is simple enough basically you select fields from a series of options and then all the events matching the fields are shown. The problem comes when I leave any field blank.
Here is the code responsible for filtering the parameters
Event.joins(:eventdates).joins(:categories).where
("eventdates.start_date = ? AND city = ? AND categories.name = ?",
params[:event][:date], params[:event][:city], params[:event][:category]).all
From what I get it's that it looks for events with any empty field, but since all of them have them not empty, it wont match unless all 3 are filled, another problem arises when I try to say, look events inside a range or array of dates, I'm clueless on how to pass multiple days into the search.
I'm pretty new to making search forms in general, so I don't even know if this is the best approach, also I'm trying to keep the searches without the need of a secialized model.
Below is probably what you are looking for. (Note: If all fields all blank, it shows all data in the events table linkable with eventdates and categories.)
events = Event.joins(:eventdates).joins(:categories)
if params[:event]
# includes below where condition to query only if params[:event][:date] has a value
events = events.where("eventdates.start_date = ?", params[:event][:date]) if params[:event][:date].present?
# includes below where condition to query only if params[:event][:city] has a value
events = events.where("city = ?", params[:event][:city]) if params[:event][:city].present?
# includes below where condition to query only if params[:event][:city] has a value
events = events.where("categories.name = ?", params[:event][:category]) if params[:event][:category].present?
end
To search using multiple days:
# params[:event][:dates] is expected to be array of dates.
# Below query gets converted into an 'IN' operation in SQL, something like "where eventdates.start_date IN ['date1', 'date2']"
events = events.where("eventdates.start_date = ?", params[:event][:dates]) if params[:event][:dates].present?
It will be more easy and optimised . If you use concern for filter data.
Make one concern in Model.
filterable.rb
module Filterable
extend ActiveSupport::Concern
module ClassMethods
def filter(filtering_params)
results = self.where(nil)
filtering_params.each do |key, value|
if column_type(key) == :date || column_type(key) ==
:datetime
results = results.where("DATE(#{column(key)}) = ?",
Date.strptime(value, "%m/%d/%Y")) if
value.present?
else
results = results.where("#{column(key)} Like ? ", "%#{value}%") if
value.present?
end
end
results
end
def resource_name
self.table_name
end
def column(key)
return key if key.split(".").count > 1
return "#{resource_name}.#{key}"
end
def column_type(key)
self.columns_hash[key].type
end
end
end
Include this concern in model file that you want to filter.
Model.rb
include Filterable
In your controller Add this methods
def search
#resources = Model.filter(class_search_params)
render 'index'
end
def class_search_params
params.slice(:id,:name) #Your field names
end
So, It is global solution. You dont need to use query for filter. just add this concern in your model file.
That's it.

ordering in rails based on the count of a word present in a single column

I have a model named Vendor. I have three different models associated with it.
Testimonial
Service
Works
I have to look up each of the tables and list the vendors(limit 5) which have the word "example" most number of times in a column in one of these models. How do I do this in rails?
I have something like this
Vendor.joins(:testimonials).where("testimonials.content LIKE ?","%example%")
I need to find the vendors who has the maximum number of occurrences of the word "example"
I hope I got you right now:
a=[]
vendors.each do |v|
c=0
c=v.testimonial.scan(/example/).count
if c>0
a=a.concat([{vendor: v, counts: c}])
end
In Ruby you can count the occurrence of a substring in a string in this way, for example
s = "this is a string with an example, example, example"
s.scan(/example/).count # => 3
This is how I ended up doing this. Not sure if my question was asked correctly. I made this with the help of a previous answer by #user3383458
vendor = Hash.new
Vendor.all.each do |v|
testi_word_count = 0
service_word_count = 0
title_word_count = 0
v.testimonials.each do |testi|
testi_word_count += testi.content.scan(/#{word_to_search}/).count
Rails.logger.info "testi_word_count"
Rails.logger.info testi_word_count
end
v.services.each do |service|
service_word_count += service.name.scan(/#{word_to_search}/).count
Rails.logger.info "service_word_count"
Rails.logger.info service_word_count
end
v.works.each do |work|
title_word_count += work.title.scan(/#{word_to_search}/).count
Rails.logger.info "title_word_count"
Rails.logger.info title_word_count
end
vendor[v]=testi_word_count + service_word_count + title_word_count
end

How to store the result of my algorithm?

I have an algorithm that searches through all of my sites users, finding those which share a common property with the user using the algorithm (by going to a certain page). It can find multiple users, each can have multiple shared properties. The algorithm works fine, in terms of finding the matches, but I'm having trouble working out how to store the data so that later I'll be able to use each unit of information. I need to be able to access both the found users, and each of the respective shared properties, so I can't just build a string. This is an example of the output, being run from the perspective of user 1:
user 4
sharedproperty3
sharedproperty6
user 6
sharedproperty6
sharedproperty10
shareproperty11
What do I need to do to be able to store this data, and have access to any bit of it for further manipulation? I was thinking of a hash of a hash, but I can't really wrap my head around it. I'm pretty new to programming, and Ruby in particular. Thanks for reading!
EDIT - Here's the code. I'm fully expecting this to be the most incorrect way to do this, but it's my first try so be gentle :)
So if I'm understanding you guys correctly, instead of adding the interests to a string, I should be creating an array or a hash, adding each interest as I find it, then storing each of these in an array or hash? Thanks so much for the help.
def getMatchedUsers
matched_user_html = nil
combined_properties = nil
online_user_list = User.logged_in.all
shared_interest = false
online_user_list.each do |n| # for every online user
combined_properties = nil
if n.email != current_user.email # that is not the current user
current_user.properties.each do |o| # go through all of the current users properties
n.properties.each do |p| # go through the online users properties
if p.interestname.eql?(o.interestname) # if the online users property matches the current user
shared_interest = true
if combined_properties == nil
combined_properties = o.interestname
else
combined_properties = combined_properties + ", " + o.interestname
end
end
end
if shared_interest == true
matched_user_html = n.actualname + ": " + combined_properties
end
end
end
end
return matched_user_html
render :nothing => true
end
This returns an array of hashes with all users and their corresponding sharedproperties.
class User
def find_matching_users
returning Array.new do |matching_users|
self.logged_in.each do |other_user|
next if current_user == other_user # jump if current_user
# see http://ruby-doc.org/core/classes/Array.html#M002212 for more details on the & opreator
unless (common_properties = current_user.properties & other_user.properties).empty?
matching_users << { :user => other_user, :common_properties => common_properties }
end
end
end
end
end
In your view you can do something like this:
<%- current_user.find_matching_users.each do |matching_user| -%>
<%-# you can acccess the user with matching_user[:user] -%>
<%-# you can acccess the common properties with matching_user[:common_properties] -%>
<%- end -%>
You can use a hash table with the key being the user object and the value being an array of the shared properties . This is assuming that you first need to do a lookup based on the user .
Something like this :
#user_results = { user1 => [sharedproperty3,sharedproperty7] , user2 => [sharedproperty10,sharedproperty11,sharedproperty12]}
You can then acces the values like :
#user_results[user1]
or you can also iterate over all the keys using #user_results.keys

Resources