Nested Routing with a Collection in Rails - ruby-on-rails-3

I'm getting an error: No route matches {:action=>"sort", :controller=>"links"}
I'm adapting from a non-nested example and am having trouble figuring out the nested routing.
Right now, my route looks like this:
resources :groups do
resources :navbars do
resources :links do
collection { post :sort }
end
end
post :add_user, on: :member
end
I am rendering a collection of links from navbar>show:
= render partial: 'links/link', collection: #navbar.links
and here's the collection, links>_link.html.haml:
%ul#links{"data-update-url" => sort_group_navbar_links_url}
- #links.each do |faq|
= content_tag_for :li, link do
%span.handle [drag]
= link.method_name
= link.code
= link.button
= link.text
= link_to 'Edit Link', edit_group_navbar_link_path(#group, #navbar, link), class: 'btn btn-mini'
= link_to 'Delete', group_navbar_link_path(#group, #navbar, link), data: { confirm: 'Are you sure?' }, method: :delete, class: 'btn btn-mini'
My links_controller has the sort action:
def sort
params[:link].each_with_index do |id, index|
Link.update_all({display_order: index+1}, {id: id})
end
render nothing: true
end
Because my link collection is being rendered from the navbar>show page, it's not clear to me where my sort action should be located (in links_controller or in navbars_controller).
And my navbars_controller defines #links:
def show
#links = #navbar.links.order("display_order")
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #navbar }
end
end
Also here's the js for good measure (links.js.coffee):
jQuery ->
$('#links').sortable
axis: 'y'
handle: '.handle'
update: ->
$.post($(this).data('update-url'), $(this).sortable('serialize'))
Maybe this last line also needs work to include the route?
I'm using rails 3.2.

Related

No route matches {:action=>"show", :controller=>"restaurants"}

If I want to go with my home page clicking on the map localhost:3000/maps gets out this error No route matches {:action=>"show", :controller=>"restaurants"}
controllers/maps_controller.rb
def index
#maps = Map.all
#json = Map.all.to_gmaps4rails do |map, marker|
marker.infowindow info_for_restaurant(map.restaurant)
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #maps }
end
end
def show
#map = Map.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #map }
end
end
private
def info_for_restaurant(restaurant)
link_to restaurant_path do
content_tag("h2") do
restaurant.name
end
end
end
routes.rb
resources :restaurants
resources :maps
This is answer for my question:
controllers/maps_controller.rb
def index
#maps = Map.all
#json = Map.all.to_gmaps4rails do |map, marker|
marker.infowindow render_to_string(:partial => "/maps/maps_link",
:layout => false, :locals => { :map => map})
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #maps }
end
end
views/maps/_maps_link.html.erb
<div class="map-link">
<h2><%= link_to map.restaurant.title, map.restaurant %></h2>
</div>
You referred to restaurant_path within info_for_restaurant, which is part of MapsController. Rails met error here.
You need to either define the restaurant_path in restaurant controller, or comment out this function in maps controller at this moment.
Your approach is wrong in several levels. Let's work on them, one at a time:
1) Your call to the route helper is wrong:
restaurant_path is the route helper for a show action. A show action needs an id parameter to be valid. Your call is missing a parameter.
So, your code must be something like this:
def info_for_restaurant(restaurant)
link_to restaurant_path(restaurant) do
content_tag("h2") do
restaurant.name
end
end
end
To see the parameters needed for each action, you can run rake routes on the console.
However, this does not solve the problem, as you're also:
2) Calling view helpers from your controller
link_to and content_tag are view helper methods, and you don't want to bother your controller with view issues. So, the best way to solve this problem is to move your info_for_restaurant method to a helper, and call it from a view instead.
So, now, your controller will not assign anything to #json, and the last line of your view will look like this:
<%= gmaps4rails #maps.to_gmaps4rails {|map, marker| marker.infowindow info_for_restaurant(map.restaurant) } %>

Submitting form via multiple partials

