Activity
Posted in Implementing Highcharts in RoR
Check out these resources:
https://stackoverflow.com/questions/23830970/highcharts-trying-to-update-series
Based on the SO answer, you can either redraw the chart or just change out the series. I think changing the series would be the better way, but it would be worth testing them both and seeing what your experience is based on your needs.
Posted in Implementing Highcharts in RoR
I can't speak to the integration with filterrific, however loading live data is just a matter of making an ajax call and updating the data:
https://www.highcharts.com/docs/working-with-data/live-data
function requestData() {
$.ajax({
url: 'url_to_your_controller_action',
success: function(point) {
var series = chart.series[0],
shift = series.data.length > 20; // shift if the series is
// longer than 20
// add the point
chart.series[0].addPoint(point, true, shift);
// call it again after one second
setTimeout(requestData, 1000);
},
cache: false
});
}
In this example, they update every second, however you could remove that part and just have the ajax function trigger when a user updates the filter attributes. From here really all you need to do is update the ajax URL with whatever params you need in order to have your controller actions query return the correct set of records based on whatever filters you selected.
Posted in Implementing Highcharts in RoR
Hey John,
If you want to just get up and running, it's really just a matter of throwing a script tag in a page and load the resources... check out the first series below for some notes on how you can load your data in
From here, it just depends on what your needs are and how many charts you needs / how you need to load the data that would determine how you would really want to implement it all for your final product.
index.html.erb
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="height: 400px;"></div>
<script>
Highcharts.chart('container', {
title: {
text: 'Solar Employment Growth by Sector, 2010-2016'
},
subtitle: {
text: 'Source: thesolarfoundation.com'
},
yAxis: {
title: {
text: 'Number of Employees'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
plotOptions: {
series: {
label: {
connectorAllowed: false
},
pointStart: 2010
}
},
series: [{
name: 'Installation',
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
// here you could do <%= raw @your_data %>
// so in your controllers index action, you'd have:
// @your_data = [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
// data: <%= raw @your_data %>
// would render data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175]
}, {
name: 'Manufacturing',
data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434]
}, {
name: 'Sales & Distribution',
data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387]
}, {
name: 'Project Development',
data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227]
}, {
name: 'Other',
data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111]
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
</script>
Hey Kelvin,
I've never done it, but the keyword you're looking for is "web scraping"
Check out: https://www.google.com/search?q=web+scraping
You could do something like this:
class User < ApplicationRecord
has_one :profile
after_create :init_profile
def init_profile
self.build_profile.save(validate: false)
end
end
This lets you create the records but if you have other functions that check if profile.valid?
then it would return false, and this may not be the desired result. See: https://www.dan-manges.com/blog/action-dependent-validations-and-why-on-update-is-bad Notice they're talking about the on: :update
, which isn't what we're doing here, however the side effect is the same.
Posted in Rails Braintree couldn't update
What are you using to authenticate your users in this app if you're not using Devise? The error shown is clearly that it's expecting a password, and your validations on your user model also state you need password info when saving/updating a user.
I think you need to restructure your models some... your user
model really needs to be focused on just the users information needed to login. Everything else needs to be in their own model that is associated with the user
model.
So instead of putting a users company in the user model, create a company
model and then depending on your needs, either do a has_one
or has_many
association between the user
and company
.
You also need a subscription
model that will take care of keeping track of a users subscription. You may also consider a payment_source
model that will keep track of the braintree_id
.
Ideally, for what you're wanting to accomplish, you shouldn't need to save anything to the user
model when you're creating a transaction.
Posted in Rails Braintree couldn't update
Hi Lee,
You probably have a validation on the user model or transaction model that's not being satisfied. Can you post any validations you have on your user and transaction model?
You can also use the byebug gem and place byebug
right before the transaction that fails. Then try another subscription and this time when byebug is triggered, try creating the transaction there manually and see what error is raised.
Hey Morgan,
Just iterate through the images and save each one like you would any has_many
def get_listings
resp = client.get("/v1/some/api/posts")
resp.body.each do |post|
user = @user.posts.new(
headline: post["headline"],
body: post["body"]
)
listing["media"].each do |media|
user.images.build(url: media["url"])
end
user.save
end
end
I haven't tested this, so you may have to play around with it some (you may need to actually save the user first, then iterate through and build the associations, I can't recall off the top of my head) but you should get the idea.
Hey Dim,
Just check to see if the time field is blank
def example
if boolean_field == true && datetime_field.blank?
datetime_field = Time.now
end
end
I can get the data to pass but not actually take into account the day, hour etc i.e. 20 impressions on Thurday and 40 impressions on Friday
If you work out what I gave you, it will do just what you're wanting... to where it will give you a range of impressions for your raffle based on a given time range.
the example provided is if the raffles were a seperate entity to the dashboard and not actually attached to anything
That doesn't matter at all for what you're trying to do.
It's not a diffult thing I'm trying to do here
Just because it's easy to explain doesn't necessariliy mean it's easy to do in code. I've done these exact kind of gigs plenty of times, so trust me, what I provided you will work. However, I can't do the project for you. I got you 3/4 of the way and gave you guidance to complete the other 1/4.
Best of luck.
Clone this - https://github.com/nanosplit/deleteme
bundle install
rake db:create
rake db:migrate
rake db:seed
rails s
http://lvh.me:3000
Take a look at the concern and controller:
https://github.com/nanosplit/deleteme/blob/master/app/models/concerns/raffle_impressions.rb
https://github.com/nanosplit/deleteme/blob/master/app/controllers/raffles_controller.rb
This isn't a copy/paste, you're going to have to take a look at what's actually happening, try to understand what is going on at each step, and then work out how to replicate the result in code. Google will be your best friend here. Most of the structure is there for you, you just have to figure out how to get your time ranges sorted out for the given time period you want to record, and then feed that into the raffle_impressions_count
method.
Did you put raffle_impressions.rb
in app/models/concerns/raffle_impressions.rb
and restart your console / rails server?
Try this:
raffles.rb
class Dashboard::Raffle < ApplicationRecord
is_impressionable :counter_cache => true, :column_name => :impressions_count, :unique => :all
has_many :users
include RaffleImpressions
end
app/models/concerns/raffle_impressions.rb
module RaffleImpressions
extend ActiveSupport::Concern
def raffle_impressions_count
time_ranges = [['2017-12-08 08:00:00 -0600', '2017-12-08 09:00:00 -0600'], ['2017-12-08 09:00:00 -0600', '2017-12-08 10:00:00 -0600']]
impressions = []
time_ranges.each do |time|
impressions << [[ time[0], time[1] ], self.impressionist_count(start_date: time[0], end_date: time[1]) ]
end
return { :name => self.name, :data => impressions }
end
end
This is using concerns, so I had to add extend ActiveSupport::Concern
to the raffle_impressions.rb
. Testing the execution real quick I noticed I had the return hash wrong, I forgot to make name and data symbols... so be sure to update that in yours.
Also, to help you with debugging, be sure to watch Chris' video on it: https://gorails.com/episodes/debugging-with-better-errors
That's not how you setup a method to receive params
I would suggest some reading to get a better understanding
- https://launchschool.com/books/ruby/read/methods
- https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls
- http://ruby.bastardsbook.com/chapters/methods
And really my example was only to illustrate the general concept you're after. So with your setup, you'd be looking for something more like:
raffle.rb
class Dashboard::Raffle < ApplicationRecord
is_impressionable :counter_cache => true, :column_name => :impressions_count, :unique => :all
has_many :users
include 'RaffleImpressions'
end
raffle_impressions.rb
module RaffleImpressions
def raffle_impressions_count
time_ranges = [['2017-12-08 08:00:00 -0600', '2017-12-08 09:00:00 -0600'], ['2017-12-08 09:00:00 -0600', '2017-12-08 10:00:00 -0600']]
impressions = []
time_ranges.each do |time|
impressions << [[ time[0], time[1] ], self.impressionist_count(start_date: time[0], end_date: time[1]) ]
end
return { name => self.title, data => impressions }
end
end
Then you should be able to call Dashboard::Raffle.first.raffle_impressions_count
to get an output for a single raffle. If you wanted multiple, you'd have to iterate over each Raffle
, calling raffle_impressions_count
on each iteration and load that into an array that you'd then pass to chartkick.
Oops, noticed a mistake - that's what I get for trying to write this out in a comment box :)
raffles = Dashboard::Raffle.all
time_ranges = [['2017-12-08 08:00:00 -0600', '2017-12-08 09:00:00 -0600'], ['2017-12-08 09:00:00 -0600', '2017-12-08 10:00:00 -0600']]
raffles_array = [] # don't need raffles_hash, instead just an array to load
raffles.each do |raffle|
impressions = []
time_ranges.each do |time|
impressions << [[ time[0], time[1] ], raffle.impressionist_count(start_date: time[0], end_date: time[1]) ]
end
raffles_array << { name => raffle.name, data => impressions }
end
return raffles_array
You may need to do some more playing but I think that's pretty close.
Yes, the last thing you see there is the return value - 0
So that's one value for one time range for one raffle. Now you need to create a function to build the hash like I showed so you end up with a range of time values along with their respective impression counts for each raffle.
So basically, what you're needing is something similar to:
edits made
raffles = Dashboard::Raffle.all
# time_ranges you need another function that you can give it a start_time and an end_time,
# and then have it spit out an array like you see below that is an array of grouped time spans.
# Example below shows two time groups that span one hour each.
time_ranges = [['2017-12-08 08:00:00 -0600', '2017-12-08 09:00:00 -0600'], ['2017-12-08 09:00:00 -0600', '2017-12-08 10:00:00 -0600']]
raffle_hash = {}
raffles.each do |raffle|
impressions = []
time_ranges.each do |time|
impressions << [[ time[0], time[1] ], raffle.impressionist_count(start_date: time[0], end_date: time[1]) ]
end
raffle_hash[raffle.name] = impressions
end
return raffle_hash
This would give you an output like this:
[{name: "Test Raffle 2", data: [[['2017-12-08 08:00:00 -0600', '2017-12-08 09:00:00 -0600'], 34], [['2017-12-08 09:00:00 -0600', '2017-12-08 10:00:00 -0600'], 12]]}]
This is just an example of the basic steps you're going to have to take to get your output.
Right, because that's just a single query for a single point in time. Go into your rails console and type in your query and look at the output
Dashboard::Raffle.first.impressionist_count(start_date: Time.now - 1.hour, end_date: Time.now)
You'll see it only gives you a single value. So you have to make a function that will iterate over a range of time to eventually build up a hash that looks like this:
[{name: "Test Raffle 2", data: [["8am-9am", 34], ["9am-10am", 12], ["10am-11am", 45], ["11am-12pm", 89]]}]
You bet! :)
Just save it before redirecting
def create
# @post = current_user.posts.build(posts_params) << How do I do this now?
@parent = parent
@post = @parent.posts.new(post_params)
@post.user_id = current_user.id
respond_to do |format|
if @post.save
format.html { redirect_to posts_path, notice: "Post successfully created!"}
else
format.html { render :new }
end
end
end