I am attempting to follow this tutorial and I am getting stuck: Adding a 5 star ratings feature to a Rails 4 model.
Im a begginer with javascript and ajax so I spent a few hours learning how ajax works with javascript. I believe the problem has to do with where the average_rating method is (rails problem?).
def average_rating
ratings.sum(:score) / ratings.size
end
Currently I have followed the tutorial exactly how it says, while replacing comment with review. In the tutorial it says to define the average_rating in the comment model (mine is in the review model), and I am not sure why I would do that.
Also I have added this (not sure if It belongs in the current controller or if it belongs in rating controller):
#this is the controller used for the view which displays the stars
def page
#rating = Rating.where(review_id: #review.id, user_id: #current_user.id).first
unless #rating
#rating = Rating.create(review_id: #review.id, user_id: #current_user.id, score: 0)
end
end
When I try to load the page here is the error I get: ZeroDivisionError below it says divided by 0 and it highlights this line score: <%= #review.average_rating %>,
UPDATE When I delete this script from the view which has the average_rating, the stars show for my_rating. So something is messing up with the average part:
<script> #did not delete this line
$('#star').raty({
readOnly: true,
score: <%= #review.average_rating %>,
path: '/assets'
});
Deleted part^^^
Basically, i would love to get more info, but here are some pointers that might help:
make sure the relation is working: make sure you have has_many :ratings for the user/review and 'belongs_to :user/:review' for the ratings. other direction- are you getting the ratings in a controller method? if so, consider changing it to #ratings.
use first_or_XXXX - this is a great rails option to save conditional instantiation. there is first_or_create that would do exactly what you did:
Rating.where(review_id: #review.id, user_id: #current_user.id).first_or_create do |rating|
rating.score = 0
end
finally, ratings.size, will not update after create, which might explain the zero devision. read more in this question's selected answer and comments. Therefore, it's recommended to use count (will check on the db, so only saved ratings will be counted) or length (i.e. user/review.ratings.length which will count also built (not saved) objects.
hope that helps.
Related
Issue: I want to find a way to paginate over Stripe API results past a certain number. The issue is, as time goes on and more API documentation appears, a page will be loaded with way too much data. Preferably I would like to have a months worth of data per page.
Question: How can I limit to results on the views side and create pagination for it.
For example, I have this in my controller:
#payouts = Stripe::Payout.list(
{
limit: 100,
expand: ['data.destination']
},
{ stripe_account: current_user.stripe_token }
)
Views:
#table html stuffs
...
<% #payouts.each do |payout| %>
<tr>
<td><%= number_to_currency(as_table_row_payout(payout["amount"] / 100.00 )) %></td>
<td><%= as_table_row_payout(Time.at(payout["arrival_date"]).strftime('%m/%d/%Y')) %></td>
</tr>
<% end %>
...
I have the will_paginate gem but that didn't seem to work. So I figured there may be a way with jquery / JS to solve this. Does anyone have a solution to limit the amount of API JSON data that is requested on the view page?
Somewhat of an update and a bit off topic... (sorry if this strays from the post itself and starts a new conversation)
I have found a gem for will_paginate to paginate through API requests
I have found the api-pagination gem here: https://github.com/davidcelis/api-pagination
Although, when i installed the gem and followed the directions, nothing seemed to happen - I manually created an api_pagination.rb config file and did what it seems like the docs say to do as well... Anyone use this before?
The Stripe API uses cursors for pagination rather than just specifying a page and a page size (which is what will_paginate and kaminari do).
If you look at the api docs for listing payouts the arguments you'll need to use are ending_before and starting_after.
If you retrieve 10 payouts with ids [1, 2, ..., 10] and you want the next "page" of results you'll need to make the request again with starting_after=10. I.e. from the payout with id=10 get me the next 10 payouts.
I'm not aware of any gem support for this (although that definitely doesn't mean that there isn't any!) and I've tended to roll my own by generating "Next" and "Previous" links to set starting_after the id of the last payout in my current page or ending_before the id of the first payout in my current page. E.g.
<%= link_to 'Previous', list_payouts_url(first_payout_id: #payouts.first.id) %>
<%= link_to 'Next', list_payouts_url(last_payout_id: #payouts.last.id) %>
and then setting the ending_before or starting_after to params[:first_payout_id] and params[:last_payout_id].
I'm new to Rails and have been confused by this problem for a while.
I'm looking to create a translation app. When a user clicks a link containing a word, I want the rails controller to get the translation through an external API call, save the word and translation, and then display the translation, all without refreshing the page.
The particular issue I have is getting some string (which will be the translation) to be passed from the controller to a js file, where it can then update the HTML to display the translation.
In the controller (texts_controller.rb):
def createword
#word = Word.new(word_params)
#word.save
#translation = "Some string"
respond_to do |format|
format.js
end
end
In the javascript (createword.js.erb)
console.log("done");
$(".message").html(<%= #translation %>);
When I delete the second line containing #translation, the javascript works just fine and logs "done" to the console. However, when I do include that line, none of it works.
How can I get this variable to the js, or if that is not possible, what is the best way to get it to the view?
I didn't try this, but adding some quotes will probably do what you want:
$(".message").text("<%= #translation %>");
Good day,
I would like to create a real time Newsticker/Marquee scroller for my rails app, Similar to what you would find on Sky Sports News TV channel.
I Need to be able to query the database table (which i can) and display the output in the ticker/marquee one table row at a time looping it over. Also i would like to either try display this query in real-time or very frequently and updating the output on the clients end without the page refreshing. (Similar to a chat room or twitter feed.)
Here is some basic code
Simple Query Which shows the subject and paper if the start time is < Current time and Stop time is > Current time
Model
Timetable.where("start < ? AND stop > ?", Time.now, Time.now).order('id ASC').pluck(:subject, :paper)
Html
<table><tbody><% #timetables.each do |timetable| %><tr><td><%= timetable[0] %></td><td>%= timetable[1] %></td></tr><% end %></tbody></table>
If anyone is able to hepl or point me in the right direction, Ill really appreciate it. Thanks
At the moment i could probably use a partial to display the query and update the partial, not sure if there is a better method using any gems that will open up an event listener or socket?
Interesting problem you've got here. Got me excited and I tried some things out myself!
If you want to have content refreshed on the client side (no page reload), you need to use javascript to repeatedly query the server. In Rails you'd probably go with a partial that's being rendered from both the page view and the API-view that's used in an AJAX call.
Let's assume you have a model called Item of which you want to show the latest 3 on your page and then fetch the latest every 5 seconds to update the page. You might want to create something that looks like the following:
controllers/content_controller.rb
class ContentController < ApplicationController
def show
end
end
views/content/show.haml
%h1 Page with updated items
.updateme
= render "items/latest"
controllers/items_controller.rb
class ItemsController < ApplicationController
layout false
def index
end
end
views/items/index.haml
= render "items/latest"
views/items/_latest.haml
- Item.last(3).each do |item|
= item.subject
Last but not least you will need to add javascript that calls the index for items
javascripts/update.js
function updateItems() {
$.ajax({
url: "/items",
}).done(function(data) {
$("div.updateme").html(data)
});
}
$( document ).ready(function() {
window.setInterval(function(){
updateItems();
}, 5000);
});
Hopefully this gets you started in the right direction :)
I am trying to establish a dynamic form on a contact's page. I would like on this page to be a link that says "add an email address" and then when I click on it, a form appears to enter email address.
So I used a link_to with remote true :
= link_to "Add an email", add_email_path, id:'link-remote-link', remote: true
In my controller i specified :
def add_email
render layout: false
end
But when I receive my response with listening on ajax:sucess, layout is still their in the variable. But I just want the form add_email.html.haml
In order to try to know if the code in my controller was executed, I tryed to put a creation of an object in it. Fact is that it was never created.
Never the less, rails console writes "Processing by ContactsController#add_email as JS
"
So...why is it not executed ?
Thank you :)
Layout
We set the layout in the application_controller to manage the ajax responses:
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
layout Proc.new { |controller| !controller.request.xhr? }
end
You may wish to try this - to see if it's the call in your controller which is rendering the layout.
Personally, I think your layout: false call is being overridden with some other element / part of your controller. I'd recommend checking to make sure this is the case
--
Controller
As you've stated, the case may be that your controller isn't being called, or processed correctly.
This could be caused by a number of issues, most notably from having incorrect routes, or some other dependency preventing the method from firing properly.
To clarify, I would make sure I have the following set up:
#config/routes.rb
resources :contacts do
get :add_email, on: :collection
end
#app/controllers/contacts_controller.rb
class ContactsController < ApplicationController
def add_email
...
end
end
Hello people
I'm trying to figured this out, but I still can't do it.
I have a rails 3 app, I'm working with invoices and payments. In the form for payments I have a collection_select where I display all the invoices number (extracted from a postgres database), and what I'm trying to do is when i select an invoice autopopulate others text_fields (provider, address, etc.) without reloading the page, in the same form.
I know I should use ajax, js, jquery, but I'm a beginner in these languages, so i don't know how or where to start
hope you can help me... thanks
What you are going to want to do is route an ajax call to a controller, which will respond with json containing the information. you will then use jquery to populate the different fields.
In your routes:
get "invoice/:id/get_json", :controller=>"invoice", :action=>"get_json"
In your invoice_controller:
def get_json
invoice = Invoice.find(params[:invoice_id])
render :text => invoice.to_json
end
In your invoice model (if the default to_json method is not sufficent):
def to_json
json = "{"
json += "id:'#{self.id}'"
json += ",date_created:'#{self.date}'"
... //add other data you want to have here later
json += "}"
end
In your javascript file,
$("#invoice_selecter").change(function(){ //calls this function when the selected value changes
$.get("/invoice/"+$(this).val()+"/get_json",function(data, status, xhr){ //does ajax call to the invoice route we set up above
data = eval(data); //turn the response text into a javascript object
$("#field_1").val(data.date_created); //sets the value of the fields to the data returned
...
});
});
You are probably going to run into a few issues, i would highly recommend downloading and installing fire bug if you are not on google chrome.. and if you are, make sure you are using the development tools. I believe you can open them up by right clicking and hitting inspect element. Through this, you should be able to monitor the ajax request, and whether or not it succeeded and things.