Rails: how are paths generated? - ruby-on-rails

In Rails 3, when a scaffold is generated for instance for a 'Category' the will be a categories_path (and a edit_category_path(#category), ...) used in the erb views.
This is not a variable that can be found anywhere and probably is generated. However in my case, for a different entity, Article, I first generated the model and then the controller. Now when I try output an articles_path, I get a
undefined method `articles_path' for #<#:0x000001019d1be0>
I cannot even use a <%= form_for(#article) do |f| %> as this generates the same error.
What am I supposed to do?
My routings are like this:
resources :categories do
resources :articles
end

The articles resource is within the categories scope, so the correct path to use would be category_articles_path(#category) or edit_category_articles_path(#category, #article). To do this for your form_for, try:
<%= form_for([#category, #article]) do |f| %>

As article lives in the category scope, you need to use category_articles_path.

Related

How do I create a form for an associated model?

I have a company model and a bank_account model.
company has_many bank_accounts and bank_account belongs_to company.
I have a route companies/:company_id/bank_accounts/new which generates a form:
<%= form_for #bank_account do |form| %>
(form elements here)
<% end %>
But when I get to that page, I get: undefined method bank_accounts_path
Here's my resource routes in routes.rb:
resources :companies do
resources :bank_accounts, module: :companies
end
and my nested bank_account_controller.rb in controllers/companies/
I need my form to post the entered data to the create action. Ruby should know this already right because I'm in the new action? But clearly it doesn't recognise the route.
Let me know if you need more information.
So I was changing a few things to match a similar model for company contacts. I knew these we're the same concept in my application so the same routing and form should work.
First I moved my nested bank_account_controller.rb out of companies and just placed it in app/controllers.
I moved all my bank_account views out of the nested bank_account folder inside views/companies to just app/views/bank_accounts.
I then removed the module companies from my routes.rb so I just had resources :bank_accounts within my companies resources.
Finally, I changed the form_for to: form_with (model: [#company, #bank_account], local: true) do |form| %>
Forms constantly trip me up as a somewhat newbie to RoR. I need to understand better what the difference is between for and with :)
You have nested resource, therefore you need
<%= form_for [#company, #bank_account] do |form| %>

NoMethodError for a method that exists

Well, i'm new to rails, but not new to the rails way and i've got an error that i dont know how to fix it.
I've created the controller and than the view.
Controller:
class ReclamacoesController < ApplicationController
def new
#reclamacao = Reclamacao.new
end
end
and than, the view under Views>controllerName>new.html.erb.
<%= form_for #reclamacao do |f| %>
<%= f.text_field :titulo %>
<% end %>
The model Reclamacao exist.
I've created the resource routes for it too.
resources :reclamacoes
So, when i access /reclamacoes/new an exception is thrown.
NoMethodError in Reclamacoes#new
undefined method `reclamacaos_path' for #<#<Class:0x00000001fc0660>:0x00000001fba850>
Extracted source (around line #1):
<%= form_for #reclamacao do |f| %>
<%= f.text_field :titulo %>
<% end %>
Rails.root: /home/ubuntu/workspace/aqueleprojetoprivate/medicos
Application Trace | Framework Trace | Full Trace
app/views/reclamacoes/new.html.erb:1:in `_app_views_reclamacoes_new_html_erb___3194888715597102324_16164860'
the routes:
reclamacoes GET /reclamacoes(.:format) reclamacoes#index
POST /reclamacoes(.:format) reclamacoes#create
new_reclamaco GET /reclamacoes/new(.:format) reclamacoes#new
edit_reclamaco GET /reclamacoes/:id/edit(.:format) reclamacoes#edit
reclamaco GET /reclamacoes/:id(.:format) reclamacoes#show
PATCH /reclamacoes/:id(.:format) reclamacoes#update
PUT /reclamacoes/:id(.:format) reclamacoes#update
DELETE /reclamacoes/:id(.:format) reclamacoes#destroy
What is wrong?
Rails is trying to automatically guess plurals. The problem is that your resource is reclamacao which Rails is turning into reclamacaos plural. But you have named it as reclamacoes
I suggest either changing names or instruct Rails to use better plurals. Here's a relevant article: How do I override rails naming conventions?
Take a look at the output from rake routes. You will notice a spelling error
reclamacoes GET /reclamacoes(.:format) reclamacoes#index
POST /reclamacoes(.:format) reclamacoes#create
new_reclamaco GET /reclamacoes/new(.:format) reclamacoes#new
edit_reclamaco GET /reclamacoes/:id/edit(.:format) reclamacoes#edit
reclamaco GET /reclamacoes/:id(.:format) reclamacoes#show
PATCH /reclamacoes/:id(.:format) reclamacoes#update
PUT /reclamacoes/:id(.:format) reclamacoes#update
DELETE /reclamacoes/:id(.:format) reclamacoes#destroy
Based on the above output, the correct path name is reclamacoes path.
Rails emphasizes Convention over Configuration, and you have different spellings in your models, views and controllers.

Rails Undefined Method Path for New

I am relatively new to rails but having a real problem with something that I know should be really simple. I have a model called channel, in it I have a simple new method, in the view I have form but every time I try and load it, I get an error to say:
undefined method `channels_path'
My view (new.html.erb) is really simple, for the minute it just has a button in it with a name and a value, it just looks like this:
<%= simple_form_for #channel do |f| %>
<%= f.error_notification %>
<%= f.button :submit, 'Free Plan', name: 'plan', value: 'free' %>
<% end %>
My Controller has:
def new
#channel = Channel.new
end
And in my routes I have:
resources :channel
Output form a rake routes is:
channel_index GET /channel(.:format) channel#index
POST /channel(.:format) channel#create
new_channel GET /channel/new(.:format) channel#new
edit_channel GET /channel/:id/edit(.:format) channel#edit
channel GET /channel/:id(.:format) channel#show
PATCH /channel/:id(.:format) channel#update
PUT /channel/:id(.:format) channel#update
DELETE /channel/:id(.:format) channel#destroy
Which all looks how I expect. But as the error says there is no channels_path, but as far as I am aware, there shouldn't be.
I am sure this is supposed to be really simple but I just cannot see what I am doing wrong. Can anybody help?
Many thanks
David
EDIT
I have updated the route to be:
resources :channels
I can now load the form, however I now get the error when trying to submit it:
param is missing or the value is empty: channel
Being caused by:
# only allow specific params
def channel_params
params.require(:channel).permit(:name,
:slug,
:description,
:plan,
:subscription_ends
)
end
I am assuming singular is correct here based on the model, but have tried plural too with no luck. Any more thoughts?
Many thanks
Edit
Got it working in the end, it appears you have to have at least one input in your form. I added an input for the name field and it started working.
Many thanks to everyone that commented
According to your rake task, the path should be
channel_path
If it's not working with the simple_form_for helper, it's probably because you should have set up your routes as resources: channels
UPDATE
The new bug is coming from nothing being received by the controller for :channel
Try adding a field like so
f.hidden_field :plan, :value => "free"

How can I create a Rails form that POSTs to this custom route?

I have this route...
match '/set_current_location/:contract_id' => 'contracts#set_current_location',
:as => :set_current_location
I've written the ContractsController#set_current_location action and tests and that's all working as expected.
I'm having trouble with the view code.
I understand that this isn't The Rails Way, but because of the underlying DB structure (which I didn't create and am not allowed to change), it would be best in this one special case to not base the form on a model at all.
So my question is, how can I create a non-model form that posts to that route?
This should work for you:
<%= form_tag(set_current_location_path(contract_id), method: :post) do %>
...
<% end %>

Ruby on Rails Passing Parameter In URL

This is probably a very simple fix but I've been unable to find an answer just yet.
My application has orders and tasks. Orders have many tasks. When a user clicks new task in the show order view, it passes the order.id:
<%= link_to "New Task", new_task_path(:order_id=> #order.id) %>
The url shows:
/tasks/new?order_id=1
I just don't know how to extract this and use it in my form? I have tried:
<%= f.text_field :order_id, :value => #order_id %>
But it's not working.
You can do:
<%= f.text_field :order_id, :value => params[:order_id] %>
Alternately, capture the value (with params) in the controller and assign it to #order_id there.
You are doing this wrong, which is a big deal in Rails where convention-over-configuration is such an important ideal.
If an order has many tasks, your route should look like this:
/orders/:order_id/tasks/new
And your routes should be configured thusly:
resources :orders do
resources :tasks
end
You should [almost] never find yourself passing around record ids in the query string. In fact, you should almost never find yourself using query strings at all in Rails.

Resources