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 %>
Related
I'm a real newbie at Ruby and Rails, and I've been looking for the solution for two days. I need to submit data from form_tag to action 'create' in my controller to add new entries to database, but looks like I'm doing something terribly wrong, because absolutely nothing happens, and it seems that form_tag doesn't even redirect to needed action.
Here's the page code:
<h1>Todos</h1>
<% #projects.each do |project| %>
<tr>
<h2><%= project.title %></h2>
<% project.todos.each do |todo| %>
<ul style="list-style-type:disc">
<li><%= todo.text %></li>
</ul>
<% end %>
</tr>
<% end %>
<%= form_tag({controller: "mega", action: "create"}, method: "get", remote: true) do %>
<h2>New todo</h2>
<p>
<%= text_field_tag 'text' %>
</p>
<p>
<%= select_tag 'title', options_from_collection_for_select(#projects, 'id', 'title') %>
</p>
<p>
<%= link_to 'CANCEL' %>
<%= link_to 'OK', "", :onclick => "$('#form_id').submit()" %>
</p>
<% end %>
And the controller:
class MegaController < ApplicationController
def index
#projects = Project.all
#todos = Todo.all
end
def update
end
def create
#newTodo = Todo.create(text: params[:text])
#newProject = Project.find_by(title: params[:title])
#newProject.todos << #todo
#newTodo.save
end
end
My routes file. I seriously don't know how it works:
Rails.application.routes.draw do
get 'mega/index'
root 'mega#index'
get 'mega/update'
post 'mega/create'
resources :todos
resources :projects
end
You create resources with a POST request. Never GET.
GET requests should be idempotent - they should not update or alter resources on the server. One very important reason is that they are stored in the browser's history, so pressing the back button will cause unintended consequences for the user.
In Rails flavor MVC instead of tacking the action name on the path of the route you use the HTTP verb to create routes to the correct action:
GET /things things#index
POST /things things#create
I'm not going to attempt to salvage your code (it's deeply flawed) and instead show you how you would solve this the rails way as it is much simpler:
<%= form_for(Todo.new) do |f| %>
<h2>New todo</h2>
<%= f.text_field :text %>
<%= f.collection_select(:project_id, #projects, :id, :title, prompt: true) %>
<%= f.submit %>
<% end %>
This would submit to todos#create - if you want to route it to an unconventional action you can use the url option:
<%= form_for(Todo.new, url: polymorphic_path(controller: 'foo', action: 'bar')) do |f| %>
It's best to learn the rules before you break them.
Route:
display_panel GET /display/panel(.:format) display#panel
Controller:
class DisplayController < ApplicationController
def panel
#approval = Approval.where(user_id: current_user.id)
end
end
View:
<%= form_for approval,url: root_path, method: :patch do |f| %>
<%= f.check_box :pass%>
<%= f.submit %>
<% end %>
I think I do patch in a get action, this causes the error, so I hope to use mathod: :patch to correct it, but it still show me the same error.
I tried many solutions from other similar questions, still not work.
Update your form like this:
<%= form_for #approval, url: [update_path] , method: :patch do |f| %>
<%= f.check_box :pass%>
<%= f.submit %>
<% end %>
[update_path] should be something like approval_path, not root_path. Run rake routes | grep approval to verify if you have setup patch route for approval.
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.
I am new to RoR and still don't have enough experience on solving the different errors that may appear to me. In this case I am designing a blog where I can post articles. More specifically, my problem is related to deleting these articles.
As far as I know, writing:
resources :articles
in the routes file is an alternative for writing:
get "/articles" #index
post "/articles" #create
delete "/articles/:id" #delete
get "/articles/:id" #show
get "/articles/new" #new
get "/articles/:id/edit" #edit
patch "/articles/:id" #update
put "/articles/:id" #update
When I try to delete an article I get the following error:
No route matches [POST] "/articles/1"
The code I wrote was:
View
<% #articles.each do |art| %>
<%= art.title %>
<div>
<%= art.body %> - <%= link_to "Delete", art, method: :delete %>
</div>
<% end %>
Controller
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
It sounds like you have this in your view:
<%= art.body %> - <%= link_to "Delete", art, method: :destroy %>
But you actually need:
<%= art.body %> - <%= link_to "Delete", art, method: :delete %>
I'd advise double-checking this in your app based on your reply to a comment from #GonzaloRobaina.
It looks to me like you're missing the correct path in your code. It should work with something like this :)
<%= link_to "Delete, article_path(art), method: :delete %>
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 %>