each_with_index duplicated records - ruby

first of all, excuse me if my english is not always very good.
I have a problem with the each_with_index... When I show a project, I display the offers for this project. I have to make appear a banner in third position of offers, so I use each_with_index for that.
The problem is that: if I have sixteen offers on a project, I have sixteen times the entirely list of offers, and I don't know why.
This is my code:
- #offers.each_with_index do |offer, index|
- if !user_signed_in? && (#project.published? || #project.pending_attribution?)
- if #offers.size >= 3 && index == 3
= render 'offer_cta'
- contact_bloc = user_contact_bloc(offer.user, viewer: current_user, display_contact_info: offer.display_contact_info?)
.card.offer-card.mt-4[offer]{ class: offer_class(offer) }
.card-header.d-flex.justify-content-between.align-items-center.border-bottom-0
.offer-date
%span.text-muted
Offer filed on
= l(offer.created_at, format: '%d/%m/%Y à %Hh%M')
- if user_signed_in? && current_user.admin? && !offer.user.suspended_at.nil?
... exctera
Also, if I try this in my console, I don't have any problem...
Have you ever had this problem?
Don't hesitate to ask me if you need more information.
EDIT :
This is the code in my render 'offer_cta', a very basic code:
.row
.col-md-12
.project-cta.p-5.mb-2.text-center
%h5
%strong
blabla
%p.text-muted blablabla
%p.m-0
= link_to "Send a quote", "", class: "btn btn-primary px-3", data: { toggle: 'modal', target: '#modal-sign' }, onclick: "ga('send', 'event', 'button', 'Clic', 'Sign up');", tabindex: -1
#offers initialization:
#offers = #project.offers_accessible_by(current_ability, current_user)
#offers.mark_as_read_for(current_user)
#offers = #offers.includes(:offer_interactions, user: [:user_profile, :user_subscription, :user_contact])

Related

How to get commit history of users in gitlab in rails

I am trying to create an app which will fetch the gitlab/github commit history of the user which i can just show in a side panel and it can be checked on or off depending on my criteria. I want to know if there is a way to fetch the current logged user's gitlab/github commit history. I tried to use the gem
https://github.com/libgit2/rugged
But couldn't find a way to implement my need. If anyone knows how to implement this it would be so much helpful. Thanks.
Update
I have now managed to get the user by using :
Gitlab.endpoint = 'https://gitlab.com/api/v4'
Gitlab.private_token = 'token'
g = Gitlab.client(
endpoint: 'https://gitlab.com/api/v4',
private_token: 'token',
httparty: {
headers: { 'Cookie' => 'gitlab_canary=true' }
}
)
By using the command g.user i am able to get the user but i need to get the commits of the user that he has done in gitlab.
Use this gitlab API GET /projects/:id/repository/commits to fetch all the commits on a repository gitlab api. Check the attached code for more details.
Basically this git log --author="user_name" command can give you git commit history for a specific user, you can even use email address just the first name or last name in the above command.
Once you have authenticated with gitlab you can run the following command from ruby.
cmd = 'git log --author="user_name"'
system(cmd)
Sample code form ruby to connect to gitlab using private token which is not ideal but just an example
require 'json'
require 'curb'
require 'net/http'
begin
def parseCoverageReport(report_text)
coverage_perc = report_text.match /All files\s+\|\s+(\d+\.?\d+).*\n/
if not coverage_perc then
coverage_perc = report_text.match /^TOTAL\s+\d+\s+\d+\s+(\d+)%$/
end
if coverage_perc then
#if we found coverage value in job trace
#puts "coverage_perc[1]: #{coverage_perc[1]}"
coverage_perc[1].to_i
end
end
gen_config = YAML.load_file("config/general.yml")
gitlab_config = YAML.load_file("config/gitlab.yml")
SCHEDULER.every gen_config[:job_trigger_interval], :first_in => 0 do |job|
table = {
title: "Projects",
hrows: Array.new.push({cols: [
{value: "Project name"},
{value: "Open Merge Requests"},
{value: "Code coverage"}
]}),
rows: Array.new
}
instances = gitlab_config['instances']
instances.each do |instance|
gitlab_url = gitlab_config['instances'][instance.first]['url']
# gitlab_token = gitlab_config['instances'][instance.first]['api_key']
gitlab_token = ENV[gitlab_config['instances'][instance.first]['api_key']]
red_threshold = gitlab_config['instances'][instance.first]['red_threshold']
orange_threshold = gitlab_config['instances'][instance.first]['orange_threshold']
cov_red_threshold = gitlab_config['instances'][instance.first]['cov_red_threshold']
cov_orange_threshold = gitlab_config['instances'][instance.first]['cov_orange_threshold']
projects = gitlab_config['instances'][instance.first]['projects']
projects.each do |name, project|
merge_reqs = JSON.parse(Curl.get("#{gitlab_url}/api/v4/projects/#{project['id']}/merge_requests?state=opened&private_token=#{gitlab_token}&per_page=200").body_str)
git_project = JSON.parse(Curl.get("#{gitlab_url}/api/v4/projects/#{project['id']}?private_token=#{gitlab_token}").body_str)
opened_mrs = merge_reqs.select { |merge_reqs| %w[opened].include? merge_reqs['state'] }
repo_name = git_project['name']
repo_url = git_project['web_url']
status = case
when opened_mrs.size >= red_threshold then 'danger'
when opened_mrs.size >= orange_threshold then 'warning'
else
'ok'
end
mrs_count = "#{opened_mrs.size}"
send_event("#{name}_mr", { current: mrs_count, status: status })
color = case
when opened_mrs.size >= red_threshold then 'red'
when opened_mrs.size >= orange_threshold then 'orange'
else
'green'
end
font_color = color == 'orange' ? 'black' : 'white'
cov_color = color
font_cov_color = 'white'
code_coverage = "---"
code_coverage_tag = "---"
cov_job_url = ''
jobs = JSON.parse(Curl.get("#{gitlab_url}/api/v4/projects/#{project['id']}/jobs?scope=success&private_token=#{gitlab_token}&per_page=30").body_str)
code_cov_job = jobs.find { |gitlab_job| !gitlab_job['coverage'].nil? }
if not code_cov_job then
#if no job has 'coverage' feature set up in Gitlab try to parse
#'coverage' from jobs trace manually
jobs.each do |job|
trace_report = Curl.get("#{gitlab_url}/api/v4/projects/#{project['id']}/jobs/#{job['id']}/trace?private_token=#{gitlab_token}").body_str
code_cov_percentage = parseCoverageReport(trace_report)
if code_cov_percentage then
code_cov_job = job
code_cov_job['coverage'] = code_cov_percentage
break
end
end
end
if code_cov_job then
#found code coverage data => process them
code_coverage = code_cov_job['coverage'].to_i
cov_job_url = code_cov_job['web_url'].to_s
#update code covergate SprintProgress widgets at the same job
widget_title = "code_coverage_progress_#{project['id']}"
send_event(widget_title, {
title: "Code Coverage - #{git_project['name']}",
sprintboard_url: cov_job_url,
min: 0,
max: 100,
value: code_coverage,
moreinfo: ''
})
cov_color = case
when code_coverage <= cov_red_threshold then 'red'
when code_coverage <= cov_orange_threshold then 'orange'
else
'green'
end
code_coverage = "#{code_coverage}%"
code_coverage_tag = "<a href='#{cov_job_url}' target='_blank'>#{code_coverage.to_s}</a>"
end
repo_name_a_tag = "<a href='#{repo_url}' target='_blank'>#{repo_name}</a>"
open_mrs_size = "<a href='#{repo_url}/merge_requests' target='_blank'>#{opened_mrs.size}</a>"
table[:rows].push({
cols: [
{ value: repo_name_a_tag, style: "color: #{font_color}; background-color: #{color}" },
{ value: open_mrs_size, style: "color: #{font_color}; background-color: #{color}" },
{ value: code_coverage_tag, style: "color: #{cov_color == 'orange' ? 'black' : 'white'}; background-color: #{cov_color}" }
]
})
end
end
send_event('open_merge_requests_table', table)
end
rescue Errno::ENOENT
puts "No config file found for gitlab - not starting the Gitlab job"
end
In the above ruby example please have a look at the following code snippet
merge_reqs = JSON.parse(Curl.get("#{gitlab_url}/api/v4/projects/#{project['id']}/merge_requests?state=opened&private_token=#{gitlab_token}&per_page=200").body_str)
git_project = JSON.parse(Curl.get("#{gitlab_url}/api/v4/projects/#{project['id']}?private_token=#{gitlab_token}").body_str)
opened_mrs = merge_reqs.select { |merge_reqs| %w[opened].include? merge_reqs['state'] }
repo_name = git_project['name']
repo_url = git_project['web_url']
In here what i am trying to do is connect to our gitlab instance using a private_token and then for a specific project id (which you can get it form the UI of gitlab) check for the open merge request. I also get the git_project from which i get the name and web_url (which was my use case).
For your use case you will have to get the project_id(for gitlab UI) and then use some appropriate method to get the commits.gitlab docs

Avoid building identical pages with Middleman proxy

I am creating a static website with Middleman, referencing products parsed from a spreadsheet.
My table has these columns:
_________________________________
| Product Name | Price | Category |
| Pet Food | $12 | Pets |
| iPhone | $500 | Phone |
| Pet toy | $25 | Pets |
|______________|_______|__________|
I created pages that show all products in the Pets and Phone categories using a template called product_category.html. It creates a page for each unique category, eg. pets.html and phone.html.
The problem is that given the way I proceed, Middleman builds one category page for each product in the category, and then skips it as it is identical:
remote: create build/pets.html
remote: identical build/pets.html
remote: create build/iphone.html
Here is my sample for config.rb:
rows_by_categories = app.data.spreadsheet.sheet1.group_by { |row| row.category }
#Category Landings
app.data.spreadsheet.sheet1.each do |f|
proxy "/#{f.category.to_s.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')}.html", "/product_category.html", locals: {
f: {
categorytitle: f.category,
name: f.name,
all_in_category: rows_by_categories[f.category],
price: f.selling_price,
},
categories: rows_by_categories.keys,
}, ignore: true
end
I understand the loop iterates on each line of my spreadsheet and recreates a page for the corresponding category. Yet the few tries I gave, eg. modifying app.data.spreadsheet.sheet1.each do |f| into rows_by_categories.each do |f| are unsuccessful. Any clue?
As mentioned I have no experience with middleman but I am going to try and help anyway.
It appears that your main issue is that you are looping the individual items rather than the groups. Please try the below instead.
rows_by_categories = app.data.spreadsheet.sheet1.group_by { |row| row.category }
#Category Landings
rows_by_categories.each do |category, rows|
path_name = "/#{category.to_s.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')}.html"
row_data = rows.map do |row|
{
categorytitle: row.category,
name: row.name,
price: row.selling_price,
}
end
proxy path_name, "/product_category.html", locals: {
products: row_data,
categories: rows_by_categories.keys
}, ignore: true
end
Here we loop through the categories and products will now be an Array of all the products in that category rather than a single product. This will, in my limited knowledge, create a single page for each category and give you a collection products that you can loop through

Ruby Dashing: Issues with Jobs (on a CentOS Server)

I'm having a weird event occur, where my dashing dashboard's list widget is showing erroneous data. Here's the screenshot from my live Dashing widget
Erroneous Widget
Expected Output
What follows is the code for the widget:
Code in .erb
<li data-row="1" data-col="1" data-sizex="2" data-sizey="6">
<div data-id="facebook_insights" data-view="List" data-unordered="true" data-title="Facebook Insights: Weekly Post Views" data-moreinfo="Updated every 10 seconds"</div>
</li>
Code in job .rb
require 'mysql2'
social_count = Hash.new({ value: 0 })
time = Time.new()
date_time1 = Time.new(time.year, time.month, time.day-1)
...
SCHEDULER.every '10s' do
begin
db = Mysql.new(<HOST>,<USER>,<PASS>,<DBNAME>)
mysql1 = "SELECT <VAR> FROM <TABLE> WHERE <VAR> = '#{date_time1}' ORDER BY <VAR> DESC LIMIT 1"
...
result1 = db.query(mysql1)
...
rescue
ensure
db.close
end
result1.each do |row|
strrow1 = row[0]
$value1 = strrow1.to_i
end
...
social_count[0] = {label: "1:", value: $value1}
...
send_event('facebook_insights', { items: social_count.values })
end
What is really baffling, is that this code works for a similar widget using different data in the SQL query. Can anyone help me understand why?
I checked and re-checked the data and in my other, working code, I had my $value variables defined as $valueX with X being the number. I thought to myself "Maybe the variable names are getting confused due to them having the same name", so I changed my code to
Working Code
result1.each do |row|
strrow1 = row[0]
$variable1 = strrow1.to_i
end
...
social_count[0] = {label: "1:", value: $variable1}
Et Voila! Eureka! It worked. Not sure why it still got confused with the names, but from now on, my names will be unique!

How to I reference an array member in Ruby?

Given this array in Ruby:
myarray = [name: "John", age: 35]
How do I refer to the age?
I tried myarray[:age] but got an error can't convert Symbol into Integer
Update:
I was trying to simplify my question by extracting what I thought my problem is. I may not understand completely.
I'm experimenting with Dashing and trying to send a number to a meter widget. I've created a variable, 'response_raw' and am trying to send it in the third send event. Here's my code:
SCHEDULER.every '1m', :first_in => 0 do
# Get checks
url = "https://#{CGI::escape user}:#{CGI::escape password}#api.pingdom.com/api/2.0/checks"
`enter code here`response = RestClient.get(url, {"App-Key" => api_key})
response = JSON.parse(response.body, :symbolize_names => true)
if response[:checks]
checks = response[:checks].map { |check|
if check[:status] == 'up'
state = 'up'
last_response_time = "#{check[:lastresponsetime]}ms"
response_raw = check[:lastresponsetime]
else
state = 'down'
last_response_time = "DOWN"
response_raw = 0
end
{ name: check[:name], state: state, lastRepsonseTime: last_response_time, pt: response_raw }
}
else
checks = [name: "pingdom", state: "down", lastRepsonseTime: "-", pt: 0]
end
checks.sort_by { |check| check['name'] }
send_event('pingdom', { checks: checks })
send_event('pingdom-meter', { value: checks[:pt] })
end
In CoffeeScript [name: "John", age: 35] is an array containing single object with two properties (name and age).
Here is how it'll look in plain JavaScript:
myarray = [
{
name: "John",
age: 35
}
];
So, answering your question, to access an age you should take the first element of an array and then reference an age property:
myarray[0].age
or
myarray[0]['age']
But, judging from your question, your're probably using wrong data structure. Why don't you want to use a plain object instead of an array?
person = name: "John", age: 35
console.log "#{person.name}'s age is #{person.age}"
Update
It looks like your question is actually about Ruby and not about CoffeeScript. Though, my answer will remain the same.
To access an age you should take the first element of an array and then reference an age property:
myarray[0][:age]
Since myarray is an array, Ruby expects an integer index, but you're giving it symbol :age instead.
I finally figured it out with Leonid's help. Thank you.
I changed:
send_event('pingdom-meter', { value: checks[:pt] })
to
send_event('pingdom-meter', { value: checks[0][:pt] })

Simple fields for performance on table with 230 rows

We are trying to embed two simple form fields as columns in a table, we noticed that it takes about 4.5 seconds for simple fields to generate those tags. The table has 230 rows.
Performance with the simple_fields_for block commented out is .5 seconds, with simple fields for : 5 seconds
= simple_form_for :account,url: create_transactions_path, method: :put do |f|
%table.table.table-striped
......
........
........
%tbody
- loans_view = loans_view(#loans)
- loans_view.each do |lv|
- loan = lv[:loan]
- account = loan.account
.......
.......
%td
= lv[:amount_due]
= f.simple_fields_for :loan, index: loan.id do |al_f|
= al_f.simple_fields_for :account_transaction, index: account.id do |act_f|
%td
= act_f.input :amount, label: false, input_html:{value: account.top_up_amount}
%td
= act_f.input :include_for_update, as: :boolean, label: false, input_html: {checked: true}
We had enabled logging and made sure no db call goes out or any time consuming API is being called in the simple fields for block.

Resources