I have a little problem of link.
I have 2 models nested, one Faqcategoryand Faq.
The route is
resources :faqcategories, :path => 'faqs' do
resources :faqs, :path => 'question'
end
I can display all the "faqcategories" at http://localhost:3000/faqs/
and all the faqcategory as "questions" at http://localhost:3000/faqs/8
But when I want to go on the show of the question at http://localhost:3000/faqs/8/question/1 , it sends me at http://localhost:3000/faqs/1/question/8
I have set up the view like that:
<% #faqs.each do |question| %>
<%= link_to question.title, faqcategory_faq_path(question), class: "btn btn-rose btn-round" %>
<% end %>
In the FaqcateroriesController the "show" is set up like that:
def show
#faqs = #faqcategory.faqs
end
How do you think I can solve that?
I have found the solution.
<% #faqcategory.faqs.each do |question| %>
<%= link_to question.title, faqcategory_faq_path(question.faqcategory_id, question), class: "btn btn-rose btn-round" %>
<% end %>
It was missing "question.faqcategory_id"
Related
I have Challenges containing Puns, and it is possible to vote on puns. On the Challenge Show page, all puns are rendered and show their votes count. This is currently on the view page:
<%= render #challenge.puns.reverse %>
<br>
<div id="form">
<%= render "puns/form" %>
</div>
I want the puns form to appear above the items (puns) already submitted. But if swap them around, like this:
<div id="form">
<%= render "puns/form" %>
</div>
<%= render #challenge.puns.reverse %>
I get a controller error and pun.id is not suddenly not available and the voting link breaks.
No route matches {:action=>"upvote", :challenge_id=>"9", :controller=>"puns", :id=>nil}, missing required keys: [:id]
Here is the puns/form part that is causing the issue
<% if signed_in? %>
<% if current_user.voted_for? pun %>
<%= pun.votes_for.size %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% else %>
<%= link_to like_challenge_pun_path(#challenge, pun.id), method: :put do %>
<span class="heart_like">❤</span> <%= pun.votes_for.size %>
<% end %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% end %>
<% end %>
It is the like_challenge_pun_path that throws an error but I cannot understand why. I am declaring #challenge again here, so it should be able to get the id.
Here is the form for the puns:
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
<span class=".emoji-picker-container">
<%= f.text_area :pun_text, placeholder: "Add pun", data: { emojiable: true } %>
</span>
<%= f.submit %>
<% end %>
Also, here is my routes setup
resources :challenges do
resources :puns do
member do
put "like", to: "puns#upvote"
put "dislike", to: "puns#downvote"
end
end
end
and the corresponding action to upvote
def upvote
#pun = #challenge.puns.find(params[:id])
#pun.upvote_by current_user
redirect_to #challenge
end
Can anyone help?
I think the code is for the puns collection.
I assume the issue is that in the form you have something like:
#challenge.puns.build
So in #challenge.puns collection appears not persisted record (without id), so path for this model cannot be generated.
As a quick solution I suggest:
<%= render #challenge.puns.reverse.select(&:persisted?) %>
UPDATE:
As I assumed you have
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
You can also try:
<%= form_for([#challenge, Pun.new]) do |f| %>
Or solve it in the controller. But need to see controller code for it.
I'm a real newbie at Ruby and Rails, and I've been looking for the solution for two days. I need to submit data from form_tag to action 'create' in my controller to add new entries to database, but looks like I'm doing something terribly wrong, because absolutely nothing happens, and it seems that form_tag doesn't even redirect to needed action.
Here's the page code:
<h1>Todos</h1>
<% #projects.each do |project| %>
<tr>
<h2><%= project.title %></h2>
<% project.todos.each do |todo| %>
<ul style="list-style-type:disc">
<li><%= todo.text %></li>
</ul>
<% end %>
</tr>
<% end %>
<%= form_tag({controller: "mega", action: "create"}, method: "get", remote: true) do %>
<h2>New todo</h2>
<p>
<%= text_field_tag 'text' %>
</p>
<p>
<%= select_tag 'title', options_from_collection_for_select(#projects, 'id', 'title') %>
</p>
<p>
<%= link_to 'CANCEL' %>
<%= link_to 'OK', "", :onclick => "$('#form_id').submit()" %>
</p>
<% end %>
And the controller:
class MegaController < ApplicationController
def index
#projects = Project.all
#todos = Todo.all
end
def update
end
def create
#newTodo = Todo.create(text: params[:text])
#newProject = Project.find_by(title: params[:title])
#newProject.todos << #todo
#newTodo.save
end
end
My routes file. I seriously don't know how it works:
Rails.application.routes.draw do
get 'mega/index'
root 'mega#index'
get 'mega/update'
post 'mega/create'
resources :todos
resources :projects
end
You create resources with a POST request. Never GET.
GET requests should be idempotent - they should not update or alter resources on the server. One very important reason is that they are stored in the browser's history, so pressing the back button will cause unintended consequences for the user.
In Rails flavor MVC instead of tacking the action name on the path of the route you use the HTTP verb to create routes to the correct action:
GET /things things#index
POST /things things#create
I'm not going to attempt to salvage your code (it's deeply flawed) and instead show you how you would solve this the rails way as it is much simpler:
<%= form_for(Todo.new) do |f| %>
<h2>New todo</h2>
<%= f.text_field :text %>
<%= f.collection_select(:project_id, #projects, :id, :title, prompt: true) %>
<%= f.submit %>
<% end %>
This would submit to todos#create - if you want to route it to an unconventional action you can use the url option:
<%= form_for(Todo.new, url: polymorphic_path(controller: 'foo', action: 'bar')) do |f| %>
It's best to learn the rules before you break them.
I have referenced these 2 stackoverflow posts, but i can't seem to get q[categories_name_cont] to be populated with "CategoryName" in my url: /articles/browse?utf8=✓&q[categories_name_cont]=&commit=CategoryName after i click the button named "CategoryName" for example.
1) Rails filter with button or link_to using Ransack
2) How to construct a clickable link with a scope using Ransack and Rails
browse.html.erb
<% #categories.each do |category| %>
<%= search_form_for #q, url: browse_articles_path, method: :get do |f| %>
<%= f.hidden_field :categories_name_cont %>
<%= f.submit category.name, :class => 'btn btn-primary', :onclick => "document.getElementById('q_categories_name_cont').value = '#{category.name}'" %>
<% end %>
<% end %>
articles_controller.rb
def browse
#q = Article.ransack(params[:q])
#articles = #q.result.includes(:categories, :users)
#categories = Category.with_articles.order('name ASC').all
end
UPDATE:
1) Hardcoding document.getElementById('q_categories_name_cont').value = "CategoryName" didn't result in this url either..
/articles/browse?utf8=✓&q[categories_name_cont]=CategoryName after i click the button named "CategoryName"
2) I ended up using the below method to pass parameters to the url:
<% #categories.each do |category| %>
<a class="btn btn-large btn-primary" href="/articles/browse?utf8=✓&q[categories_name_cont]=<%= category.name %>">
</a>
<% end %>
You need to manually fill that in.
<%= f.hidden_field :categories_name_cont, params[:q].try(:[], :categories_name_cont) %>
It can get quite annoying though. For this reason I have actually written a small gem for doing this automatically together with SimpleForm. If you want to take a look, then you can find it here:
https://github.com/kaspernj/simple_form_ransack
I've spent a few days on this and just haven't been able to get my head around how to apply a scope or other method to this. I've also tried some search gems but because I'm at such a basic level, wanted to keep things as simple as possible. The effort below is loosely based on rails casts #37 "simple search" tutorial. Its the only one that's been marginally successful.
My problem; I want to run a search on year, make, model, engine(if any), drilling down to the desired vehicle(s). To make things easy on me, I did one search per page. Currently I'm not able to carry the previous search params over to the current search. I'm sure there are better ways of doing this than the one below, and I'm open to suggestions. I just haven't been able to successfully adapt examples I've found online.
The Database:
I have a postgres database table named "carinfo", that table has columns "id, caryear, carmake, carmodel, carengine, submodel, website1, website2, website3". I've populated it with some test data with a dozen or so vehicles.
controllers/listing_controller.rb
To simplify things I haven't used a model yet so its all in the controller:
class ListingController < ApplicationController
include ListingHelper
def year
#searchyr = Carinfo.find(:all)
end
def make
#searchmk = Carinfo.find(:all, :conditions => ['caryear LIKE ?', "%#{params[:year]}%"])
end
def model
#searchmdl = Carinfo.find(:all, :conditions => ['caryear LIKE ? AND carmake LIKE ?', "%#{params[:year]}%", "%#{params[:make]}%"] )
# '%2009%' static values work ok
end
def engine
#searcheng = Carinfo.find(:all, :conditions => ['caryear LIKE ? AND carmake LIKE ? AND carmodel LIKE ?', "%#{params[:year]}%", "%#{params[:make]}%", "%#{params[:model]}%"])
end
def selectedcar
#searchres = Carinfo.find(:all, :conditions => ['caryear LIKE ? AND carmake LIKE ? AND carmodel LIKE ? AND carengine LIKE ?', "%#{params[:year]}%", "%#{params[:make]}%", "%#{params[:model]}%","%#{params[:engine]}%"])
end
end
views/listing/year.html.erb
<% provide(:title, "Year") %>
<h1>Year Search - Under: Listing</h1>
<%= form_tag(make_path, :method => "get") do %>
<%= select_tag :year, options_for_select(#searchyr.collect{|y| [y.caryear, y.caryear]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<!-- this can be deleted once everything is working it just helps see what's filtered -->
<ul>
<% for search in #searchyr %>
<li>
<%= search.caryear %>
<%= search.carmake %>
<%= search.carmodel %>
</li>
<% end %>
</ul>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/make.html.erb
<% provide(:title, "Make Search") %>
<h1>Make Search - Under: Listing</h1>
<%= form_tag(model_path, :method => "get") do %>
<%= select_tag :make, options_for_select(#searchmk.collect{|y| [y.carmake, y.carmake]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/model.html.erb
<% provide(:title, "Model Search") %>
<h1>Model Search - Under: Listing</h1>
<%= form_tag(engine_path, :method => "get") do %>
<%= select_tag :model, options_for_select(#searchmdl.collect{|y| [y.carmodel, y.carmodel]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/model.html.erb
<% provide(:title, "Engine Search") %>
<h1>Engine Search - Under: Listing</h1>
<%= form_tag(selectedcar_path, :method => "get") do %>
<%= select_tag :engine, options_for_select(#searcheng.collect{|y| [y.carengine, y.carengine]}.uniq), {:onchange => 'this.form.submit()'} %>
<% end %>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
views/listing/selectedcar.html.erb
<% provide(:title, "Selected Car") %>
<h1>Selected Car - Under: Listing</h1>
<center><%= button_to "Reset Search", year_path, class: "btn btn-large btn-primary" %></center>
<ul>
<% for search in #searchres %>
<li>
<%= search.caryear %>
<%= search.carmake %>
<%= link_to search.carmodel, search_path(search) %>
</li>
<% end %>
</ul>
config/routes.rb
Just the section dealing with this problem:
match '/year', to: 'listing#year'
match '/make', to: 'listing#make'
match '/model', to: 'listing#model'
match '/engine', to: 'listing#engine'
match '/selectedcar', to: 'listing#selectedcar'
As always, help is greatly appreciated.
Thanks
Mike
First off, you're controller doesn't need all of those methods, do something like this:
class ListingController < ApplicationController
include ListingHelper
def search
#search = Carinfo.where('caryear LIKE ?', params[:year]) unless params[:year].blank?
#search = #search.where('carmake LIKE ?', params[:make]) unless params[:make].blank?
etc etc...
end
end
Then just have one form that has all of the inputs that you'd like to search
I'm trying to get an admin interface working in Rails, but I'm having trouble using link_to with the nested routes. I'm trying to get a link to /admin/cake_class/:id but it's sending me to admin/cake_class.:id instead.
config/routes.rb:
namespace :admin do
resources :cake_class
end
/app/views/admin/cake_class/index.html.erb
<h1>all classes</h1>
<% #classes.each do |c| %>
<%= c.date %>
<%= c.name %>
<%= link_to 'Show', admin_cake_class_path(c) %>
<% end %>
Any suggestions?
The :resources should be plural, :cake_classes, which could be tripping you up.
What does the output of rake routes show?