gmaps4rails select scope - ruby-on-rails-3

I have gmaps4rails working to show all locations. But, I would like to show a map with workorders using their locations. Workorder belongs_to location.
In the workorders controller, this will display all of the locations:
#json = Location.all.to_gmaps4rails
But, this won't display workorder locations:
#json = Workorder.location.all.to_gmaps4rails
This is the view code:
<%= gmaps("markers" => {"data" => #json, "options" => {"list_container" => "markers_list"} }) %>
<strong><ul id="markers_list"> </ul></strong>

belongs_to specifies a one-to-one association with another class (It returns only one entry).
to_gmaps4rails is a method from Enumerable (it expects to be called on an Array).
Also, you can't call the relation directly from the class (it's not a class method, it's an instance method):
Workorder.location.all.to_gmaps4rails
should be:
a_work_order = WOrkorder.first
a_work_order.location
and to use it with to_gmaps4rails
[a_work_order.location].to_a.compact.to_gmaps4rails
It isn't pretty, but it covers both when location is nil and when it returns something.

Related

How to get typeahead/autocomplete text to refer to foreign id in Rails?

So I have been working on getting this Twitter Bootstrap typeahead to work and right now I can get a list of all my data when I start typing it into the form, but when I submit, the values do not get passed in as IDs. Is there any way for me to pass in an id number based on the autocomplete selection?
Here's the code I'm using...
<%= f.text_field :cargo_to_load_id, :data => { provide: "typeahead", source: Cargo.order(:name).map(&:name) , items: "9" } %>
Turns out that I need to have these getter and setter methods in my model file. These will then do the work of finding the corresponding id.
def cargo_to_unload_name
cargo_to_unload(:name)
end
def cargo_to_unload_name=(name)
self.cargo_to_unload = Cargo.find_by_name(name)
end
def cargo_to_load_name
cargo_to_load(:name)
end
def cargo_to_load_name=(name)
self.cargo_to_load = Cargo.find_by_name(name)
end

detect if a form is submitted with ruby on rails?

Is there a way to detect if a form is submitted? Im trying to set a class based on a custom validation something like below example, is that possible?
.control-group{ :class => ("error" if form_is_submitted ) }
Now trying :
.control-group{ :class => ("error" if params[:user][:profile_attributes][:gender] == nil) }
This fails if the form is not submitted because then the params are nill and throws an error
If your form data is submitted through fields with name attributes like user[profile_attributes][gender] (all having the user prefix), you can check if the :user exists in params.
... if params.include?(:user)
If for some reason (like coming from the route) params[:user] is already going to have a value even for GET requests, you can look for a specific form field having a value. For example, you could add a hidden field
<%= f.hidden_field :some_field, :value => true %>
and check for it in your condition
... if params[:user].include?(:some_field)
You can alternatively check if the request is via the POST method
... if request.post?
This works for other methods as well, like request.put? for an update method.

Creating actions and routes for tags and categories

I'm creating a blog for myself with Rails 3.2.5, and am trying to handle tags and categories properly. I want to allow the user to click on a link_to with the tag name that brings them to other entries with the same tag and have the URL be 'root.com/tag/selected-tag'. For categories I'd like to have the same thing with the URL being 'root.com/category/selected-category'. I've already started on this and am using acts_as_taggable_on for tagging and a simple text input for the category (will become a select input when I decide what categories I want).
How would I go about handling this? I've tried creating a controller for tags and categories, each with only an index action. For 'tags#index' I have:
#entries = Entry.order('created_at desc').tagged_with(params[:format]).paginate(:page => params[:page], :per_page => 10)
and for each tag's link I have:
= link_to tag, tag_path(tag)
For some reason the tag is being passed as the :format, that's why I've got tagged_with(params[:format]).
I have 'categories#index' defined as:
#entries = Entry.order('created_at desc').where(:category => params[:format]).paginate(:page => params[:page], :per_page => 10)
and the category's link is:
- entry.tag_list.each do |tag|
= link_to tag, tag_path(tag)
Since the tags and category are being passed as the :format the URL's are appearing as 'root.com/tag.selected-tag' and 'root.com/category.selected-category'.
How would I go about handling tags and categories properly to achieve getting the URL's to appear as 'root.com/tag/selected-tag' and 'root.com/category/selected-category'?
The below will probably do what you want:
In your routes:
match 'tag/:tag' => 'tags#index', :as => :tag
Then, when someone visits example.com/tag/some-tag-here, you can then access the tag within your controller through:
params[:tag]
you can link to your route by doing:
link_to tag, tag_path(:tag => tag)
An analogous solution should work for categories as well.

newbie: render different view and layout based on condition loose #object access

I am trying to render a view + layout based on a condition. The following code seems to work but loses access to #objects set upfront. I call this code in a ProfilesController method Show.
#profiles = Profile.where(:user_id => current_user.id).first
if #profile.nil? == true
render :view => "show",
:layout => "application"
else
render :template => "profiles/my_profile",
:layout => "profiles"
end
Gives output:
undefined method `profiles' for nil:NilClass
How could one render based on a condition and still preserve the previous set #objects (in this case the access to #profiles)
Setting layout in view is not the way to go, its not the rails way and was not advised so even if possible. I changed setting layout in controller action and render the right code in my show partial wich complete solved the issue.

Have I coded myself into a corner with this custom route?

I don't even know how to write a proper title for this. I kind of cobbled together some routing code based on a bunch of different articles, and now I'm wondering if I've painted myself into a corner.
I've got a NewsArticle model, and I want the links to look like this:
/news # List of all articles
/news/2011 # List of articles published this year
/news/2011/06 # List of articles published this month
/news/2011/06/28 # List of articles published on this day
/news/2011/06/28/my-post-title # Actual article
Ok, going against the Rails way already, but so be it.
I've got routes setup like this:
controller :news_articles, :via => [:get] do
match '/news(/:year/(/:month(/:day)))' => :index, :constraints => { :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/ }
match '/news/:year/:month/:day/:id' => :show
end
Note there is no :as declaration. That's because when I do add something like :as => "news_archive" then I end up with news_archive_path which returns something stupid like "/news?year=2010&month=4". So, I excluded that bit and wrote my own path methods in my application helper file:
def news_archive_path(year = nil, month = nil, day = nil)
return "/news" if year.nil?
t = Time.zone.local(year.to_i, month.nil? ? nil : month.to_i, day.nil? ? nil : day.to_i)
if month.nil?
"/news/#{t.year}"
elsif day.nil?
"/news/#{t.year}/#{"%02d" % t.month}"
else
"/news/#{t.year}/#{"%02d" % t.month}/#{"%02d" % t.day}"
end
end
def news_article_path(article)
t = article.published_at.in_time_zone
"#{news_archive_path(t.year, t.month, t.day)}/#{article.friendly_id}"
end
Great, this all works in practice. But now I've run into a problem where I'm testing my controllers and I want to make sure that the right links appear on the rendered templates. (Oh yeah, I'm not keeping separate view tests but instead using render_views in my controller tests.) But the tests are failing with the error undefined methodnews_article_path' for #`.
So, have I just approached this all wrong and painted myself into a corner? Or can I get out of this by somehow including the helper methods in the controller test? Or do I just suck it up for the sake of getting the test to pass and hardcode the links as I expect them to be?
To make news_article_path available you need to do:
class MyClass
include Rails.application.routes.url_helpers
end
Now MyClass#news_article_path will be defined. You can try to include the url_helpers into your test case. I've seen that break recently with "stack level too deep" errors (it creates an infinite recursion of "super" calls in initialize). If it doesn't work, create your own view helpers class and do "MyViewHelper.new.news_article_path" etc.
It's probably not a good idea to be generating the paths by concatenating string in your path helpers. Instead, simply use the url_for() method. Eg:
def news_article_path(article, options = {})
url_for(options.merge(:controller => :articles,
:action => :show,
:id => article.id,
:year => article.year,
:month => article.month,
:day => article.day))
end
(This assumes day, month, year are added as quick methods on your model, eg:
def year
self.published_at.in_time_zone.year
end
For your tests, either include the helper methods via something along these lines: My helper methods in controller - or use the url_for method again.
...That said - as you suggested, testing views within controller tests isn't ideal. :)