Trying to populate gmaps4rails with multiple json strings in one page - ruby

I hope I am asking this right, so please let me know if I'm way off.
The problem is trying to build a homepage that draws from multiple controllers, to display the nearest locations from multiple controllers, ie. food, businesses, ect.
Right now the individual listings pages have maps drawn from their respective
#json = Controller.all.to_gmaps4rails
How would I do something like :
#json = Controller1 Controller2 .all.to_gmaps4rails
I hope this isnt a noob question and I'm just having a bad day. Thanks guys!
edit 12.5.2011 #seanhill - this is one of the models, the other sections are very close to this format. First off, I wasn't even sure if my homepage requires it's own model, as it doesn't interact with the db at all, more pulling data from controllers that do the work. Thanks for the response Sean!
class Dining < ActiveRecord::Base
validates_uniqueness_of :name, :message => "already exists"
attr_accessible :name, :address, :cuisine, :latitude, :longitude, :about, :facebook, :twitter, :phone, :website
geocoded_by :address
after_validation :geocode, :if => :address_changed?
acts_as_gmappable :process_geocoding => false
def gmaps4rails_address
"#{self.address}"
end
def gmaps4rails_infowindow
"<h3>#{self.name}</h3><br /><h5>#{self.cuisine}</h5>"
end
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end

Try this
holder = Controller1.all
holder << Controller2.all
#json = holder.flatten.map{|h| {lng: h.longitude, lat: h.latitude, class: h.class.to_s}}.to_json
Make sure to change longitude and latitude based on your column names and use js to manipulate the markers based upon class.
As the #Sean Hill said you shouldn't be calling .all on controllers but I think you have a slight misunderstanding of how things are working. Assuming you have a Model called Dining and another called Shop, when you call Dining.all or Shop.all inside class DiningsController < ApplicationController, you are calling .all on either the Dining Model or the Shop Model not on the DiningsController.
The information you display through a controller is only limited by the methods you call in it although it is best practice ensure the main focus of the information displayed is related to the respective controller.
So what you are really trying to do is get the records from multiple models and group them together to display them in a single map.
With that said the answer should read something like this
holder = Dining.all # Takes all Dining records returned as an array and sets them to holder variable
holder << Shop.all # Pushes the Shop records array into the holder with the dining records
holder.flatten!# Next we flatten the array so we only have a single array.
# Then we use the map method to run the given code one time for each instance
# in the holder array to extract the info we need. The results for every instance
# in holder are returned in an array which we then convert to_json.
#json = holder.map{|h| {lng: h.longitude, lat: h.latitude, class: h.class.to_s}}.to_json

#json1 = something.to_gmaps4rails
#json2 = something.to_gmaps4rails
#json = (JSON.parse(#json1) + JSON.parse(#json2)).to_json

