Understanding Haml Code - ruby-on-rails

I am currently working with a RoR project where my team is using Haml as a templating engine. I have difficulty understanding the following code.
%td
= link_to 'Edit', [:edit, :merchants, category, subcategory], class: 'btn'
= link_to 'Delete', [:merchants, category, subcategory], :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn'
Which translate into html as
<a class="btn" href="/admin/categories/28/sub_categories/147/edit">Edit</a>
<a class="btn" data-confirm="Are you sure?" data-method="delete" href="/admin/categories/28/sub_categories/147" rel="nofollow">Delete</a>
From Haml documentation, I found out that [] notation used for object reference so I am not sure how the [ ] notation translated into href notation. I am pretty new to both Ruby On Rails and Haml, so any help will be appreciated.

It nothing about the Haml. It is a Rails helper what's builds some_awesome_path from arrays of :symbol and variables.
Internally, Rails will convert [:edit, :merchants, category, subcategory] to a call to merchants_category_subcategory_path. Most (if not all) Rails methods that expect a path will also take an object representation of your resource, like respond_with, link_to, render, redirect_to, form_for, etc.
Some example:
This array:
[:new, #object, :post]
Translate to:
new_businesses_post_path() and new_businesses_post_url()
Creating URLs From Objects

In Rails we have two ways to build pathes
by *_path methods
by polymorphic pathes http://api.rubyonrails.org/classes/ActionDispatch/Routing/PolymorphicRoutes.html#method-i-polymorphic_url
Also some methods (form_for, link_to) not requires to call polymorpic_path and able to take array directly.

Related

:method put: not working instead Get method

So I am trying to use the following route:
<%= link_to like_post_path(#post), :method => :put do %>
But I don't know why is using GET method instead of PUT
No route matches [GET] "/posts/1/like"
makes no sense to me..
myroutes.rb:
resources :posts do
member do
put "like" => "posts#upvote"
put "dislike" => "posts#downvote"
end
You are using correct format and your code is should generate something like this:
<a data-method="put" href="...">
From your routes error message we can conclude that it is not being sent using POST with _method=put params. So, the problem must be that you did not include jQuery and Rails jQuery extension javascript files.
An easy fix would be to include application.js file (jquery and rails js extension are included by default) in your page.
link_to signature :
link_to(name = nil, options = nil, html_options = nil, &block)
According to the doc, :method belongs to the options hash.
calling
<%= link_to like_post_path(#post), :method => :put do %>
results in putting into
name : like_post_path(#post),
options: nil,
html_options: { method: :put }
From Hash
Hashes are also commonly used as a way to have named parameters in functions. Note that no brackets are used below. If a hash is the last argument on a method call, no braces are needed, thus creating a really clean interface:
EDIT
<%= link_to like_post_path(#post), { method: :put } do %>
leads to what you are trying to achieve.

Methods with link_to In ruby tags (ruby on rails)

I am working on a Ruby on Rails project, and I noticed that the link_to can either work with or without a method specified.
With the method specified:
<%= link_to "Log In", new_user_session_path, class: 'btn btn-primary navbar btn', method: :get %>
Without the method specified:
<%= link_to "About", about_path, class: 'navbar-brand' %>
How do I know when should I use a method with link_to, and when I should not?
From my understanding, you should use method when it's different from get. Eg, I specify it when I need to use post and so on.
It tells the browser which HTTP method to use when submitting the request to the web server. Supported verbs are :post, :get, :delete, :patch, and :put.
You can always specify it if you want to be explicit, otherwise it's only necessary when you need it to deviate from the default. Different functions have different defaults.
button_to defaults to :post
link_to defaults to :get
etc.
This link has many examples and a more thorough explanation:
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html

Rails, destroy link NoMethodError

I have the following list of items:
= #kid.educations.each do |education|
= education.studies_centre
= _('-')
= education.city_and_country
= link_to _("<i class='fa fa-times-circle a-lg'></i> delete").html_safe, education, :confirm => 'Are you sure?',:method => :delete, class: "btn btn-danger btn-xs pull-right"
%br
%small
= education.academic_qualification
%hr
%br
As you can see, I have a delete option, but I does not work. I get:
undefined method `education_path' for #<#<Class:0x007fd00c61c270>:0x007fd00cdd5b88>
What I'm doing wrong.
Thanks for your help
UPDATE ROUTES
dashboard_kid_educations GET /dashboard/kids/:kid_id/educations(.:format) dashboard/educations#index
POST /dashboard/kids/:kid_id/educations(.:format) dashboard/educations#create
new_dashboard_kid_education GET /dashboard/kids/:kid_id/educations/new(.:format) dashboard/educations#new
edit_dashboard_kid_education GET /dashboard/kids/:kid_id/educations/:id/edit(.:format) dashboard/educations#edit
dashboard_kid_education GET /dashboard/kids/:kid_id/educations/:id(.:format) dashboard/educations#show
PUT /dashboard/kids/:kid_id/educations/:id(.:format) dashboard/educations#update
DELETE /dashboard/kids/:kid_id/educations/:id(.:format) dashboard/educations#destroy
You're using namespaced nested resources, so your link should be like this:
= link_to _("<i class='fa fa-times-circle a-lg'></i> delete").html_safe, [:dashboard, #kid, education], :confirm => 'Are you sure?',:method => :delete, class: "btn btn-danger btn-xs pull-right"
If you using nested resources you should pass 2 arguments to path helper. And I think it's better to use block to improve code readability
= link_to dashboard_kid_education_path(#kid, education), confirm: 'Are you sure?', method: :delete, class: 'btn btn-danger btn-xs pull-right' do
%i.fa.fa-times-circle.a-lg
= 'delete'
Nested Routes
Something to add to Marek's answer is the idea of nested routes
Essentially, when you define a nested route (like below), Rails does not instinctively know when you're calling this:
#config/routes.rb
resources :dashboard do
resources :education
end
The bottom line is that Rails will only call routes as they pertain to the model of the object you're calling. In your example, you call education (which is presumably built from Eduction.find())
To Rails, by passing this to your routes, you will essentially tell your application to find routes for the Education model only, hence why your error looks like this:
undefined method `education_path'
--
The way to fix this, as detailed by Marek is to ensure you are referencing the correct path in your <%= link_to %> call. To do this, you have to reference the nested route as described by Marek's solution

Rails button_to fails with path doesn't exist for a path that exists

Writing my first, very simple Rails application, a simple admin app to track work for one of our departments. The generated index page for people has a link_to on it to add a new person. I tried to change that to button_to and it fails saying the path /people/new doesn't exist, though obviously it does since link_to goes to the same place.
I'm using Rails 3/Ruby 1.9.2. I have this code on my /app/views/people/index.html.erb page:
<%= link_to 'New Person', new_person_path %>
<%= button_to "New", :controller => "people", :action => "new" %>
The link_to works. The button_to fails with this:
Routing Error
No route matches "/people/new"
Also tried just
<%= button_to 'New Person', new_person_path %>
Same error. Odd.
button_to defaults to the post method. Try putting :method => :get in there. This is why link_to works.
There's a good explanation for this, as always :)
link_to uses GET as default, where button_to uses POST. And there's no POST route that matches, only a GET route.
If you want to use button_to, you can add :method => :get to your buttons params and it will use GET.
Did you set up your routing options in config/routes.rb? Check if you have this in your routes.rb file:
resources :people
Check this guide for more informations about how routes work.
Is your button_to inside a form? button_to creates a form of its own so this would create a form within a form and likely break routing.

what is the right 'rails' way to add a link_to a new custom method

We're adding a new method 'delete_stuff' to the WidgetsController of a scaffolded app.
in routes we added
match 'widget/delete_stuff/:id' => 'widgets#delete_stuff'
I CAN manually create html (GET) links like
My Custom Delete Stuff
But that's bad on so many levels (uses GET instead of DELETE, doesn't permit a CONFIRM dialog, isnt DRY, etc)
Problem is I can't figure out how to use the url helpers for a custom method... trying to do something like this:
<% link_to 'DeleteStuff', #widget, :confirm => 'Are you sure?', :method => :delete %>
But that just gets ignored when the html is rendered.
I'm clearly missing something fundamental on how to use link_to, any help will be appreciated!
Cheers,
JP
Looks like you're missing an equals sign at the beginning. It should read:
<%= link_to 'DeleteStuff', #widget, :confirm => 'Are you sure?', :method => :delete %>
to solve your routing and make your additional action a delete method try this;
in routes.rb
resources :widgets do
member do
delete 'delete_stuff'
end
end
First run rake routes to know what URL helpers are available to you. You may see a line beginning with:
delete_stuff_widget
You can then append path or url to get the name you should use in your views and controllers. I suspect your new link_to will look like:
link_to "DeleteStuff", delete_stuff_widget_path(#widget), :confirm => "Sure?", :method => :delete

Resources