Rails route, show all elements on the same page - ruby

I need to show all my elements on the same page.
In routes:
namespace :nourishment do
resources :diets do
resources :nourishment_meals, :controller => 'meals'
get 'nourishment_meals/show_all_meals' => 'meals#show_all_meals', as: "show_all_meals"
end
end
which will generate:
nourishment_diet_nourishment_meals_path GET /nourishment/diets/:diet_id/nourishment_meals(.:format) nourishment/meals#index
POST /nourishment/diets/:diet_id/nourishment_meals(.:format) nourishment/meals#create
new_nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/new(.:format) nourishment/meals#new
edit_nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/:id/edit(.:format) nourishment/meals#edit
nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#show
PATCH /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#update
PUT /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#update
DELETE /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#destroy
[**THIS**]
nourishment_diet_show_all_meals_path GET /nourishment/diets/:diet_id/nourishment_meals/show_all_meals(.:format) nourishment/meals#show_all_meals
The problem, when I do this:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path, :class=>"button green" %>
This error raise:
Problem:
Problem:
Document(s) not found for class NourishmentMeal with id(s) show_all_meals.
Summary:
When calling NourishmentMeal.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): show_all_meals ... (1 total) and the following ids were not found: show_all_meals.
Resolution:
Search for an id that is in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error when searching for a single id, or only the matched documents when searching for multiples.
The error is here, on my meals_controller.rb
private
# Use callbacks to share common setup or constraints between actions.
def set_nourishment_meal
#nourishment_diet = NourishmentDiet.find(params[:diet_id])
[***HERE***] #nourishment_meal = #nourishment_diet.meals.find(params[:id])
end
Method:
def show_all_meals
puts "This word does not appear"
end
Can someone help me?

The route below expects a :diet_id. A diet instance has to be provided as an argument for this path to call corresponding action.
nourishment_diet_show_all_meals_path GET /nourishment/diets/:diet_id/nourishment_meals/show_all_meals(.:format) nourishment/meals#show_all_meals
This should be changed:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path, :class=>"button green" %>
to:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path(diet), :class=>"button green" %>
Notice the argument (diet) above.

