A loop in a loop to fill an array? - ruby-on-rails

I am building a time registration program. Users can work on a project, and I want to display in a chart how many hours each user worked on a project, let's say, each month. The chart plugin works like this:
first_serie = OpenFlashChartLazy::Serie.new(
[["2008-1",100],["2008-2",120],["2008-3",130]],
{:title=>"name_of_user1",:start_date=>Time.mktime(2008,1,1),:items=>8})
This adds a new line in the graph.
My question is how can I loop through all my users and for each fill a new series with data from the database?

I have no idea how you generate all the data for Serie.new, but you can get started using this:
#series = []
users = User.find(:all)
users.each do |user|
#series << OpenFlashChartLazy::Serie.new(blah, blah, blah)
end
This will add all of the added Serie objects to an array.

As a follow up to Pesto would be nicer to use inject.
#series = User.all.inject([]) do |mem, user|
mem << OpenFlashChartLazy::Serie.new(user.foo, user.bar, user.foobarbob)
end
Same code, just doesnt have a #series = []

Related

ActiveRecord Grouping posts created by the same user in the past hour

I have a Story model. A story is created by a user, and those stories go into a feed. If a user creates more than one story within an hour, I want to only show one story, so my question is how do I write an ActiveRecord query to group by created_at to the hour, and user_id?
So this turned out to be pretty easy.
Story.find_each.group_by do |story|
[story.user_id, story.created_at.beginning_of_hour]
end
then you can map over the results and do whatever. I checked if a group had more than one object in it, and if it did, created a new Story, inserted the info for all the stories I wanted to group, and then added it to an array of stories. I never save the new story, so I don't end up with a bunch of weird stories saved.
If anyone has a better way to do this, I'm open to suggestions.
Here is the entire method:
def self.smart_feed
feed = []
self.find_each(batch_size: 10).group_by do |story|
[story.user_id, story.created_at.beginning_of_hour]
end.map do |stories|
if stories.second.count > 1
temp_story = self.new()
stories.second.map do |story|
if story.ratings.any?
temp_story.ratings.append(story.ratings)
elsif story.flights.any?
temp_story.flights.append(story.flights)
end
temp_story.description = "Added #{temp_story.ratings.size} new ratings and #{temp_story.flights.size} new flights"
temp_story.user_id = story.user_id
end
feed.append(temp_story)
else
feed.append(stories.second.first)
end
end
return feed.reverse
end

Rails - submitting JSONs to database from controller

I am working on a Rails app, and I am attempting to insert attributes from JSONs as database entries. I'm running into a problem, though, and would appreciate some guidance.
I've been able to jam a few things together and come up with something that sort of works...
def create
#report_group = Array.new
#report_group.push({location:"home", comments:"Hello, database!"}, {location:"away", comments:"Goodbye, database!"})
#report_group.each do |x|
#new_report = Report.new(x)
#new_report.user_id = current_user.id
#new_report.save
end
end
private
def report_params(params)
params.permit(:user_id,:location,:comments)
end
This is a good first step - this commits two entries to my database, one for each of the hashes pushed into #report_group, but it is suffering from a problem - the create action does not reference the report_params whitelist.
I have built several Rails apps where entries are submitted one at a time via the standard Rails form helpers, but I have never done it with multiple JSONs like this before. Trying out the syntax I'd use in a typical form helper situation
#new_report = Report.new(report_params(x))
throws the expectable error undefined method permit' for #<Hash:0x007f966b35e270> but I am not sure what else to do here.
EDIT TO SHOW SOLUTION
Big thanks to #oreoluwa for pointing me in the right direction. Here's the solution that I came up with.
def create
#report_group = Array.new
#report_group.push({location:"home", comments:"Hello, database!"}, {location:"away", comments:"Goodbye, database!"})
#report_group.each do |x|
hash = ActionController::Parameters.new(x)
#new_report = Report.new(report_params(hash))
#new_report.user_id = current_user.id
#new_report.save
end
end
private
def report_params(params)
params.permit(:user_id,:location,:comments)
end
You're getting the error because a Hash is not the same as an ActionController::Parameters. In order to use the permit method with your Hash you may need to first convert it to ActionController::Parameters, as such:
hash = {location:"home", comments:"Hello, database!"}
parameter = ActionController::Parameters.new(hash)
parameter.permit(:user_id,:location,:comments)
I don't know if that is what you're looking for, but I thought to point you in the right direction.

How to get random ids, that are not on X list

So I have a code snippet that essentially finds a random List, and prints it out. However in the loop it also saves that id into a table called statuses.
Now I want to be able to go through that list again, and this time print out 150 randoms. However, this time I want it to check through statuses first to make sure that List item haven't been printed out before.
Here's the code I have now:
class ScheduleTweets
#queue = :schedules_queue
def self.perform(user_token, user_id)
client = Buffer::Client.new(user_token)
user = user_id
list = List.all.sample(150)
profiles = client.profiles
profile_ids = profiles.map(&:id)
list.each do |list|
list.statuses.create(:user_id => user)
client.create_update(body: {text: "#{list.text}", profile_ids: profile_ids })
end
end
end
If I were to guess I should add something after List.all.sample(150) where it checks if the list has a list_id that is present in Status.
Gather the list items from the statues table and make an array with that result.
stat_ids = Status.all.collect{|s| s.list_id}
now loop through the random 150 list and check the list id contains in stat_ids or not.
random_lists.each do |rl|
if stat_ids.include?(rl.id)
//do something
end
end
As I don't know your database architecture, I assumed it as above.

assigning values to model

I'm kinda new to coding on rails. It would be great if you could help me out with what I think might be noob question.Here's my code:
def create
#project = Project.new(params[:project])
if #project.save
redirect_to new_project_path
end
student=#project.student_str.split(";")
#users = User.where(:code => student)
#users.each do |c|
puts c.email
end
#users.each do |c|
puts "I'm here"
c.projects = "#{c.projects};#{#project.id}"
end
end
So, in the create method, Each time a new project is created a string called student_str is stored where the ID number of each student is seperated by a ";". I split that string to an array using the split function to get an array of student ID's. I have the puts c.email and puts "I'm here" to make sure the loops are working fine. I get the proper outputs on terminal.
The problem here is the
c.projects = "#{c.projects};#{#project.id}"
That simply does not seem to be working.
My model is not updated when this line is executed. I get no errors though.
Can you tell me what I might have to do to fix this?
thanks!
You have to call c.save after you updated the projects attribute. Otherwise the object is updated but not the database so the next time you load it the changes are gone.

Iterating through every record in a database - Ruby on Rails / ActiveRecord

n00b question. I'm trying to loop through every User record in my database. The pseudo code might look a little something like this:
def send_notifications
render :nothing => true
# Randomly select Message record from DB
#message = Message.offset(rand(Message.count)).first
random_message = #message.content
#user = User.all.entries.each do
#user = User.find(:id)
number_to_text = ""
#user.number = number_to_text #number is a User's phone number
puts #user.number
end
end
Can someone fill me in on the best approach for doing this? A little help with the syntax would be great too :)
Here is the correct syntax to iterate over all User :
User.all.each do |user|
#the code here is called once for each user
# user is accessible by 'user' variable
# WARNING: User.all performs poorly with large datasets
end
To improve performance and decrease load, use User.find_each (see doc) instead of User.all. Note that using find_each loses the ability to sort.
Also a possible one-liner for same purpose:
User.all.map { |u| u.number = ""; puts u.number }

Resources