I think I am deeply misunderstanding how to write instances.
Miniatures have_many Manufacturers through the Productions table.
On the miniatures show page I am trying to list all the manufacturers for the current miniature and have them link the Manufacturer show page. Like so:
<% #miniature.manufacturers.each do |manufacturer| %>
<%= link_to #miniature.manufacturer.name, manufacturer_path %>
<% end %>
Needless to say it does not work. It gives "undefined method `manufacturer'".
I have tried A LOT of different combinations to no avail. The following version puts all the manufacturers, rolled into one link, once for each manufacturer a miniature has, and links to /manufacturers. A big mess.
<% #miniature.manufacturers.each do |manufacturer| %>
<%= link_to #miniature.manufacturers.map(&:name).join(', '), manufacturer_path %>
<% end %>
I have been working on other things and hoping I would get the hang of this but I'm pretty sure it's something pretty fundamental about how I set up the instance.
If it's more likely something I need to add to the controller then I can add my controller code here. Any help much appreciated.
Does this work:
<% #miniature.manufacturers.each do |manufacturer| %>
<%= link_to manufacturer.name, manufacturer_path(manufacturer) %>
<% end %>
Related
I am building an application where n users can talk to each other (like a messaging application) in public. Because you might want to have a different bio for each talk you do (for example a discussion about me regarding Ruby on Rails would need a different bio than one about Psychology) I have a Spkr model which has a User and a Tlk. The below code successfully means that on the users profile page, for each instance of them being a Spkr, the Tlk, and it's participants is visible with each Spkr's image (so if a Tlk has three participants, then all three images will be visible).
The setup is such where the default image is the User's image, but the Spkr can also customise their image by uploading one as a Spkr. I am worried that I am loading the front end with too much computation. Right now everything works... so is it ok? Or should I be limiting the computation happening when building views?
Thank you
<% #user.spkrs.each do |spkr| %>
<%= link_to show_tlk_path(spkr.tlk) do %>
<h4><%= spkr.tlk.title %></h4>
<% spkr.tlk.spkrs.each do |speaker| %>
<div class="tlk-tlking-image spkr-image image-spkr-<%= spkr.id %>"
<% if speaker.image.present? %>
style="background-image: url(<%= rails_blob_url(speaker.image) %>)"
<% elsif speaker.user.image.present? %>
style="background-image: url(<%= rails_blob_url(speaker.user.image) %>)"
<% end %>
>
</div>
<p><%= speaker.name %></p>
<% end %>
<% end %>
<% end %>
It tends to be considered good practice to keep the view as free of 'back end' calculations as possible. These files are often worked on by front end developers who may not even know how to code ruby, so the less of it that is in the view the better. It's also just not where it belongs in rail's Model Controller View framework.
First of all the code you've put can be simplified to:
<% #user.spkrs.each do |spkr| %>
<%= link_to show_tlk_path(spkr.tlk) do %>
<h4><%= spkr.tlk.title %></h4>
<% spkr.tlk.spkrs.each do |speaker| %>
<div class="tlk-tlking-image spkr-image image-spkr-<%= spkr.id %>"
style="background-image: url(<%= rails_blob_url((speaker.image || speaker.user.image) %>)"
>
</div>
<p><%= speaker.name %></p>
<% end %>
<% end %>
<% end %>
But as you say, if you want to handle this in a more appropriate place, I'd add a method to the Speaker class:
# app/models/speaker.rb
class Speaker << ApplicationBase
def image_for_view
image || user.image
end
end
This will let you call speaker.image_for_view which I think reads nicely in the view file itself.
Along with the great answer let me just add something that might help you to make views more clear. Might not be relevant to your question directly but might help you to get some idea how you can make views beautiful.
The first thing to make views look good are helpers. Though rails provide helpers for every controller, helpers are global meaning it can be used anywhere in any views. So, global formatings should be done with helpers. Like if you want a date formatter that needs to be used in a lot of view files, you can create a helper called date_helper.rb in app/helpers and put you desired date formatting -
module DateHelper
def formatted_date(date)
date.strftime([%m/%d/%Y')
end
end
Next is what rails people like to call a Presenter pattern. This is helpful when you don't want some logic to be shared across all views. Some logic that doesn't feel like belongs in controller or model are put there to make views readable. Suppose you have a view like below which is a bit messy -
<p>
Post title: <%= post.title.gsub("forbidden word", "") %>
<%= link_to "Read post", post, class: "w-75 p-3 text-#{post.draft? ? "orange" : "green"} border-#{post.draft? ? "orange" : "green"}" %>
</p>
To make this more beautiful you can create a presenter class named post_presenter.rb which should reside in app/presenters and write some code like -
class PostPresenter
def initialize(post)
#post = post
end
def title_without_forbidden_words
#post.title.gsub("forbidden word", "")
end
def css_color
#post.draft? ? "orange" : "green"
end
end
and in the view -
<% presenter = PostPresenter.new(post) %>
<p>
Post title: <%= presenter.title_without_forbidden_words %>
<%= link_to "Read post", post, class: "w-75 p-3 text-#{presenter.css_color} border-#{presenter.css_color}" %>
</p>
Such way a view might be more clear and also it can be lifesaver for frontend developers. This are the best two methods I found till now that makes a rails view beautiful which I always try to use.
Examples are taken from rubyguides website. Thanks to them,
I'm developing an online course site using Ruby on Rails and bootstrap. I have a model for Courses and a model for Lessons. In the lesson controller show view I am not only showing the lesson page with video, discussion and notes but also a list of all the lessons belonging to the course. This is done by:
<%= #lessons.each do |lesson| %>
<%= link_to [lesson.course, lesson] do %>
<%= lesson.title %>
<% end %>
<% end %>
The user can, from the individual lesson page, pick the next lesson to watch.
Question:
The URL generated is: localhost:3000/courses/1/lessons/2 (I'll change this with Friendly Id gem later). I would like to show in the list of all lessons on the individual lesson page which lesson the user is watching right now. So basically maybe have something say "You are currently watching : Lesson with id 2" and have it in a different background color with some custom html. How can I have different HTML and CSS for the currently watching lesson in the all lessons list?
Thanks a lot in advance!
/Jacob
A simple way would be to add a conditional, in the case you have the current lesson available in a local variable or method current_lesson. Then it can look like this:
<%= #lessons.each do |lesson| %>
<% if lesson.id == current_lesson.id %>
... other html ...
<% else %>
<%= link_to [lesson.course, lesson] do %>
<%= lesson.title %>
<% end %>
<% end %>
<% end %>
I've just started using rails yesterday, so this is a kinda noob question
for example, a user is at www.example.com/name
and I want to make several links to www.example.com/name/:id
So I tried something like this:
<% #items.each do |item| %>
<%= link_to item.name, '/name' :id %>
<% end %>
I know, it was a complete guess on how I should write the code, but the restful code sends to a completely wrong link. How should I write this three lines?
Use the route helper:
<% #items.each do |item| %>
<%= link_to item.name, item_path(item) %>
<% end %>
ps: when you have a simple question like this one, take a look at this guide, you'll often find the answer.
Try
<%= link_to item.name, item_path(item) %>
item_path is a URL helper method which spits out the link to show a name.
URL helpers have the general form:
{action}_{class}_path({object or object_id})
If {action}_ is omitted, then the default action is assumed (normally show).
I'm making a form for an Order object, and the order has many Products, via a join table called OrderProducts. So, we've got something like this:
<% #order = Order.new %>
<% form_for #order do |f| %>
<% #products.each do |product| %>
... want to iterate over products here to build up "order[product_ids][]", with one checkbox per product
<% end %>
<% end %>
Usually for each product i would have a check_box_tag, saying
<%= check_box_tag "order[product_ids][]", product.id, #order.product_ids.include?(product.id) %>
But this, while working fine, always feels like a bit of a cop out. Is there a way i can do it with the f.check_box syntax? Important note - on the project in question I'm working in Rails 2.2.2, so a solution that works in rails 2 would be ideal.
Rails <= 2.x (original)
<% #products.each do |product| -%>
<% fields_for 'product[]' , product do |product_fields| -%>
[...]
<%= product_fields.check_box :id %>
<% end -%>
<% end -%>
Rails >= 3.x (updated)
<% #products.each do |product| -%>
<%= fields_for 'product[]' , product do |product_fields| -%>
[...]
<%= product_fields.check_box :id %>
<% end -%>
<% end -%>
I know the author was looking for version 2 answers, but this is the top hit for google and I though I would update:
One can do this ( I'm using 4.0, don't know how far back it goes ):
<%= form_for #order do |form| %>
<%= form.collection_check_boxes(:product_ids, Product.all, :id, :labeling_method ) %>
<% end %>
For more info: http://edgeapi.rubyonrails.org...
I've done a number of multi checkbox forms over the years and different Rails version. Rails has never provided any really clean way to do it, but the "cop out" solution you came up with is pretty good isn't it? It's one line, it's explicit, and as long as the list of products is reasonably short it will perform adequately.
To answer your specific question, f.check_box will never work for this. It's just short hand for the check_box_tag, but none of the semantics apply. If you want to go Rails native, the only possibility I think is to use nested attributes. Part of the problem is that there is not one obvious way for this type of thing to work. Rails core went through a lot of planning and feedback to come up with nested attributes as they exist, and though they seem a bit obtuse, they capture the most common use cases quite elegantly. But nested attributes were introduced in Rails 2.3, and besides they will introduce quite a bit of conceptual overhead for something which sounds like it doesn't need the complexity.
There are also some plugins that provide helpers for this, although I haven't used any in a long time (since Rails 2 era actually). My impression is that they too are overkill unless you have many forms that make use of this pattern.
In short, I think you should go ahead with your existing solution.
formastic gem
check_boxes option is very good to implement multiple checkboxes
like
f.input :yourcolumn, :as => :check_boxes, :collection => your_collection
I'm new to rails and am working on extending the functionality of my basic blog app. What I would like to do is create date-based navigation links. For example, I would like to have a list of links with the names of the months (as the links) and when you click on the month it shows you all the articles published in that month.
I'm struggling with how to best accomplish this.
Should I create a new Model / View / Controller for something like an ArticleArchive? Or is the solution more simple based on my needs?
I've searched the other posts in the community and none seemed to answer this. Any help with how to structure this and possibly implement is appreciated. Thanks!
Here's an example on approaching this, although in this I wanted to sort it by day. This is for your controller action:
def index
#article_days = Article.all.group_by{ |r| r.published_at }
end
To modify this to months, you'd want to do something like r.published_at.beginning_of_month in the example above and essentially group_by the name of the month.
In the view template:
<% #article_days.sort.each do |pub, articles| %>
<h3><%= pub.strftime('%e %A, %B %Y') %></h3>
<% for article in articles %>
<%= article.title %><br/>
<%= article.summary %>
<% end %>
<% end %>
There's a screencast on this as well.
UPDATE
OK - so you only want the names of the month appearing. Keep the instance variable we setup in your index action along with your other code (you probably have setup #articles = Article.all). Then where you want the links listed do:
<% #article_months.sort.each do |pub, articles| %>
<h3><%= pub.strftime('%B') %></h3>
<% for article in articles %>
<%= link_to "#{article.title}", article_path(article) %>
<% end %>
<% end %>