I have a really long form which I would like to break up into about 5 partials. When the user hits 'Next' at the bottom of each partial I want to use AJAX to load the next partial until the last partial submits the entire form into the database. Also, if the user hits 'Previous' I need the fields to be populated with what the user filled in previously.
So far I have this which is not working:
users/new.html.erb
<%= form_for(#user, :html => { :class => "form-horizontal" }, remote: true) do |f| %>
...
<%= f.submit "Next" %>
users_controller.rb
def create
#user = User.new(params[:user])
if #user.save
respond_to do |format|
format.html { flash[:success] = "Welcome to Friends First!"
redirect_to #user }
format.js
end
else
render :new
end
end
create.js.erb
$("#site_content").html("<%= escape_javascript(render('layouts/partial2')) %>");
I would put each of the 5 parts into separate divs (display: none) and only show (display: block) the first. When the user clicks "next", I would show the second, etc. The final submit to the create action can also be done via jquery through
$.ajax(
url: '/users',
type: 'post',
data: $("form").serialize()
)
I hope, that helps.

Ability to store Name/Email in a session

I have a form that I want a user to put in their name and email, which get stored in a session. They can then post text in a chat box.
In my view, to create the initial session:
<%= simple_form_for(#comments, :url => guest_login_order_path(#order)) do |f| %>
<input name="comment[new_user_comment_name]" />
<input name="comment[new_user_comment_email]" />
<%= f.button :submit, :value => 'Guest Signin', :class => '' %>
<% end %>
This goes to my controller:
def guest_login
#order = Order.where(:public_hash => params[:public_hash]).first
session[:new_user_account] = params[:new_user]
respond_to do |format|
if session[:new_user_account]
format.html { redirect_to #order, notice: 'Your account has been created.' }
format.json { render json: #order, status: :created, location: #order }
else
format.html { render action: "invoice" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
The params get passed correctly but I'm not quite sure if the cookie is being created. Is there way to specify a name so I can see if it was created? Also in the view, would I have a conditional then to see if there is a session present?
Rails creates a session for you so you don't need to check if it's present. If you'd like to easily retrieve the user from the session you can create a helper method in your application controller:
class ApplicationController < ActionController::Base
def current_user
#current_user ||= session[:new_user_account]
end
helper_method :current_user
end
This method will be available to other controllers and views in your app.

Using jquery tokeninput and acts_as_taggable_on

I've implemented the framework outlined in this post: How to use jquery-Tokeninput and Acts-as-taggable-on with some difficulty. This is working insofar as prepopulating with the appropriate theme and ajax search, but when I enter a new tag, it is immediately deleted when the text area loses focus. I'm not sure what I'm doing wrong. Here's some of my relevant code:
User Model (does the tagging):
class User < ActiveRecord::Base
[...]
# tagging
acts_as_tagger
Item Model (accepts a tag):
class Item < ActiveRecord::Base
attr_accessible :title, :tag_list
#tagging functionality
acts_as_taggable_on :tags
Item Controller:
def tags
#tags = ActsAsTaggableOn::Tag.where("tags.name LIKE ?", "%#{params[:q]}%")
respond_to do |format|
format.json { render :json => #tags.collect{|t| {:id => t.name, :name => t.name }}}
end
end
On my form partial:
<%= f.input :tag_list, :label => "Tags", :input_html => { :class => "text_field short", "data-pre" => #item.tags.map(&:attributes).to_json }, :hint => "separate tags by a space" %>
my routes:
get "items/tags" => "items#tags", :as => :tags
resources :items
[almost there!!!]
the js on the form [note: the id of the element is assigned dynamically]:
<script type="text/javascript">
$(function() {
$("#item_tag_list").tokenInput("/art_items/tags", {
prePopulate: $("#item_tag_list").data("pre"),
preventDuplicates: true,
crossDomain: false,
theme: "facebook"
});
});
</script>
If you still want to use Jquery TokenInput and add tags there are different ways to do it.
1.
This is actually from my same question; the newest answer: How to use jquery-Tokeninput and Acts-as-taggable-on
This could go in your controller.
def tags
query = params[:q]
if query[-1,1] == " "
query = query.gsub(" ", "")
Tag.find_or_create_by_name(query)
end
#Do the search in memory for better performance
#tags = ActsAsTaggableOn::Tag.all
#tags = #tags.select { |v| v.name =~ /#{query}/i }
respond_to do |format|
format.json{ render :json => #tags.map(&:attributes) }
end
end
This will create the tag, whenever the space bar is hit.
You could then add this search setting in the jquery script:
noResultsText: 'No result, hit space to create a new tag',
It's a little dirty but it works for me.
2.
Check out this guy's method: https://github.com/vdepizzol/jquery-tokeninput
He made a custom entry ability:
$(function() {
$("#book_author_tokens").tokenInput("/authors.json", {
crossDomain: false,
prePopulate: $("#book_author_tokens").data("pre"),
theme: "facebook",
allowCustomEntry: true
});
});
3.
Not to sure about this one but it may help: Rails : Using jquery tokeninput (railscast #258) to create new entries
4.
This one seems legit as well: https://github.com/loopj/jquery-tokeninput/pull/219
I personally like the first one, seems easiest to get and install.

How to create a custom POST Action in Rails3

I am trying to create a custom POST action for my article object.
In my routes.rb, I have set the action in the following way:
resources :articles do
member do
post 'update_assigned_video'
end
end
In my articles_controller.rb I have:
def update_assigned_video
#article = Articles.find(params[:id])
#video = Video.find(:id => params[:chosenVideo])
respond_to do |format|
if !#video.nil?
#article.video = #video
format.html { redirect_to(#article, :notice => t('article.updated')) }
else
format.html { render :action => "assign_video" }
end
end
Then in my view I make a form like this:
<%= form_for #article, :url => update_assigned_video_article_path(#article) do |f|%>
[...]
<%= f.submit t('general.save') %>
The view renders (so I think he knows the route). But clicking on the submit button brings the following error message:
No route matches "/articles/28/update_assigned_video"
rake routes knows it also:
update_assigned_video_article POST /articles/:id/update_assigned_video(.:format) {:action=>"update_assigned_video", :controller=>"articles"}
What am I doing wrong?
Is this the wrong approach to do this?
Your form_for will do a PUT request rather than a POST request, because it's acting on an existing object. I would recommend changing the line in your routes file from this:
post 'update_assigned_video'
To this:
put 'update_assigned_video'