<h1>Listing categories</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Thumburl</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #categories.each do |category| %>
<tr>
<td><%= category.name %></td>
<td><%= category.thumburl %></td>
<td><%= link_to 'Show', category_path(category) %></td>
<td><%= link_to 'Edit', edit_category_path(category) %></td>
<td><%= link_to 'Destroy', category, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'New Category', new_category_path %>
So, as I said in my last post, I'm trying to go through Ruby code as I find it on Codecademy's RoR tutorial. Since they have such a straightforward tutorial, I figure it would be ridiculous to not understand everything they throw at me.
In this bit, they have an html.erb file that is supposed to form a tabled-view. Everything seems clear to me until they get to <tbody>.
Here, first, we are iterating on an instance variable #categories...now, where this instance variable is found, I don't know. I thought instance variables meant they could only be used within a particular class, yet this is a markup page, i.e. no classes have been defined, so how does Ruby know where or what this instance variable is?
Next: so, as I understand it, the word 'category', here, is serving as a variable because it was specified as such by pipe syntax two lines earlier. Now, whether this variable can be used beyond this html.erb page is beyond me, cause I thought instance variables were denoted with an '#.' With this variable, we call the method 'name'. So, is 'name' a custom method, and if so, where is it defined?
Now, the third <td> tag contains code that tells Ruby to link to some name 'Show,' yet I'm not sure what this name points to...also, 'category_path' is a method we defined in our routes.rb file, and it has the parameter of our blocked variable 'category.'
Lastly, the final row cell links to some name 'Destroy,' but this comma syntax is something I haven't seen before:
<td><%= link_to 'Destroy', category, method: :delete, data: { confirm: 'Are you sure?' } %></td>
The instance variable #categories should be defined in CategoriesController, which is a subclass of action controller. Ruby's instance variables are not persistent, and any #variables you defined in a controller action is accessible in the action's view. I am not sure if you are familiar with MVC patterns, and if not, you can take a look at this question:
What is MVC in Ruby on Rails?
Name is an attribute of the resource/model category. You should see its class in app/model/category.rb. It is a subclass of ActiveRecord, which acts as a wrapper of the database of your choice. So you probably have a database table called categories with column name 'name'.
And as #JoelL mentioned, the link_to are view helpers that are meant to simplify your syntax in view files,make your code more organized, and save you time. You can define your own view helpers in app/helpers. Some of the helpers are automatically made for you when you define a resources :resource_name in config/routes.rb. In this case, you probably have resources :categories in your config/routes.rb
Related
Using Rails' resources directive, I have created a set of routes for a controller (contacts). I'm now editing the default views they come with to include some of my own content. However, the link_to method is failing, telling me that I'm missing a required parameter.
No route matches {:action => 'show', :controller => 'contacts', :id => nil} missing required keys [:id]
It's obvious why this is happening - the link_to method is not being supplied with an ID, instead it's getting nil. However, the code I'm using matches the documentation for link_to.
This is the view in question:
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.first %></td>
<td><%= contact.last %></td>
<td><%= contact.title %></td>
<td><%= contact.city %></td>
<td><%= contact.phone %></td>
<td><%= contact.email %></td>
<td><%= link_to 'Show', contact %></td>
<td><%= link_to 'Edit', edit_contact_path(contact) %></td>
<td><%= link_to 'Delete', contact.id, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
#contacts is a set of contacts returned from the controller. The line that sets that is:
#contacts = Contact.select("title, first, last, city, phone, email")
.where("created_by" => #current_user.id)
The relevant content of the routes.rb file is simply resources :contacts.
The documentation states:
Because it relies on url_for, link_to supports both older-style controller/action/id arguments and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base your application on resources and use [...]
link_to "Profile", #profile
This appears to be what I'm using with link_to 'Show', contact.
Why is the ID not getting passed to link_to?
What can I do to remedy this?
Change
Contact.select("title, first, last, city, phone, email")
to
Contact.select("title, first, last, city, phone, email, id")
the contact's id is nil because it isn't in the select query.
Also, although it doesn't seem to be causing problems right now, I would reccomend using an array of symbols instead of a comma-separated string, so that the sql query is more specific. For example:
Contact.select("title, first").to_sql #=> SELECT title, first FROM contacts
Contact.select(:title,:first).to_sql #=> SELECT "contacts"."title", "contacts"."first" FROM contacts
This way if you do a join with another model, it won't complain about the unspecific id in select. If you feel like you're typing too much, you can use the %i(...) syntax:
Contact.select(*%i(title first last city phone email))
Your code seems fine.
Maybe you have an instance in the #contacts array that is not saved and therefore, has no id?
Another way to put the same (again, your code is fine) would be:
= link_to 'Show', contact_path(contact)
I would suggest posting the routes file.
I followed the "Getting Started" tutorial at http://guides.rubyonrails.org/getting_started.html, and wanted to change what is output on the articles index page.
rather than showing the text of the article in the main table, I want to see the most recent comment made on that article.
Here is the code for the index:
<tr>
<td><%= article.title %></td>
<td><%= article.comments.select(:body).last %></td>
<td><%= link_to 'Show', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
Where 'article.comments.select(:body).last' is meant to show the body of the latest comment made on the article in question (this table iterates for every article).
Instead of seeing the text from the comment however, I see this:
{Comment:0x44f9ec8} (with sharp brackets instead of curly - wont let me post the sharp ones.... <>)
I also tried editing comment.create in the comments_controller with:
#article.text = #comment.body
After setting the index table field to 'article.text' (which works fine), but with no effect.
Anyone have any idea what I'm doing wrong??
Any help is much appreciated.
article.comments.select(:body).last does not do what you expect
the select part uses this select which alters the SQL command you use. It forces selecting only the body field from comments and returns a comment object.
so you need to change your code to article.comments.select(:body).last.body
If you need to have all the body fields and just use one, I suggest that you use pluck if you are on rails > 3.2
article.comments.pluck(:body).last
I have created a partial for a LineItem that, in my case, emits a <tr> with a couple of <td>s. This works just fine and dandy.
What I'd want to do then, is use the same partial in different places. The original view has plenty of room, so displaying every cell is ok. But another (a sidebar), has much less space, and I'd only want to display two of the 5 cells.
So the question, then, is what is the correct way of implementing this? I'd like for the "full" version to be the default unless otherwise specified, and only use the limited version if a parameter is passed.
Currently I'd probably use the feature of passing locals to a partial and check if a parameter limited is defined, and if so, skip the last N cells. Am I on a right track, and if so, what kind of a variable should I use (can I use symbols for this)?
Current _line_item.html.erb (that I'm somewhat unhappy with)
<tr>
<td><%= line_item.quantity %>×</td>
<td><%= line_item.product.title %></td>
<td class="item_price"><%= number_to_currency(line_item.total_price, unit: '€') %></td>
<% unless defined? limited %>
<td class="remove_item"><%= button_to 'Remove', line_item, method: :delete %></td>
<% end %>
</tr>
Edit: Added current version.
Yes, you are on the right track. You can do something like
<%= render 'partial_name', limited: true %>
and then in the partial:
<% limited ||= false %> # More explicit as to what default value is
<tr>
<td><%= line_item.quantity %>×</td>
<td><%= line_item.product.title %></td>
<td class="item_price"><%= number_to_currency(line_item.total_price, unit: '€') %></td>
<% unless limited %>
<td class="remove_item"><%= button_to 'Remove', line_item, method: :delete %></td>
<% end %>
</tr>
I'm still new to Rails, and can't seem to wrap my head around this.
I have table showing of several Products with several attributes in form columns. In my index view I'm showing a shortened table, with just some of the columns. In my products#show I'm telling the full story, but obviously only for the selected Product. What I want to do, is letting users select a number of Products in products#index, and then store the selected IDs in a hash, sending them to another view, which I want the IDs to be presented in a full scale table, telling the whole story, of several products at once. Basically this is for comparing Products.
I'm not sure how to tackle this. As I'm already using DataTables, using javascript would make sense, but I'm unsure on how. And ideas? I've tried several ideas, but none of them got me anywhere.
products#index
<table id="products"cellpadding="0" cellspacing="0" border="0" class="table.responsive">
<thead>
<tr>
<th></th>
<th>Product Name</th>
<th>TG</th>
<th>TD</th>
<th>DK</th>
<th>DF</th>
<th>T260</th>
<th>T288</th>
<th>CTI</th>
<th>Strength</th>
<th>Rigidity</th>
<th>Standards</th>
<th>Manufactorer</th>
</tr>
</thead>
<tbody>
<% #products.each do |product| %>
<tr>
<td><%= check_box_tag "product_ids[]", product.id %></td>
<td><%= link_to product.name, product %></td>
<td><%= product.TG %></td>
<td><%= product.TD %></td>
<td><%= product.DK %></td>
<td><%= product.DF %></td>
<td><%= product.T260 %></td>
<td><%= product.T288 %></td>
<td><%= product.CTI %></td>
<td><%= product.ElectricStrength %></td>
<td><%= product.rigidity %></td>
<td><% product.standards.each do |standard| %>
<%= link_to standard.name, standard %>,
<% end %> </td>
<td><%= product.producer %></td>
<% end %>
</tr>
</tbody>
</table>
If anyone could spare some time to point me in the right direction, that would be wonderful!
This shouldn't be too tough to tackle, I'll walk you through the basic steps that I would take.
My basic approach would be to take a form of said checkboxes and submit it to an action designed to handle them in the way described, like so:
Create a new route to use for all of this. Take a look at 2.10.2 Adding Collection Routes in the docs (assuming you are using resources). Maybe call it something like "compare".
Use a form not backed by a model to hold your checkboxes and labels (1 of each for each product) - it should post to your new route.
In your controller, add the action for your route. This action should fetch the ids passed in by the form from the params and load the relevant products (remember that find can take an array of ids, so it should be pretty easy).
Finally, add a view for your new action, with the relevant logic to present your comparison.
You can easily come in an backfill this with javascript, but it is not required. Honestly, it would be more useful for adding a little extra panache, like disabling the button and showing a spinner, or something, than a full-on javascript submission, which doesn't really buy you anything in this particular case.
Learning Ruby and Rails. In following the getting started guide if I invoke
rails generate scaffold Post name:string title:string content:text
it generates among other things code like the following in index.html.erb:
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.title %></td>
<td><%= post.content %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
My only concern in the above is edit_post_path, and my question is, what is it - and specifically from a Ruby standpoint. It certainly has every appearance of being a Ruby method, and its embedded in other code which is most definitely Ruby: posts.each do |post|...end that's all Ruby
But if edit_post_path is a Ruby method, where is the code for it? 'post' is a label I have provided to Rails, so presumably this Ruby method should be somewhere in my site directory along with other Ruby code generated when invoking "rails generate scaffold..." above (i.e. it wouldn't be in a Rails-specific directory for example). But there is no such method 'edit_post_path' defined anywhere. So is it not really Ruby at all, just something contrived to look that way for some reason, and really just a string of text that is processed by something strictly proprietary to Rails. Is this an example of what is so cool about Rails?
That is a Rails helper method - aka sugar syntax as James pointed out - for routing within your app.
To see all the routes available to you, at the command line do rake routes. You will see a list of the helpers on the left, then you will see the HTTP operation in the second column, third column = URL path format, and last column is a breakdown of the controller and action that it relates to.
To see some of the Ruby code that is at the heart of this magic, check it out in the Rails 3 repo, like this: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb#L444
Also if you want to create custom URLs for specific resources, check out: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/url_for.rb
Here is some more info on routing in general: http://guides.rubyonrails.org/routing.html
Hope that helps.
It's "sugar"-syntax built into Rails. There are a ton of easy methods like this to speed up development.