Rails querying with an array - ruby-on-rails

so in my controller i made a page which shows only the group_pages(the scaffold) in which the array #group_post_users contain the current user so:
def my_group
#group_pages = GroupPage.all
#group_pages.each do |group_page|
#group_page_users = group_page.page_users.split(',')
#group_page_users.push(group_page.user.email)
#mg_users = User.find_by_email(#group_page_users)
#gg_users = User.where(:email => #group_page_users)
group_page.super_uses = #gg_users
#g_pages = GroupPage.where(:super_uses => #selected_posts.map(&:id))
end
end
now i have an array of users for a group_page in #group_page_users and i only want to show the group pages which contain the current user inside the #group_page
basically i want something like this :
#g_pages = GroupPage.where(:super_uses => current_user.email)

Related

how append an object to association relation in rails?

In a rails 4.1 application I need to add an object to an "AssociationRelation"
def index
employee = Employee.where(id_person: params[:id_person]).take
receipts_t = employee.receipts.where(:consent => true) #gives 3 results
receipts_n = employee.receipts.where(:consent => nil).limit(1) #gives 1 result
#I would need to add the null consent query result to the true consent results
#something similar to this and the result is still an association relation
#receipts = receipts_t + receipts_n
end
Is there a simple way to do this?
A way of solving this:
def index
employee_receipts = Employee.find_by(id_person: params[:id_person]).receipts
receipts_t = employee_receipts.where(consent: true)
receipts_n = employee_receipts.where(consent: nil).limit(1)
#receipts = Receipt.where(id: receipts_t.ids + receipts_n.ids)
end
Unfortunately .or() can't be used here because it's only available from Rails v5.0.0.1
you could do this way
receipts_t_ids = employee.receipts.where(:consent => true).pluck(:id)
receipts_n_ids = employee.receipts.where(:consent => nil).limit(1).pluck(:id)
#receipts = Receipt.where(id: receipts_t_ids + receipts_n_ids)
To avoid extra queries and keeping arrays in memory, you can use or
Like this:
def index
employee_receipts = Employee.find_by(id_person: params[:id_person]).receipts
#receipts =
employee_receipts.where(consent: true).or(
employee_receipts.where(consent: nil).limit(1)
)
end

How do I perform an ActiveRecord query after form submission?

Would this work? I want to do something like coins transfer
#logs = Logs.new(log_params)
#logs.save
#tt = Users.where(email: params[:email]).update(money: Users.find(current_user.id)['money'] - params[:money])
#tt.save
#wr = Users.find(current_user.id).update(money: Users.where(email: params[:email])['money'] + params[:money])
#wr.save
I don't know if you are planning to display those values in your views, but you could do something like this:
sender = Users.where(email: params[:email]).first
# This returns the user
recipient = Users.find(current_user.id)
# or just current_user if it inherit from the User class
money_to_substract = recipient.money - params[:money]
money_to_sum = recipient.money + params[:money]
Then your transsaction would be a bit dryier
User.transaction do
#logs = Logs.new(log_params)
#tt = sender.update(money: money_to_substract)
# update saves to the database so no need to call save
# #tt.save
#wr = recipient.update(money: money_to_sum)
# update saves to the database so no need to call save
# #wr.save
end
But IMHO, I would do something like this:
models/User.rb
class User < ActiveRecord::Base
...
def sends_money(amount)
money_to_substract = self.money - amount
update(money: money_to_substract)
end
def receives_money(amount)
money_to_sum = self.money + amount
update(money: money_to_sum)
end
...
end
In your controller
amount = params[:money].to_i
User.transaction do
#logs = Logs.new(log_params)
#tt = sender.sends_money(amount)
#wr = recipient.receives_money(amount)
end
Which makes things easier to read and follow through your code.
Hope this helps!

Is there a way I can use a rake task or method that can rewrite an HTML partial using erb?

