Simple rails button question - ruby-on-rails

Very noob question here.
I am trying to make a digg-like website and when they click a button I want a counter to go up, just like in digg. So I did:
<%=button_to("vote", :action => "vote")%>
and then in my controller I made a action:
def vote
#article = Article.find(params[:id])
#article.votes = #article.votes + 1
respond_to do |format|
format.html { redirect_to(#article.company) }
end
end
When I do that you I get the error:
No route matches {:action=>"agree", :controller=>"companies"}
What should I do?

In a terminal type "rake routes", then look at your routes to find what path you need to use to vote for an article.
Then use
<%= button_to "Vote", vote_path(:id => article.id) %>
Just change the "vote_path" to the path in your rake routes output.
If it's not already in your rake routes file, put something like this in
match "vote/:id" => "controler_name#vote", :as => :vote

Take a look at http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

Related

What does article_path mean?

I am quite new to programming and am working my way through the official Getting Started guide. This guides new RoR programmers through a practical Blog application involving CRUD articles that have many comments.
article_path is something that comes up quite often but I have no idea at all at what this does, what it means, how it is used etc.
Here are some examples of how the guide uses article_path:
<%= form_for :article, url: articles_path do |f| %>
(in app/views/articles/new.html.erb)
<%= link_to 'Back', articles_path %>
(also in app/views/articles/new.html.erb)
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
(in app/controllers/articles_controller.rb)
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
(in app/controllers/comments_controller.rb)
I would be very grateful for an explanation, as I like to fully understand what a specific line of code does.
Thank you for your time
articles_path will produce something like this http://yourserver.com/articles which will be associated with your ArticlesController and index action.
Consequently article_path(#article) will produce something like this http://yourserver.com/articles/1234567 which will be associated with your ArticlesController and show action and produce a page for an article with id 1234567.
You also can do rake routes on the command line and see all the details
The following in your routes.rb file:
match '/articles' => 'articles#index', :via => [:get], :as => :articles
Can be invoked my mentioning articles_path. In the above example any request given to domain.com/articles will be mapped to articles#index. Instead of making request to '/articles' you can just use 'articles_path'
Another Example:
match '/articles/all' => 'articles#getAll', :via => [:get], :as => :articles_complete
Any request to yourserver.com/articles/all will be mapped to articles controller and getAll Action. Instead of mentioning '/articles/all', you can just invoke 'articles_complete_path'. I'm naming articles_complete instead of articles_all to show the convention used.

How to make a custom route in Rails? By custom I mean one that reacts to params

So essentially I've setup a route to match "products/:product", which seems to respond to a page like baseurl/products/toaster and displays the toaster product. My problem is I can't seem to use link_to to generate this path, and by that I mean I don't know how. Any help on this?
There are several solutions on this one :
<%= link_to 'Toaster', { :controller => 'products', :action => 'whatever', :product => 'toaster' } %>
But it's not really Rails Way, for that you need to add :as => :product at the end of your route. This will create the product_path helper that can be used this way :
<%= link_to 'Toaster', product_path(:product => 'toaster') %>
Within your routes file you can do something like:
match "products/:product" => "products#show", :as => :product
Where the controller is ProductsController and the view is show
within the Products controller your have
def show
#product = Hub.find_by_name(params[:product])
respond_to do |format|
format.html # show.html.erb
end
end
Where whatever is in the products/:product section will be available via params.
Then, since we used :as in your routes you can do this with link_to:
<%= link_to product(#product) %>
Where #product is an instance of a product or a string. This is just an example and the param can be anything you want, the same goes for controller/action. For more info you should check out this.
Hope this helps!

Rails: link_to calls custom method in controller

I am looking to use link_to to call a method in my controller. However, for some odd reason the route looks for the show method.
In my view:
<% #beverages.each do |beverage| %>
..
<%= link_to 'Archive', beverages_archive_path(:id => beverage.id) %>
..
<% end %>
In my config/routes.rb
match 'beverages/archive' => 'beverages#archive'
In my beverages_controller.rb
def archive
beverage = Beverage.find(params[:id])
respond_to do |format|
# format.html # show.html.erb
format.json { render json: beverage }
end
# beverage.update_attribute('archive', true)
end
When I click on the archive link in the view, the URL does change to: http://localhost:3000/beverages/archive?id=11, however I get the following error.
The error I get:
ActiveRecord::RecordNotFound (Couldn't find Beverage with id=archive):
app/controllers/beverages_controller.rb:46:in `show'
Any idea on what I am doing wrong? Your help is much appreciated!
PS. I also looked at Rails 3 link_to delete destory method calls show method?
but nothing seemed to work.
Have you tried this in your routes?
match 'beverages/:id/archive' => 'beverages#archive', as: :beverages_archive
This will create the beverages_archive_path method for you. Also, as you are looking for a specific beverage, use :id inside the route so that it knows where to take the id parameter from.
Apart from that, you can always tell a link specifically which controller and action to link to by doing:
link_to "Label", :controller => :my_controller, :action => :index
Taken from here: Ruby on rails 3 link_to controller and action
Use the other notation (not match) instead.
resources :beverages do
collection do
get :archive
end
end
Try this one out and let me know if something went wrong.
There's not quite enough information here to know why beverages_archive_path works in your app -- one problem is that your routes file does not define a name for your beverages#archive route. What you want is something like:
match 'beverages/archive' => 'beverages#archive', :as => :beverages_archive
or better yet use resourceful routing conventions like so:
resources :beverages do
collection do
get :archive
end
end
What's happening is that you have a beverages#show route that matches /beverages/:id, and this is what /beverages/archive matches (with :id => 'archive').

Rails - Add action to controller created by scaffold

I'm trying to add an action called rollback to controller.
As I've seen, the only things I should do is writting the new action:
def rollback
puts "ROLLBACK!"
respond_to do |format|
format.html # index.html.erb
format.json { render json: #components }
end
Modify the routes.rb file:
resources :components do
collection do
post :rollback, :as => 'rollback'
end
end
And calling the action from some view:
<%= link_to 'Rollback', rollback_components_path %>
But I get the following error:
Couldn't find Component with id=rollback
app/controllers/components_controller.rb:18:in `show'
That's because instead of going to rollback action, the controller thinks that we are trying to 'show' to component with id 'rollback'.
Something that it seems weird for me is that calling 'new' action rails uses new_component_path (without s, in singular), but if I write rollback_component_path it throws me an error and I cant see the view.
In your routes you require a POST, just clicking a link is by default a GET, so either write
resources :components do
collection do
get :rollback
end
end
and then the link_to will work as expected.
I am assuming the rollback operation is not idempotent, so a POST is semantically better in that case.
If you write your link as follows, then rails will create an inline form for you:
link_to 'Rollback', rollback_components_path, :method => 'post'
Hope this helps.
This will work
routes.rb
resources :components
match "components/rollback" => "components#rollback", :as => :rollback
In views
<%=link_to 'Rollback', rollback_path%>

rails newbie - how to change querystring into route

Am learning rails the way most do, by implementing a blog. I've just put tagging in and have got my article view to the point where it's displaying clickable tags when you display an article. The issue is that the links are coming out like this;
http://localhost:3000/articles?tagged_with=development
I would prefer not to have the querystring, and instead have something like;
http://localhost:3000/articles/tagged_with/development
I can't find anything relevant in the "routes inside out" guide on the rails site (lots of useful stuff in there, just not this!)
Complete code here:
https://github.com/mikeyhogarth/mikeyblog
Pertinant bits are;
the link in _article.html.erb:
<%= link_to tag, articles_path(:tagged_with => tag) %>
the articles index controller:
def index
if(params[:tagged_with])
#tag = params[:tagged_with]
#articles = Article.tagged_with #tag
else
#articles = Article.all
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #articles }
end
end
what is the rails best practice way of doing this? Do I need to implement a "tagged_with" action and create a helper or is there some rails routing magic that can sort this out in a jiffy?
EDIT: Eventually found the answer
Try adding something like this to your routes (untested):
match '/articles/tagged/:tagged_with' => 'articles#index', :as => :tagged_articles
Then:
link_to(tag, tagged_articles_path(:tagged_with=>"foobar"))
I found the answer eventually: I needed a "named route". If anyone else has this question, I just put this in my routes.rb file;
match "/articles/tagged_with/:tag" => "articles#index", :as => "articles_tagged_with"
then simply relpaced my "link_to" with this;
<%= link_to tag, articles_tagged_with_path(:tag => tag) %>,

Resources