Rails "NoMethodError" with sub-resources - ruby-on-rails

I'm a newbie Rails developer who is getting the following error when trying to access the 'new' action on my CityController:
undefined method `cities_path' for #<#<Class:0x104608c18>:0x104606f08>
Extracted source (around line #2):
1: <h1>New City</h1>
2: <%= form_for(#city) do |f| %>
3: <%= f.error_messages %>
4:
5: <div class="field">
As some background, I have a State model with many Cities. I'm getting this error after clicking on the following link coming from a State show page:
<p>Add a city: <%= link_to "Add city", new_state_city_path(#state) %></p>
When I run 'rake:routes' it says this is a legit route...
For more background, here is the CityController 'new' action:
def new
#city = City.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #city }
end
end
Here is the (complete) form in the view:
<%= form_for(#city) do |f| %>
<%= f.error_messages %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
This initially made me think that it's a resources/routes issue since it came back with a mention of 'cities_path' (in fact, that's what another person posting to Stack Overflow had wrong (Rails error "NoMethodError" - My first ruby app). However, that doesn't seem to be the case from what I can see. Here are how my resources look in my routes file:
resources :states do
resources :cities
end
I can get it working when they are not sub-resources, but I really need to keep them as sub-resources for my future plans with the app. Any help would be very much appreciated, since I've been racking my brains on this for more hours than I would care to admit... Thanks!
(Not sure this matters at all, but I'm running the very latest version of Rails 3 beta2).

Your problem is coming from line 2 of your view above, specifically the form_for declaration. As you pointed out, state_city_path is a valid path, but right now, your form is not using this path, it's using city_path. When using nested resources, you need to define everything in terms of that nesting. Your form_for should look something like form_for([#state, #city]) do (I don't remember the exact syntax).
Your follow up answer will work, but isn't exactly the best way to go about it, unless you want to be able to look at cities that are not in the context of a state.
Hope this helps.
PS. The form_for documentation is pretty good, and shows some good examples when using it with resources.

The problem is most likely in this line:
<p>Add a city: <%= link_to "Add city", new_state_city_path(#state) %></p>
It should be :
<p>Add a city: <%= link_to "Add city", new_state_cities_path(#state) %></p>
This is a language nuance, that takes some getting used to. I actually had the same problem. The paths need to be pluralized. I would also check to make sure that your routes.rb file has the pluralized version as well. There should be a line that looks like this:
map.resources :cities
If you have a line that says city instead of cities you should change it to cities. Hope this helps. Another great resource to check out is the #ruby irc channel on freenode, if you run into anymore problems.

Nevermind - I think I figured it out... I needed to have cities defined as a resource on its own, as well as a sub-resource of states. Now it seems to work.

Related

How should I approach making a custom form involving different model attributes?

I'm rather new to Ruby, so I need guidance as how to approach this. I know how to make very simple forms, but I'm thinking of implementing a custom form that can generate a payroll for a business during a specific start and end date. I already have business and payroll models, but I'm not sure how to implement this type of custom form and properly route it to get it be fully functional. Are there any resources or pieces of guidance I can get to help me with this?
please checkout this link :create an application on RoR. Please go to the link above and get started by creating your very own application. I have started with this and have learned a lot from this. This will get you kick started on RoR. But I believe you need more guidance in Ruby also. So I am attaching some more useful links. Please check them out also.
tutorails point - ruby
ruby-lang documentation
ruby guides
Thank you.
I don't know if I really get your issue... If your models Business and Payroll are linked (with :belongs_to and :has_many) you should check the fields_for method. You can nest it in a form_for/form_with to create fields associated to an other model. For instance you can do something like that:
#in your view
<%= form_with model: #business |f| %>
<%= f.label "Something:" %>
<%= f.text_field :something %>
<%= f.fields_for #business.payroll do |ff| %>
<%= ff.label "Something else:" %>
<%= ff.text_field :something_else %>
<% end %>
<%= f.submit %>
<% end %>
#in your controller
if #business.create(business_params)
#...
end
if #business.payroll.create(payroll_params)
#...
end
Hope it will help you !

Referencing attributes within a fields_for do block

I have a bit of an odd application where I need to reference the current values of the attributes being loaded by fields_for. The application takes a bit of explanation (it's to cater to a somewhat quirky but necessary jquery plugin) so I'll describe it with a simpler example.
Say I'm loading a list of customers into a form . And (for some reason) I want to head each person's fields with the name currently saved to the database before providing the fields to change it. Something like this:
<%= company.simple_fields_for :customers do |customer|%>
<span>Name previously saved was: <%= customer.name %></span>
<%= customer.input :name %>
<% end %>
Obviously the <%= customer.name %> above isn't a legitimate use for the builder but how might I reference the name attribute of each customer? Again, please pardon the goofy example.
Many thanks in advance.
I believe you should be able to access the customer object via customer.object, in the same way you can access the root object via form.object:
<%= company.simple_fields_for :customers do |customer|%>
<span>Name previously saved was: <%= customer.object.name %></span>
<%= customer.input :name %>
<% end %>

NoMethodError in #new - form_for, but resources set?

So, I'm trying some steps into rails and searched around SO, but couldn't find any answer. I constantly get NoMethodError undefined method for Line 1 as soon as I browse to /tswhois/new. Whats wrong?
controllers/tswhois_controller.rb
class TswhoisController < ApplicationController
def index
#tswhois = Tswhois.all
end
def new
#tswhois = Tswhois.new
end
end
config/routes.rb
Rails.application.routes.draw do
resources :tswhois
end
views/tswhois/new.html.erb
<% form_for (#tswhois) do |f| %>
<p>
<%= f.label :url %>
<%= f.text_field :url %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
console
rails console
Loading development environment (Rails 4.1.8)
2.1.5 :001 > Tswhois.count
(10.6ms) SELECT COUNT(*) FROM `tswhois`
=> 0
Just remember conventions in rails: model name is singular ie no s or es at the end. Routing is built around your model name. Your error page suggests Rails doesn't get the correct route for the action, in this example new action.
Can you copy and paste the entire error message ? try also: <%= form_for(#tswhois) do |f| %> without space and with the = sign
Did you restart the server after adding the resources to the routes.rb? the code you provided for your routes file is missing 'end' at the end of it.
Look into your views/tswhois/new.html.erb code. The code snippet you posted is probably from views/tswhois/_form.html.erb
It probably has a line <%= link_to 'something', tswhois_index_path %>
Change it to
<%= link_to 'something', tswhois_path %>
Thing is, the name 'tswhois' is going to be rather confusing due to the convention of singular and plural for a single instance and array of instances respectively.

Passing Input Text From text_field_tag as a variable for a URL...?

Okay, so I didn't know really how to word this correctly, but here is essentially what I am trying to do.
I am trying to take the text that a user inputs into my search box and pass it on to the URL.
Here is my view page so far:
<h1>What's the weather like by you?</h1>
<br />
<%= form_tag('http://api.wunderground.com/api/myAPIkey/conditions/q/**USER_TEXT_FROM_TEXT_FIELD_TAG**.json',:method =>
'get') do %>
<p>
<%= text_field_tag 'zipcode', params[:search] %>
<%= submit_tag "Check It Out!", :name => nil %>
</p>
<% end %>
I know this is probably such an easy thing to do, but I can't seem to find any way to correctly do it. Thanks for your help!
It looks like you are trying to redirect form submission to different url based on user input.
My no JavaScript sugestion would be to go through your own controller and redirect_to custom url. Something like this:
change your view to:
<h1>What's the weather like by you?</h1>
<br />
<%= form_tag('/weather') do %>
<p>
<%= text_field_tag 'zipcode' %>
<%= submit_tag "Check It Out!", :name => nil %>
</p>
<% end %>
create weather controller:
rails g controller weather create
add this line to your config/route.rb file:
match 'weather' => 'weather#create', via: :post
and modify you app/controllers/weather_controller.rb to look like this:
class WeatherController < ApplicationController
def create
redirect_to "http://api.wunderground.com/api/myAPIkey/conditions/q/#{params[:zipcode].split.join('+')}.json"
end
end
This isn't a nice solution and it isn't the smartest solution, it simply duplicates your code using rails stack. Your question doesn't give many information about what you would like to to with the date returned by api?? Do you really want to simply redirect to given url and see data as json?
I just try to give you another idea how to tackle this problem, its not a final solution.

What all models/controllers are needed for building a counter

I want to create a counter example where in the variable increments when ever the user presses a button on the webpage(view)
I have created the ruby program for the counter like this:
def counter(x = 0)
x+=1
puts "The current value is #{x}"
end
I have saved this as counter.rb. Then for the view I created another file called counter.erb But I dont know where to call this rb file and should I use <%= %> embedded ruby tags? Totally confused.
Another thing is the method counter's parameter should be linked to the button clicks.
Please guide me
Thanks,
Ok this is basic and you should be knowing this but still, I will tell you. The question is also vague so I will assume that you have a counter which is a number and a name for the counter. This is how you update any column from scratch.So first create
rails generate scaffold counter count:integer name:string
After this step.
def update
#counter = Counter.find(params[:id])
if #counter.update_attributes(params[:counter])
redirect_to #counter, :flash => { :success => "Profile updated." }
end
end
After this create a view in edit.html.erb under views:
<%= form_for(#counter) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :count %><br />
<%= f.text_field :count %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
Go to counter.rb model and do the following:
class Counter < ActiveRecord::Base
attr_accessible :count, :name
end
You dont have to add anything in the routes file because it already has the update resource.
Now open the browser and if you say
localhost:3000/counter/1/update
after creating the first counter value then you can update stuff from there.
This is how you updating can be done in ruby on rails. If you need more explanation regarding your code you should check the api documentation for rails it is a good start. I am a beginner too.
Looks like you are lacking basic understanding of Rails and MVC. I suggest you start with a simple tutorial to get a grasp on how things are working.
http://guides.rubyonrails.org/getting_started.html will get you started with a simple app and also explains everything you need to know at the beginning.
Basically said, you need a CounterController and - if you want to persist your counter - a Counter model. or you could use a cookie.
However, I advise you to read the guide I posted above.

Resources