Not able to render partial with Gmaps4Rails - ruby-on-rails

I have a map which has got marker based on state of US. Each state has n number of city.
I have got a state model, controller and city model, controller.
When I click on the marker of the state, I want the list of cities to be displayed in the info window.
All this information is appearing on the homepage.
This is what I have done so far :-
home_controller.rb
def index
#states = State.all.to_gmaps4rails do |state,marker|
marker.infowindow render_to_string(:partial => "/states/gmaps4rails_infowindow", :locals => {:object => state})
marker.json({:id => state.id})
end
end
home/index.html.haml
=gmaps({"map_options" =>{ "auto_zoom" => false, "zoom" => 3}, "markers" => { "data" => #states } })
state_controller.rb
def gmaps4rails_infowindow
#state = Gmaps.map.markers
end
states/_gmaps4rails_infowindow.html.haml
=#state.cities.each do |city|
=city.name
Needless to say that it is not working. Can someone please help me out?

Well, your home_controller.rb is fine. you write here you want to use a partial with a local variable named object.
In the partial itself, you write:
=#state.cities.each do |city|
=city.name
The instance variable isn't defined there, you defined a local variable just above.
Replace with:
=object.cities.each do |city|
=city.name
From there it should work.
Notice:
def gmaps4rails_infowindow
#state = Gmaps.map.markers
end
is:
useless: you define the infowindow in the controller
wrong: Gmaps.map.markers only lives as js variable

Related

Trying to combine Users into the same marker using gmaps4rails

I can't figure out how to combine users into the same markers in gmaps4rails. I feel like I'm somewhat close, but can't exactly figure out what I'm doing wrong between using the gmaps4rails helper, converting to JSON, and rendering by partial.
def map
distinct_locations = User.where("location IS NOT NULL").select("DISTINCT(LOCATION)").map(&:location)
#markers = []
distinct_locations.each do |city|
temp_marker = User.where(:location => city).first.to_gmaps4rails
city_users = User.where(:location => city)
render_to_string(:partial => "/users/map_marker_info", :locals => { :users => city_users})
#markers << temp_marker
end
#markers
end
As you can see, in my controller, I first get an array of distinct_locations, which is just an array of city names (like "New York, New York").
Then I create the #markers to hold the JSON I'll eventually return.
For each unique city that I found, I'm TRYING to first create a marker using the to_gmaps4rails helper using the first User I find in that city. Then I'm trying to find all the other users in the city (via city_users = User.where(:location => city).
I'm then trying to render my partial using this collection of Users in the same city with something like this for now (but eventually will pull different attributes from Users):
#_map_marker_info.html.haml
.map_info_window
%h4
=users.first.location
%p
=users.count
Finally, I add the marker to #markers after each city is processed.
Eventually, I return #markers as a JSON that then becomes a beautiful map thanks to the awesome gmaps4rails gem.
I'm sure I'm doing a lot of things wrong (and probably many things inefficiently)...but can someone help me just to get it working?
Well, just one of those moments when things crystallize after you post a question. Anyways, here's what I have and it works. (Though still open to people giving more efficient answers). This "custom marker" is very very similar to the official documentation:
https://github.com/apneadiving/Google-Maps-for-Rails/wiki/Controller
def map
#markers = User.select("DISTINCT ON (location) *").where("location IS NOT NULL").all.to_gmaps4rails do |user, marker|
city_users = User.where(:location => user.location)
marker.infowindow render_to_string(:partial => "/users/map_marker_info", :locals => { :users => city_users })
end
end
Basically, select Users based on distinct locations (you really only need the latitude and longitude columns for the to_gmaps4rails helper to work. Also I removed the nil values for people who don't have locations.
Then for each "location", essentially, create the marker, but for the locals, pass in all the Users with the same location. That's what city_users is for -- all the users in the same city.
And so now I can do something like this in my partial:
.map_info_window
%h4
=users.count
in
=users.first.location
-users.each do |user|
=link_to user.full_name, user

global variable in application controller?

I grap the first country with
#country = Country.find(1)
Then i my head navigation i make this loop to get the right tags:
%ul.thumbnails
- #country.tags.find_each(:conditions => "active_house = true") do |a|
%li.span2
.thumbnail
- a.attachments.limit(1).each do |b|
= image_tag(b.file.url)
.caption
%p
#{link_to a.url, tag_country_region_houses_path(#country, a.name), :class => 'btn-nav-drop'}
This works fine. But the navigation is global so i created a method in application_controller like this:
helper_method :tags
def tags
#country = Country.find(1)
#tags = #country.tags.find_each(:conditions => "active_house = true")
end
And in the navigation view:
%ul.thumbnails
- tags do |a|
%li.span2
.thumbnail
- a.attachments.limit(1).each do |b|
= image_tag(b.file.url)
.caption
%p
#{link_to a.url, tag_country_houses_path(#country, a.name), :class => 'btn-nav-drop '}
But i get a error message "no block given (yield)"
Thanks..remco
Well, this is nothing about global variable which should be avoided whenever possible.
Your problem is in this line
tag_country_houses_path(#country, a.name)
There is NO #country exists in View.
You may wonder why. The reason is helper can't pass instance variables to View, different from controller.
What your helper all did is to return an array object #tags. The value of this object is available in view, but not instance variable #tags, neither #country.
The fix? Use something to replace #country. If the association is country has_many tags, you can do it like this:
tag_country_houses_path(a.country, a.name)
If not, you can set a method in tag model to get the country.
And you can even use some includes to make query more efficient but that is another story.
Also, your helper can be simplified without assigning any variables.
def tags
Country.find(1).find_each(:conditions => "active_house = true")
end
find_each accepts a block that will be yielded. Because you write find_each in helper without the block, so it will throw an error. You have two solutions.
Solution1: You can just use find to return an array.
def tags
Country.find(1).tags.find(:all, :conditions => "active_house = true")
end
in your view:
- tags.each do |t|
.........
Solution2: you can pass the block to your helper.
def tags
Country.find(1).tags.find_each(:conditions => "active_house = true") do |t|
yield t
end
end
in your view.
- tags do |t|
.........
If you have not many many records, just use solution1.

How do I use a controller method in the main layout?

I have built a 'NewsItem' controller that contains a method called 'top'. This is called by a javascript request to update a DIV on the page every 10 seconds. This is all working well.
def top(number = false)
# set the default value to use for the number
default_number = 10;
# perform checks on the variable
if number == false
if params.include?(:number)
number = params[:number]
else
number = default_number
end
end
# Run query to get the required news items
items = NewsItem.all( :order => ("created_at DESC"),
:include => [:profile],
:limit => number)
# iterate around the items that have been returned
#top_news = ""
items.each do |item|
#top_news += render_to_string :partial => "partials/news_item", :locals => {:item => item}
end
respond_to do |format|
format.html { render :partial => "partials/news_top"}
end
end
This is called with '/news/top' or '/news/top/20' to change the number of items that are returned.
The problem is that when the page is first loaded the 'news' DIV is empty for 10 seconds, until the JavaScript runs to update the DIV. So I want to ensure that the DIV is already populated by calling this function.
Now as I want the 'news' DIV to be available in all pages it is defined in the 'layouts/application.html.erb' template. So I need to call the 'top' method in the 'NewsItem' controller so that it can be rendered into the initial HTML. This is where I am struggling as I cannot work out how to use the 'helper_method' to make this available at this stage.
I have a feeling that I am missing something here and not understanding the whole process.
Thanks very much for any assistance.
Regards, Russell
Try separating out the logic. Maybe you make a method called top_news that returns the value you use in top_news. And since you're passing back a partial, use it to build the string. Partials are meant to be used to iterate over a list.
def index
#top_news = top_news
end
def top
#top_news = top_news
respond_to do |format|
format.html { render :partial => "partials/news_top"}
end
end
private
def top_news(number = false)
# set the default value to use for the number
default_number = 10;
# perform checks on the variable
if number == false
if params.include?(:number)
number = params[:number]
else
number = default_number
end
end
# Run query to get the required news items
items = NewsItem.all( :order => ("created_at DESC"),
:include => [:profile],
:limit => number)
# iterate around the items that have been returned
return render_to_string :partial => "partials/news_item", :collection => items, :as => :item
end
The other solution you can follow is to not render any partials in the controller at all except for your one javascript method and instead make a method in your model to do exactly what you're doing here.
class NewsItem
def top_news(number=20) # pass in number with default 20
NewsItem.where( :order => ("created_at DESC"),
:include => [:profile],
:limit => number)
end
end
Then just call it from your controllers to get that so you can use it in your views and iterate over it using partials in your views.

Rails accessing variable in email template

I'm still on the rather steep side of the Rails learning curve, so please pardon the rather simplistic nature of this question, but Google's just not proving very helpful.
So, my issue is this. I have a controller that is calling a mailer. (Code snippet below)
The problem I can't seem to get passed is that no matter how I try to access the values in the rhtml page, I either get errors or nothing at all.
This is the controller snippet (#person is working just fine. #item is what's not working)
if params[:id] == 'username'
item_value = #user[:login]
elsif params[:id] == 'password'
item_value = #user[:new_password]
end
#item = { 'name' => params[:id], 'val' => item_value }
ApplicantMailer.deliver_forgot(#person.email, #person, #item)
This is the mailer method snippet:
def forgot(recipient, person, item, sent_at = Time.now)
#subject = 'Site Password Retrieval'
#body['person'] = person
#body['item'] = item
#recipients = 'rdavis#localhost'
#from = CONTACT_EMAIL
#sent_on = sent_at
#headers = {}
logger.debug #body.to_yaml
end
This is the rhtml snippet:
Dear <%= #person.first_name %>,
You are receiving this email because you or someone else has used the lost <%= #item[:name] %> page from the login page.
Your <%= #item[:name] %> for your account is: <%= #item[:val] %>
So, like I said, when I try to access the values for the #item, if I use #item.name it throws a missing method error and if I use the version listed above, it doesn't show anything.
I know I'm working with a hash & thought that trying to access the keys like I showed here was the right way. Obviously, I'm missing something here.
Can someone point me in the right direction, please? Thanks!
You are using strings when creating your hash and symbols when accessing it.
You want the following:
#item = { :name => params[:id], :val => item_value }
Which is distinct from:
#item = { 'name' => params[:id], 'val' => item_value }
You can try this in irb with the following.
hash = {"a" => "val1", :a => "val2", "b" => "val3"}
hash["a"] => "val1"
hash[:a] => "val2"
hash["b"] => "val3"
hash[:b] => nil

Simplenavigation - How to create dynamic menu items?

I am trying to create a dynamic menu with simple navigation.
The problem is that the menu only works on the show action that should show dynamic menu items. All other pages gives the error:
undefined method `model_name' for #<Class:0x9236118>
I have read this, but have not found any solution:
https://github.com/andi/simple-navigation/wiki/Dynamic-Navigation-Items
My navigation.rb:
sub_nav.item :virk, 'Virksomheder', virk_path, :link => {:style => 'font-weight:bolder;', :class => 'submini'} do |virknavn|
virknavn.item :virksom, #virksomhed.try(:name), url_for(#virksomhed), :highlights_on => /virksomheder\/[0-9]+/
end
I only want the virknavn menu items to be highlighted on:
/virksomheder/:some virksomhed name
My virksomhed controller:
def index
#virksomheds = Virksomhed.all
render :layout => 'page'
end
# GET /webhosts/1
# GET /webhosts/1.xml
def show
#virksomhed = Virksomhed.find(params[:id])
render :layout => 'page'
end
I did manage to figure out that I just could set a if statement in the navigation.rb:
if params[:id].blank?
params[:id] = Virksomhed.first.id
end
#virksomhed = Virksomhed.find(params[:id])
if #virksomhed.blank?
#virksomhed = Virksomhed.first
end
And it did the magick.

Resources