Sorry for the confusing title, but I will elaborate here.
ok so on the users index page of my site I have a list of Top Trending songs. The list is ordered by user rankings and this list changes dynamically as each songs aggregate ranking changes relative to each other.
class SongratingsController < ApplicationController
#Top100 = Rails.cache.read('Top100')
lastSpot = #Top100.last
def reCalcTop100
#Top100 = Song.where('num_stars > ?', 0 ).order('num_stars desc, total_score desc').limit(100)
Rails.cache.fetch('Top100'){#Top100}
end
def addRatingToSong
userID = params[:uid].to_i
songId = params[:sid].to_i
rVal = params[:valR].to_i
#averageS = []
songRate = Songrating.find_by(:user_id => userID, :song_id => songId)
if songRate != nil
oldScore = songRate.rating
songRate.update_attributes(:rating => rVal)
#song = Song.find(songId)
score = #song.total_score - oldScore
newScore = score + rVal
averageScore = newScore/#song.songratings_count
#song.update_attributes(:total_score => newScore,:num_stars => averageScore)
#averageS[0] = averageScore
#averageS[1] = #song.songratings_count
else
Songrating.create!(:user_id => userID, :song_id => songId,:rating => rVal)
#song = Song.find(songId)
newScore = #song.total_score + rVal
averageScore = newScore/#song.songratings_count
#song.update_attributes(:total_score => newScore,:num_stars => averageScore)
#averageS[0] = averageScore
#averageS[1] = #song.songratings_count
end
if newScore > lastSpot.total_score && averageScore > lastSpot.num_stars
reCalcTop100
end
if request.xhr?
render :json => {
:starData => #averageS
}
end
end
end
As you can see in these two photos below I have a view partial that shows this list, but right now I have the list generated each time a user logs into the main page. But since this list is not unique to the user, I feel I am wasting time regenerating this list.
ideally I would like to generate and write a static HTML partial only when the top100 list changes, but I don't really know how to accomplish this.
thanks.
Yep just use erb
vars = OpenStruct.new({some_var: some_val})
rendered_html = ERB.new(File.read("#{Rails.root}/app/templates/embed_code.html.erb")).result(vars.instance_eval { binding })
This will put the rendered html in the rendered_html variable from there you can write it to a file or do anything you want. This should work in the context of a ruby class or rake task afaik.
The vars are passed to the template and can be used as <%= some_var %> in the template.
Now that i've answered you actual question, i think the better solution is to just use Rails.cache to cache the rendered data.
Anything that takes a long time can be cached with
result = Rails.cache.fetch "some_cache_key" do
# things you want to cache
end
this will cache the block and return it to result. if unstale cached data exisits in the future it will just return it from cache, if cache is empty or stale it will re-execute the block and return it into result.
Finally in the context fo a controller you can just use action caching which is a bit more hands off.
See: http://guides.rubyonrails.org/caching_with_rails.html for more details.

POST Multiple Row to Database with fill out only one form on RAILS

I'm try to develop one rails application.
When I fill out the form, I'm getting this parameter.
"daysoff"=>{"offdate"=>"06/08/2015, 06/09/2015, 06/10/2015, 06/11/2015, 06/12/2015", "assign_id"=>"3", "user_id"=>"2"}
Here is my index controller,
def index
#people = User.all
#user = User.current
#daysoff = Daysoff.new
end
My table coloumns are offdate (date), user_id (int), :assign_id (int), so i want to post each date for one row and other column values must be same.
How should i write create controller ?
You could do something like
off_dates = params["daysoff"]["offdate"].try(:split,',')
off_dates.each do |off_date|
days_off = Daysoff.new
days_off.offdate = Date.strptime(off_date.strip, "%m/%d/%Y")
days_off.user_id = params["user_id"]
days_off.assign_id = params["assign_id"]
days_off.save!
end

Validating parameters to create a class, parameters created in the controller arn't being added.

I create a class that takes two input parameters from the user, these input parameters are then used to create five others, the problem is that the five others don't show up when I check my validated paramaters only the first ones.
I know that all of the new parameters are added to the params but they don't show up in the model time_delta_params hash when I check what's in it only the first two. Thanks for any help!
My create method for the controller
def create
# XXX Add these columns to the model and populate them
# finalRating, positiveTweets, negativeTweets, neutralTweets, totalTweets
tweetRatings = {:finalRating => 0, :positiveTweets => 0, :negativeTweets => 0, :neutralTweets => 0}
#stock = Stock.find(params[:stock_id])
tweets = getTweets(#stock.hashtag, time_delta_params[:start], time_delta_params[:length].to_i)
tweets.each do |tweet|
case processTweet(tweet)
when 1
tweetRatings[:positiveTweets] += 1
tweetRatings[:finalRating] += 1
when -1
tweetRatings[:negativeTweets] += 1
tweetRatings[:finalRating] -= 1
else
tweetRatings[:neutralTweets] += 1
end
end
params[:final] = tweetRatings[:finalRating]
params[:positive] = tweetRatings[:positiveTweets]
params[:negative] = tweetRatings[:negativeTweets]
params[:neutral] = tweetRatings[:neutralTweets]
params[:total] = tweets.count
# printSomthingToRender(time_delta_params)
#time_delta = #stock.time_deltas.create(time_delta_params)
redirect_to stock_path(#stock)
end
My validation:
def time_delta_params
params.require(:time_delta).permit(
:start,
:length,
:final,
:positive,
:negative,
:neutral,
:total
)
end
You are not merging the additional parameters into the time_delta hash, but straight to the top level of params. time_delta is a hash within params.
You need to do something like:
params[:time_delta].merge!(final: tweetRatings[:finalRating],
positive: tweetRatings[:positiveTweets],
negative: tweetRatings[:negativeTweets],
neutral: tweetRatings[:neutralTweets],
total: tweets.count)
You're calling create with the time_delta_params that isn't going to contain the tweetRatings data. You would need to do something like params['time_delta'][:final] = tweetRating[:finalRating]. You could also call create and create your hash there or rename the values in the tweetRatings hash to match what is in the model.

Resources