I'm trying to create a helper method for my admin links. In quite a few
views I have the code
<% if current_user %>
<%= link_to "Edit", edit_model_path(model) %>
<%= link_to "New", new_model_path %>
<%= link_to "Delete", model, :confirm => "You're a Noob", :method
=> :delete %>
<% end %>
that only display these when logged in.
I would like to do something like this in their place
<%= admin_links(model) %>
and pass the current item into the application helper method
def admin_links(m)
if current_user
a = "#{link_to "edit" edit_m_path(m)}"
a << "#{link_to "new" new_m_path}"
a << "#{link_to "Delete", m, :confirm => "Your a Noob", :method
=> :delete}"
end
end
Or something of the like.
basically you need to transform the class name of the model into something pointing to the correct path.
model_name = m.class.to_s.underscore
And then use it to call the appropriate path methods
link_to "edit", send("edit_#{model_name}_path", m)
As an aside, you don't need to put the link_tos in #{} because that function simply returns a string.
Rails provides polymorphic routes to handle this problem: http://api.rubyonrails.org/classes/ActionDispatch/Routing/PolymorphicRoutes.html
= link_to "Edit", polymorphic_path(model), :method => :put
I would use a partial for this - instead of a helper. Wherever you want to display these links in your views, simply render the partial:
<%= render :partial => "admin_links", :locals => { :model => model } %>
In _admin_links.html.erb just paste the original code:
<% if current_user %>
<%= link_to "Edit", edit_model_path(model) %>
<%= link_to "New", new_model_path %>
<%= link_to "Delete", model, :confirm => "Your a Noob", :method => :delete %>
<% end %>
Related
I'm trying to add 'add to cart' method for my items.
items_controller:
def to_cart
#item = Item.friendly.find(params[:id])
#item.add_to_cart
redirect_to root_path
end
routes:
resources :items do
put :to_cart, on: :member
end
model:
def add_to_cart
current_user.cart.items << self
current_user.cart.save
end
show:
<%= #item.name %>
<%= link_to 'add to cart', to_cart_item_path(#item) %>
I got RoutingError: No route matches [GET] "/items/first/to_cart"
'first' because of friendly id.
What I did wrong?
Add method: :put in your link by default it's GET and rails is trying to find the route with GET method
<%= link_to 'add to cart', to_cart_item_path(#item), method: :put %>
Links on the web only send GET requests.
To send a POST/PUT/PATCH/DELETE request you need to use a form.
<%= form_for to_cart_item_path(#item), method: :put do |f| %>
<% f.submit 'Add to cart' %>
<% end %>
Rails provides a shortcut for this button_to( 'add to cart', to_cart_item_path(#item) ).
The Rails UJS driver (unobtrusive javascript driver) also provides a method that creates a form in the client when the link element has the data-method attribute:
<%= link_to 'add to cart', to_cart_item_path(#item), method: :put %>
ActionView::Template::Error (No route matches {:action=>"update",
:controller=>"text_posts"}):
<h1><%= text_post.blog %></h1>
<%= form_tag do %>
<%= link_to "New Text Post", controller: "text_posts", action: "new" %>
<%= link_to "Edit", controller: "text_posts", action: "update" %>
<%= link_to "Delete", controller: "text_posts", action: "destroy" %>
<% end %>
<span class='likes pull-left'>
new_image_link GET /image_links/new(.:format) image_links#new
edit_image_link GET /image_links/:id/edit(.:format) image_links#edit
image_link GET /image_links/:id(.:format) image_links#show
PATCH /image_links/:id(.:format) image_links#update
PUT /image_links/:id(.:format) image_links#update
DELETE /image_links/:id(.:format) image_links#destroy
text_posts GET /text_posts(.:format) text_posts#index
POST /text_posts(.:format) text_posts#create
new_text_post GET /text_posts/new(.:format) text_posts#new
edit_text_post GET /text_posts/:id/edit(.:format) text_posts#edit
text_post GET /text_posts/:id(.:format) text_posts#show
PATCH /text_posts/:id(.:format) text_posts#update
PUT /text_posts/:id(.:format) text_posts#update
DELETE /text_posts/:id(.:format) text_posts#destroy
You can do something like this:
<%= link_to "Edit", edit_text_post_path(text_post) %>
Since you use resources in your routes.rb(according to the routes your provided). If you want to go to the edit page, it's better to use the path helper, remember to provide the text_post you want to edit in the argument:
<%= link_to "Edit", edit_text_post_path(text_post) %>
<%= link_to "Delete", text_post_path(text_post), :method => :delete %>
The way you wrote is when you have something define in your routes.rb like this:
match ':controller(/:action(/:id(.:format)))', :via => :all
Even so, you still have to give it the text_post you want to edit because it requires an id in the end of the url. So it should be like:
<%= link_to 'Edit', :controller => 'text_posts', :action => 'edit', :id => text_post %>
<%= link_to 'Delete', :controller => 'text_posts', :action => 'destroy', :id => text_post %>
You don't need to wrap the links into a form_tag.
Hope it helps.
Try this .................
<h1><%= text_post.blog %></h1>
<%= link_to "New Text Post", new_text_post_path %>
<%= link_to "Edit", edit_text_post_path(text_post) %>
<%= link_to "Delete", text_post_path(text_post), method: :delete %>
Hope this will work for you.
In a Rails 3 project, I have an index list of costprojects.
I have a controller action called `viewprojects'.
I would like to add a checkbox column to the index list. Then let the user select which projects should be included in the pdf.
index:
<% #costprojects.each do |costproject| %>
<tr>
<td><%= check_box_tag "costproject_ids[]", costproject.id %></td>
...
<%= link_to 'PDF Selected', costprojects_viewprojects_path(:format => "pdf",:costproject_ids => costproject_ids[] ), :class => 'btn btn-success', :target => "_blank" %>
Controller:
def viewprojects
#costprojects = params[:costproject_ids]
respond_to do |format|
format.html
format.pdf do
render :pdf => "costprojects.pdf",
:show_as_html => params[:debug].present?,
:page_size => 'letter'
end
end
end
I'm getting:
undefined local variable or method `costproject_ids'
Update1:
Tried:
def viewprojects
#costprojects = params[:costproject_ids[]]
...
<%= link_to 'PDF Selected', costprojects_viewprojects_path(:format => "pdf",:costproject_ids[] => costproject_ids[] ), :class => 'btn btn-success', :target => "_blank" %>
I get "wrong number of arguments (0 for 1..2)"
Do I need to add form_tag and submit_tag?
Thanks for the help!
As Legendary mentioned in the comments you need to wrap this in a form. A link_to isn't going to transmit the value of the selected ids unless its contained in its query parameters, which it can't know at render time.
Try something more like this:
<%= form_tag costprojects_viewprojects_path(format: "pdf") do %>
<% #costprojects.each do |costproject| %>
<tr>
<td><%= check_box_tag "costproject_ids[]", costproject.id %>
</td>
<% end %>
...
<%= submit_tag "PDF Selected", class: "btn btn-success" %>
<% end %>
You should then be able to access the array of cost_project_ids simply with params[:cost_project_ids] in the controller, which it seems you're already doing. Note that this will send an HTTP POST, rather than a GET, so ensure your routes are correctly setup for that verb.
In my rails app I have a model Song. On one of the user's profile pages user_music_path(#user) I'm rendering all of their songs.
People can also like these songs, which is set up and working, I just want to use AJAX instead of page refreshes. The problem I'm having is when using ajax, I get the error undefined local variable or method "song" when I'm clicking the link "like".
Here is some of my code:
User's Music Page views/users/music.html.erb
...
<ul class="playlist list-group">
<%= render #songs %>
</ul>
views/songs/_song.html.erb
<li class="list-group-item">
<p class="pull-right">
<%= render :partial => 'songs/like_button', :locals => {:song => song} %>
<%= render :partial => 'songs/likes', :locals => {:song => song} %>
</p>
</li>
views/songs/_like_button.html.erb
<% if current_user.voted_on?(song) %>
<%= link_to "Unlike", unlike_song_path(song), :method => :post, :remote => true %>
<% else %>
<%= link_to "Like", like_song_path(song), :method => :post, :remote => true %>
<% end %>
views/songs/_likes.html.erb
<%= song.votes.count %>
views/songs/like.js.coffee
$("p.pull-right").html('<%= render :partial => "songs/like_button", :locals => {:song => song} %><%= render :partial => "songs/likes", :locals => {:song => song} %>');
controllers/songs_controller.rb
def like
begin
#vote = current_user.vote_for(#song = Song.find(params[:id]))
#vote.save
respond_with #song.user, :location => user_music_path(#song.user)
rescue ActiveRecord::RecordInvalid
redirect_to #song
end
end
And as mentioned earlier, the :like action worked perfectly before I starting using AJAX. I've also added respond_to :html, :js to my songs_controller. And the error I get when I try to like the song is ActionView::Template::Error (undefined local variable or method "song" for #<#<Class:0x000001028de9d0>:0x00000106ecd9f0>):
Where you have
<%= song.name %>
try instead
<%= #song.name %>
And do the same with your link_to paths and your render calls.
Do rake routes and use of of them for the link, e.g. (pseudo-code) link_to 'song', song_audio_path
I am working on a app where you can add task etc. I know this is kind of weird but I just like to see how others would implement this. How would you change the following code into a helper method and use it?
The original code
<h2>My Tasks</h2>
<% task = #work.tasks %>
<% if task.empty? %>
<%= link_to 'Create a new task', new_task_path %>
<% else %>
<%= render :partial => 'notes/note', :locals => {:note => #note} %>
<% end %>
My way of doing a helper method
def task_check
task = #work.tasks
if task.empty?
link_to 'Create a new task', new_task_path
else
render :partial => 'notes/note', :locals => {:note => #note}
end
end
In my view
<%= #work.task_check %>
Personally, I wouldn't extract this out at all, this is view logic and it belongs in the views. It definitely doesn't belong in a model, but it could arguably be extracted into a helper. I'd change it slightly:
<h2>My Tasks</h2>
<% if #work.tasks.blank? %>
<%= link_to 'Create a new task', new_task_path %>
<% else %>
<%= render :partial => 'notes/note', :locals => {:note => #note} %>
<% end %>
Calling blank? instead of empty? will work even if #work.tasks is nil
.
You can't define a helper in the model. It won't have access to render, link_to or any other controller or view methods. So just define your method almost exactly as is in a file in your helpers directory, maybe application_helpers.rb or work_helpers.rb:
def task_check(work, note)
task = work.tasks
if task.empty?
link_to 'Create a new task', new_task_path
else
render :partial => 'notes/note', :locals => {:note => note}
end
end
And then call it in your view like so:
<%= task_check(work, note) %>