I populated the map with my initial data of festivals, and then added the rides to it with javascript with this code,
<% content_for :scripts do %>
<script type="text/javascript">
Gmaps.map.callback = function() {
$.getJSON('/rides_gmap', function(data){
Gmaps.map.addMarkers(data);
});
}
</script>
<%end%>
In the rides controller I had this
def rides_gmap
#rides = Ride.all
#json = #rides.to_gmaps4rails do |ride, marker|
marker.infowindow render_to_string(:partial => "/rides/infowindow", :locals => { :ride => ride})
marker.picture({
'picture' => view_context.image_path("orange-dot.png"),
'width' => 20,
'height' => 20
})
marker.title "#{ride.address}"
marker.json({:ride_id => ride.id, :ride_festivaltype => ride.festival.festivaltype
end
respond_with #json
end
I hope this helps.

Related

How to check if value exists in params.permit?

I can't seem to figure out how to accomplish what I am trying to do here on my create method.
What I have right now works if there are no values, the item is deleted. However, if 1 or more param values exist, it passes and is saved. Not what I needed. I need an all or nothing scenario. I want to save only if all the permitted keys have their value. params.permit(:name, :description, :copyright)
Before an entry is saved using organizations.save!, I need to make sure none of the params that are permitted are nil or empty.
I search all over and can't seem to narrow down on an answer to my exact issue.
Here is my code:
class OrganizationsController < ApplicationController
def index
query_params = params.permit(:id, :name,)
if query_params.blank?
organizations = Organization.all
else
organizations = Organization.where(query_params)
end
render json: organizations, root: "organizations"
end
def create
organizations = Organization.new(organization_params)
if organization_params.present?
organizations.delete
else
organizations.save!
render json: organizations
end
end
private
def organization_params
params.permit(:name, :description, :copyright)
end
end
You should add validations to your model.
From your question i understand that you want to save details only if you get values in all the field, if not you don't want to save, right?. If yes, then adding validations to your model will give you what you wanted.
Add the following to your organization model
validates_presence_of :name
validates_presence_of :description
validates_presence_of :copyright
by doing so, the user won't be allowed to save the details unless and until all three fields have some value in it.
There is no need to use delete as the incomplete information will not be saved.
for more and advanced info click here
To check none of the values of organization_params hash is empty, you can do something like this:
organization_params.values.all? { |x| !x.empty? }
or, this:
organization_params.all? { |k,v| !v.empty? }
You can also check if any param value is empty:
organization_params.any? { |k,v| v.empty? }
So, your create method can be re-written as:
def create
organizations = Organization.new(organization_params)
if organization_params.any? { |k,v| v.empty? }
# at least one param is empty, so delete the record
organizations.delete
else
# all the params values are present, so save the record
organizations.save!
render json: organizations
end
end

ruby on rails, search results to json array (jbuilder)

I'm new to rails and I just have a quick question...
I have a calendar gem which currently pulls event data from json as such (viewings/index.json.jbuilder)
json.array!(#viewings) do |viewing|
json.extract! viewing, :id, :room_id, :user_id, :start_time, :end_time, :notes
json.title viewing.user.name
json.start viewing.start_time
json.end viewing.end_time
json.url viewing_url(viewing, format: :html)
end
anyway, I have created a search feature on my "viewings" index page, where a user selects the room from a drop-down and it displays the corresponding viewings.
However, I need to make a JSON array from the results of the search, so it can be fed to the calendar.
I know I can achieve this by doing something like, which does work:
#viewings = Viewing.where(room_id: 1 )
but obviously I want to pass a variable in to that line of code, something like
#viewings = Viewing.where(room_id: params[:search_string] )
The search string will always be a room ID, but the above code (and any variations I can think of) don't seem to work.
OR can I make a JSON array from my search output. my search is as so...
def search
#rooms = Room.all
#viewings = Viewing.simple_search(params[:search_string])
render :action => "index"
end
Can anyone help?!
EDIT:
I'm still struggling with this one a lot. I had a look at the jquery page below but its still not doing what I hoped.
I have simplified the function in my viewings controller as so:
def rmselect
#query1 = params[:rmno]
#rooms = Room.all
#viewings=Room.find(params[:rmno]).viewings
render :action => "index"
end
And I have created an _rmselect.json.jbuilder as so:
#viewings = Viewing.where(room_id: #query1 )
json.array!(#viewings) do |viewing|
json.title viewing.user.name
json.start viewing.start_time
json.end viewing.end_time
end
I was hoping the #query1 variable would be passed into the jbuilder page which would cause it only to display viewings for the selected room. However, it seems that jbuilder cannot see any variables unless they are in def index (where it's no good).
I also can't understand why _rmselect.json.jbuilder is taking the #viewings.all from def index, rather then the #viewings=Room.find(params[:rmno]).viewings from def rmselect.
Ok, I suppose the situation is like that:
Viewing model:
class Viewing < ActiveRecord::Base
...
belongs_to :room
...
end
Room model:
class Room < ActiveRecord::Base
...
has_many :viewings
...
end
Retrive viewings from room id, you can do something like:
#viewings=Room.find(params[:search_string]).viewings
For create JSON array of result, render jbuilder view who contains something like that:
# #people = People.all
json.array! #people, :id, :name
# => [ { "id": 1, "name": "David" }, { "id": 2, "name": "Jamie" } ]
I report an example of official jbuilder docs I think you can use json.array with viewings:
json.array! #viewings, field1, field2, ...
Otherwise you can use this in your controller:
render json: #viewings
but if you've used jbuilder, I think it's better you continue that way.

Update users table when running create action of different model

Just to show you how I got to this point:
Every user has many profiles. Every profile has type recognized by single table inheritance(amateur, professional, and some other). I need to store current_profile somewhere and somehow.
Professionals Controller
class ProfessionalsController < ApplicationController
def create
#professional = Professional.new(professional_params)
#user = current_user
#professional.user_id = current_user.id
#update_current_profile = User.update(#user, {:current_profile => #professional.id})
if #professional.save
...
else
...
end
end
private
def professional_params
params.require(:professional).permit(:id, :username, :user_id)
end
end
This is meant to update current_profile of user to the newly created professional profile and do some staff then.
When the profile is created current_profile is set(updated) to NULL. If I change :
#update_current_profile = User.update(#user, {:current_profile => #professional.id})
to something different, for example:
#update_current_profile = User.update(#user, {:current_profile => #professional.user_id})
or
#update_current_profile = User.update(#user, {:current_profile => 3})
it stores data in User.current_profile perfectly.
I was trying #professional without an .id too. Why is this doing so?
Another question is. Is this the best way to store current_profile of user? Would you recommend me any better/safer/more efficient solution?
Thanks all of you guys.
#professional is a new, unsaved record and therefore does not have an id yet. Can only update the current_profile once the #professional record was saved.
Just reorder the lines a bit and it should work:
def create
#professional = Professional.new(professional_params)
#user = current_user
#professional.user_id = current_user.id
if #professional.save
#update_current_profile = User.update(#user, {:current_profile => #professional.id})
# ...
else
# ...
end
end
Just another tip: You use many instance variables (the one with the #) in this method. I do not know enough about your code, but I would suggest to look if some of them can be replaced with local variables. Rule of thumb: Only use instance variables in controllers when you want to share that variable with another method or the view.

ERB is not getting some values of a local hash

I am using Sinatra and rendering views with ERB.
I have the following action
get '/user/:id' do
u = #users.retrieve( params[:id] )
u[:mykey] = [1,2,3]
erb( :user, :locals => { :user => u } )
end
and the view looks like this
<body>
<h1><%= user["name"] %></h1>
<pre><%= user["mykey"].to_json %></pre>
and where I expect to get the [1,2,3] array, I get a big fat null.
Primitive values such as the name, are passed without a problem.
Is this of class Hash or HashWithIndifferentAccess?
You are setting user[:mykey] and retrieving user["mykey"]. Use symbol or string, don't mix them unless you are using HashWithIndifferentAccess.

Add readable field descriptions to ActiveRecord models

I'd like to add descriptions to ActiveRecord model fields to serve as basic instructions / examples for each of the fields. Basically model metadata. I can then display these in the UI (next to the fields on a form etc.)
The way I'm planning to do it is simply create a static hashtable inside the model with the field name as the key and description as the value. I.e.
FIELD_DESCRIPTIONS = {
'category' => 'Select the category it should appear within.',
'title' => 'The title should be a short but descriptive summary.',
'description' => 'Please enter a full description.'
}
etc.
Then I would create a a basic form helper that would wrap these explanations inside of a span (initially hidden and shown via jQuery) so they could be instatiated via f.field_description(:title) or something along those lines.
Anyone have any better ideas? I'd like to keep this field metadata in the model since many views could use the same information, and I also think it's nice to have descriptions within the model when you're going back to look at the code (like how DataMapper can be used right within the model to specify fields).
To give you a little more detail on what I've already done (and it works fine) here's the code. I think there has to be a prettier way of expressing these descriptions in the model, so let me know if you have any ideas.
In model:
FIELD_DESCRIPTIONS = {
'category' => 'Select the category it should appear within.',
'title' => 'The title should be a short but descriptive summary.',
'description' => 'Please enter a full description.'
}
def self.describe_field(field)
FIELD_DESCRIPTIONS[field]
end
In application_helper.rb
def field_helper(form, field)
"<span class='field_helper'>#{form.object.class.describe_field(field)}</span>"
end
In view:
<%= field_helper(f, 'title') %>
This will produce the desired output:
<span class='field_helper'>The title should be a short but descriptive summary.</span>
UPDATE:
Ok So this is the final code I'm using based on the accepted answer.
File: /config/initializers/describe_attr.rb
if defined?(ActiveRecord)
# let's us add attribute descriptions to each AR model
class ActiveRecord::Base
def self.describe_attr(*params)
attrs = params.shift
unless attrs.nil?
case attrs
when Hash
##attr_descriptions = attrs
when Symbol
return ##attr_descriptions[attrs]
end
end
##attr_descriptions ||= {}
end
end
end
File: /app/models/project.rb
describe_attr(
:category => 'Select the category the project should appear within.',
:title => 'The title should be a short but descriptive summary of the project.',
:description => 'Describe the project in detail.',
:image => 'Upload an image for the project.'
)
File: /app/helpers/application_helper.rb
# assumes you have a style defined for attr_description
def describe_attr(form, attribute)
"<span class='attr_description'>#{form.object.class.describe_attr(attribute)}</span>"
end
File: /app/views/projects/_form.html.erb
<%= describe_attr(f, :title) %>
The hash is a reasonable simple solution, but if you're on rails 2.2 or higher you might want to try the internationalization api to do this. This would also put you in a good place if you ever wanted to add translations.
Check out the i18n guide for details, but basically you would create a config/locales/en.yml that includes your column names like:
en:
labels:
category: Select the category it should appear within.
Then in your view:
<%= t('labels.category') %>
The namespace is your call of course. Also check out section 4.1.4 for a neat way to separate translations based on your current view template.
If you want to patch ActiveRecord, then you can do something like:
# Add this at the bottom of enviroment.rb
class ActiveRecord::Base
def self.field_description(*params)
attrs = params.shift
unless attrs.nil?
case attrs
when Hash
##field_description = attrs
when Symbol
return ##field_description[attrs]
end
end
##field_description ||= {}
end
end
And inside your model you can add this line like a macro:
class Product < ActiveRecord::Base
field_description :category => 'Select the category it should appear within.',:title => 'The title should be a short but descriptive summary.',:description => 'Please enter a full description.'
end
To get the value
Product.field_description : title
You can mix your solution with the label helper itself:
f.label :title, f.describe(:title)
And in your model:
FIELD_DESCRIPTIONS = {
:category => 'Select the category it should appear within.',
:title => 'The title should be a short but descriptive summary.',
:description => 'Please enter a full description.'
}
def describe(:field)
self.class::FIELD_DESCRIPTIONS[field]
end
Be sure to check out formtastic, which includes support for internationalized (or not) field labels as per matschaffer's answer.
http://github.com/justinfrench/formtastic/

Resources