Reputation: 763
In my Rails app I have many categories that have many clients. It also supports switching languages.
The categories are shown in the navigation of the app and I want to make a custom dropdown that contains the clients of that category. It will be created when a user hovers on some of those categories.
I've created a new resource that is doing the job of fetching the clients that belong to the hovered category, but I'm having trouble making those clients linkable due to the internationalization.
This is the javascript code:
$(function () {
$(".nav_category").hover(function () {
category_dropdown = $(this).children(".category_dropdown");
clients_from_category = category_dropdown.children(".clients_from_category");
category_dropdown.toggle(0, "hidden");
$.get($(this).data("url"), function(response) {
client_name = response[0]['translations'][0]['name'];
client_picture = response[0]['pictures'][0]['image']['thumb']['url'];
html = "<a href='/clients/"+response[0]['id']+"' class='nearest_client'>";
html += "<img src='" + client_picture +"'>";
html += client_name;
html += "</a>";
clients_from_category.html(html);
});
}, function() {
$(this).children(".category_dropdown").toggle(0, "hidden");
})
});
The problem here is that I get the links displayed like this:
<a href="/clients/157" class="nearest_client">
<img src="/uploads/picture/image/361/thumb_image.jpg">Client name
</a>
Notice there is no locale set. It should be like:
<a href="en/clients/157">
Is there a way to get to the set locale? Or am I approaching this problem in a bad way? What is a better way of setting a listener on a div and creating the needed DOM elements from the returned JSON object?
Upvotes: 0
Views: 80
Reputation: 763
Maxcal was really helpful with his suggestion to use ActiveModel::Serializers, but after I made the necessary changes a lot of my other resources in the API part stopped working properly.
For a quick fix on this I used another data attribute that I passed to javascript:
html = "<a href='"+ $(this).data("language") + '/clients/' + response[0]['id']+"' class='nearest_client'>";
Upvotes: 0
Reputation: 102423
The solution is use the Rails link helpers to add the url or path to the JSON output.
If you are using JBuilder (which is installed by default):
# /app/clients/views/show.json.jbuilder
json.id @client.id
json.name @client.name
json.path client_path(@client)
json.url client_url(@client)
But I would recommend using ActiveModel::Serializers:
class ClientSerializer < ActiveModel::Serializer
attributes :id, :name, :path, :url
def url
client_url(object)
end
def path
client_path(object)
end
end
See the RailsCast for basic use instructions.
Then you would use it in your javascript like so:
$(function () {
$(".nav_category").hover(function () {
var category_dropdown = $(this).children(".category_dropdown");
var clients_from_category = category_dropdown.children(".clients_from_category");
var category_dropdown.toggle(0, "hidden");
$.get($(this).data("url"), function(response) {
var client = response[0];
var client_name = client['translations'][0]['name'];
var client_picture = client['pictures'][0]['image']['thumb']['url'];
var html;
html = "<a href='+ client.url +' class='nearest_client'>";
html += "<img src='" + client_picture +"'>";
html += client_name;
html += "</a>";
clients_from_category.html(html);
});
}, function() {
$(this).children(".category_dropdown").toggle(0, "hidden");
})
});
On a side note - you need to use the VAR keyword when declaring variables in javascript. Otherwise they are created as globals which is a really bad thing. Use JSLint or strict mode to catch misstakes like this.
Upvotes: 1