I think you should pass diet_id parameter in params. You should try something like this: <%= link_to "Show all meals", nourishment_diet_show_all_meals_path(#diet.id), :class=>"button green" %>. #diet.id is just an example, use whatever works for your application.

Related

Capybara::Ambiguous match, found 2 elements matching xpath - Find 1st link

I'm having an index action where I list all blog posts
<% #posts.each do |post| %>
<div class="blog-post">
<h2 class="blog-post-title"><%= link_to post.title, post_path(post) %></h2>
<p><%= post.sort_description %></p>
<p class="blog-post-meta">
<%= link_to 'Read more', post_path(post) %>
</p>
</div>
<% end %>
In my test script, in order to access the show action and view a single post I have this
find(:xpath, "//a[#href='/posts/1']").click
# or click_link(href: post_path(post))
But when I try to run the test I get this error
Failure/Error: find(:xpath, "//a[#href='/posts/1']").click
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching xpath "//a[#href='/posts/1']"
as capybara finds two different links which go to same page (one on title and the "read more" link). Is there a way to tell capybara to use the first link that finds?
Since one of the links is in the title h2 you can use that to scope the find and remove the ambiguity
find(".blog-post-title > a[href=`#{post_path(post)}`]").click # always better to use post_path than hardcode the id
You could also do first(:link, href: post_path(post)).click but first (like all) has the disadvantage of not having waiting/retrying behavior so unless you're sure the page is fully loaded when called it's best to avoid it (or enable waiting/retrying on it by specifying one of the count options first(:link, href: post_path(post), minimum: 1).click).
If you need to click blog title links a lot you could also create a custom selector with something like
Capybara.add_selector(:title_link) do
css do |post|
".blog-post-title > a[href=`#{post_path(post)}`]"
end
end
which would then allow you to do
find(:title_link, post).click
You don't have to use xpath.
In your example, you should be able to use:
first('.blog-post-title > a').click

How to generate pages for each tag in nanoc

I am new to nanoc and I am still finding my around it. I am able to get my site ready, it looks good and functions good, too. But I need to have a tags area. I am able to achieve that with
<%= tags_for(post, params = {:base_url => "http://example.com/tag/"}) %>
But how do I generate pages for tag? So for instance there is a tag called "NFL", so every time a user clicks on it, he/she should be directed to http://example.com/tag/nfl with a list of articles that correspond with NFL.
I can setup a layout which will do that. But then what kind of logic should be I using? And also do I need to have a helper for this?
You can use a preprocess block in your Rules file in order to generate new items dynamically. Here’s an example of a preprocess block where a single new item is added:
preprocess do
items << Nanoc::Item.new(
"some content here",
{ :attributes => 'here', :awesomeness => 5000 },
"/identifier/of/this/item")
end
If you want pages for each tag, you need to collect all tags first. I’m doing this with a set because I do not want duplicates:
require 'set'
tags = Set.new
items.each do |item|
item[:tags].each { |t| tags.add(t.downcase) }
end
Lastly, loop over all tags and generate items for them:
tags.each do |tag|
items << Nanoc::Item.new(
"",
{ :tag => tag },
"/tags/#{tag}/")
end
Now, you can create a specific compilation rule for /tags/*/, so that it is rendered using a "tags" layout, which will take the value of the :tag attribute, find all items with this tag and show them in a list. That layout will look somewhat like this:
<h1><%= #item[:tag] %></h1>
<ul>
<% items_with_tag(#item[:tag]).each do |i| %>
<li><%= link_to i[:title], i %></li>
<% end %>
</ul>
And that, in broad strokes, should be what you want!

put haml tags inside link_to helper

is it possible to add html-content inside a link_to helper in HAML?
i tried this, but all i get is a syntax error:
= link_to "Other page", "path/to/page.html"
%span.icon Arrow
expected output:
Other Page<span class="icon">Arrow</span>
You should use block
= link_to "path/to/page.html" do
Other page
%span.icon Arrow
If anyone is still using Rails 2.x on a project, it looks like the accepted answer returns the block, thus duplicating the link in the markup. Very simple change: use - instead of =
- link_to "path/to/page.html" do
Other page
%span.icon Arrow
The simplest way to do it is by using html_safe or raw functions
= link_to 'Other Page<span class="icon"></span>'.html_safe, "path/to/page.html"
or using raw function (recommended)
= link_to raw('Other Page<span class="icon"></span>'), "path/to/page.html"
Simple as it can get !!
Don’t use html_safe method unless you’re sure your string isn’t nil. Instead use the raw() method, which wont raise an exception on nil.

Iterate Form fields

I have build a module to add translations for each standard topic. Theses topic got many standard options and you can translate it directly in page.
I got an issue with my form about the edit view.
When i display a translation it's repeat all value of the f.input :value each time he have one and i want it to display with the each of standard value.
The question is how i can iterate my input field :value in the form to display only once per standard value and not repeat all value translated by standard value.
when i want create a new one all workings fine. It's just about the iterate field who is repeated how many times he got a field in the table.
the gist for my code :
https://gist.github.com/266562670cd8dab28548
Change:
<%= #preference_topic.preference_topic_options.each_with_index do |option, index| %>
<%= f.fields_for option.preference_topic_option_translations.first, option do |translate_form| %>
to:
<%= #preference_topic.preference_topic_options.each_with_index do |option, index| %>
<%= f.fields_for option.preference_topic_option_translations.first || option.preference_topic_option_translations.build, option do |translate_form| %>

Rails 3 refactoring issue

The following view code generates a series of links with totals (as expected):
<% #jobs.group_by(&:employer_name).sort.each do |employer, jobs| %>
<%= link_to employer, jobs_path() %> <%= "(#{jobs.length})" %>
<% end %>
However, when I refactor the view's code and move the logic to a helper, the code doesn't work as expect.
view:
<%= employer_filter(#jobs_clone) %>
helper:
def employer_filter(jobs)
jobs.group_by(&:employer_name).sort.each do |employer,jobs|
link_to employer, jobs_path()
end
end
The following output is generated:
<Job:0x10342e628>#<Job:0x10342e588>#<Job:0x10342e2e0>Employer A#<Job:0x10342e1c8>Employer B#<Job:0x10342e0d8>Employer C#<Job:0x10342ded0>Employer D#
What am I not understanding? At first blush, the code seems to be equivalent.
In the first example, it is directly outputting to erb, in the second example it is returning the result of that method.
Try this:
def employer_filter(jobs)
employer_filter = ""
jobs.group_by(&:employer_name).sort.each do |employer,jobs|
employer_filter += link_to(employer, jobs_path())
end
employer_filter
end
Then call it like this in the view:
raw(employer_filter(jobs))
Also note the use of "raw". Once you move generation of a string out of the template you need to tell rails that you don't want it html escaped.
For extra credit, you could use the "inject" command instead of explicitly building the string, but I am lazy and wanted to give you what I know would work w/o testing.
This syntax worked as I hoped it would:
def employer_filter(jobs_clone)
jobs_clone.group_by(&:employer_name).sort.collect { |group,items|
link_to( group, jobs_path() ) + " (#{items.length})"
}.join(' | ').html_safe
end

Resources