Method missing error when using cucumber (with rails, webrat, and mongomapper) - ruby-on-rails

I'm writing a few basic step instructions in Cucumber, and can't figure out why it's throwing up a "method missing" error. Here's the precise error:
undefined method `question' for nil:NilClass (ActionView::Template::Error)
The root of this error is this line from my index.html.erb page:
<p id="question"><%= #question.question %></p>
So it looks like the test thinks that #question is nil. I'm not sure why it thinks this. What should I change in my step instructions? Here they are:
Given /^a question$/ do
#question = Question.create!(:question => "here's my question..", :answer => "right_answer", :num => "1")
end
When /^I answer the question$/ do
visit root_path
fill_in "Answer", :with => "Wrong answer"
click_button "Submit answer"
end
The first step instruction passes, but the second does not.
EDIT: Here's my entire index.html.erb page, in case it's useful:
<% title "Questions" %>
<p id="question"><%= #question.question %></p>
<%= form_for #user_answer do |f| %>
<div><%= f.label :answer %></div>
<div><%= f.text_field :answer %></div>
<div id="sign_up_button"><%= f.submit "Submit answer" %></div>
<% end %>
<p><%= link_to "New Question", new_question_path %></p>
EDIT: My Question model, in case it's useful:
class Question
include MongoMapper::Document
key :question, String, :required => true
key :answer, String, :required => true
key :num, String, :required => true

Assuming you're giving us the excerpt from the stack trace properly, your issue is that you aren't setting #question properly in your controller - which you have not posted above. Several other people have alluded to that in their answers, but I'm quite convinced of it.
Your tests - cucumber or otherwise - have nothing to do with the problem you're having.
I suspect that if you visit your root_url, you will get the same problem - you will get a stack trace and an error. Without knowing exactly what your routes are, I can't be sure where you're being sent when you visit the root_url.
Your controller should be loading up #question with your question object (probably via Question.find() or something like it), then rendering your index.html.erb page. So your 'index' action in your controller ought to be the thing that is filling in your #question.
Note that you're not following rest-ey principles here - usually people have 'indexes' give you lists of things (questions in your instance), then id's give you a particular question.
I bet if you go to a particular question it works fine.
Maybe your problem is that you shouldn't be testing by visiting 'root_path' in the first place? Maybe you should be going to a particular "question's" path?

Do you have any validations at Question model? Maybe you can't create new question object like you trying.

Related

Passing rails hash map to Controller (from form)

I am developing a rails application for a client. In a nutshell, it is for monitoring the progression of PhD uni students. One of the main functional requirements was for the user to be able to fill out reports online. The issue I am having is with one of the forms.
I am allowing the number of questions per form to be completely unrestricted, so I am using dynamic symbols to store the answers to the questions, and pass those answers to the controller in a hash. Here is a snippet of the code from the form, and the controller method:
<% #questions.each do |q| %>
<div class="field">
<!--Question Label -->
<%= s.send(:label, "Question #{q.question_number}") %>
<!--Link to delete question -->
(<%= link_to 'Remove', {:controller => "report_details", :action => "delete_question", :question_to_delete => q.id}, data: { confirm: 'Are you sure?' }, :class => 'form-link', :method => "post" %>)
<!--Question text box -->
<%= s.send(:text_area, "qu_hash[question#{q.question_number}]", :rows => 3, :cols => 60, :value => q.question) %>
<!--New Question Button -->
<%= link_to '>> Insert Question Here <<', {:controller => "report_details", :action => "add_question", :position_to_add => q.id}, :method => "post" %>
</div>
<% end %>
My issue is with with the line below I think. I will explain why below, but here is my controller method (accessed by submitting the form).
def save
questions = params[:report_detail][:qu_hash]
ReportDetailQuestion.where(:report_detail_id => #report_detail.id).each do |q|
q.update_attributes(:question => questions["question#{q.question_number}".to_sym])
end
redirect_to #report, notice: 'Report was successfully updated.'
end
The error I am getting is this:
undefined method `[]' for nil:NilClass
questions = params[:report_detail][:qu_hash]
ReportDetailQuestion.where(:report_detail_id => #report_detail.id).each do |q|
#Error occurs on the below line
q.update_attributes(:question => questions["question#{q.question_number}".to_sym])
end
The hash is not a part of the database, it is being used to update entries in the table of report questions (seperate to the report table). This error is being caused because the hash is not being submitted from the form (on the error screen - where it shows the params passed to the controller, the hash is not present).
Also, I am unsure how to permit this hash through the "white list" of the object, so if someone could help with that it would also be helpful (for now I am just permitting everything, so that won't be the issue. The field just isn't being submitted for some reason).
If you need more information let me know!
Cheers
For this problem I will advise you to use nested forms which is more suitable for this case mainly for user experience. For that, you need to create a question model first.
you can follow this railscast which explains well how to do...
Not sure it is what you are looking for...

Rails Advanced Sign Up Implementation How To?

I am a three week old Rails newbie and I have something that I want to implement but have no idea how to go about it. I'm making an app:
I want a user to enter some sign-up info on the new users view page, then, when they click submit, instead of the user being created and saved in the database right away, instead I want them to be taken to a second webpage where they will be asked for some final verification before they can create their account. Then when they click 'verify' and the verification passes, the account is finally created and saved to the database.
This is hard for me because I only know how to make basic forms, where you enter info, hit submit, and you have a new entry in the database. I don't know how to defer the "user creation" for another webpage, but a friend has mentioned something about http requests, but I still don't know anything. I'll post some of my code so far:
My users_controller new definition:
def new
#user = User.new
#user.websites.build
end
My users_controller create method:
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome!"
redirect_to #user
else
render 'new'
end
end
My users/new.html.erb sign up form:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<%= render 'shared/error_messages' %>
<%= form_for(#user) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %><br/>
<%= f.label :password %>
<%= f.password_field :password %><br/>
<%= f.label :password_confirmation, 'Confirm Password' %>
<%= f.password_field :password_confirmation %><br/>
<%= f.fields_for :websites do |builder| %>
<%= builder.label :url, 'Website URL' %>
<%= builder.text_field :url %>
<% end %>
<%= f.submit "Sign up", :id => 'submit' %>
<% end %>
I've never asked a question that's just asking for advice like this before, so I'm hoping this is the right place to ask. Any and all help is appreciated.
I think you are trying to create a "multistep" form...
There is a very good railscast about it: http://railscasts.com/episodes/217-multistep-forms?view=asciicast
However, you might face some validation problems, as you need to validate each step individually. So, take a look also here: http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation
I hope it helps...
You'd better use Devise for user management.
https://github.com/plataformatec/devise
Here's a railscast tutorial.
railscasts.com/episodes/209-introducing-devise
If you're doing multistep, you can always pass information from one page to another. You can store it in a session array, repost it to the other page, or even make a cookie.
Remember to also do every step of this under https, because account creation requires sensitive info.
If Rails is your first I would actually recommend something lower level like PHP so you can understand how everything works before you start doing stuff with a high level framework like rails. MVC is usually not the best first step in web development, even though it is powerful and easier than doing everything from scratch.

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.

What is the use of hidden_field method on Page 491 in Michael Hartl's Rails tutorial book?

(First of all, I want to note that this question might only be answered if you have read the book or even got the book in your hand so that you can read the relevant part on Page 491, since I can only extract a small section and paste it here. I apologize for that.)
This is the _follow.html.erb partial used in the book on page 491:
<%= form_for current_user.relationships.
build(:followed_id => #user.id) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<div class="actions"><%= f.submit "Follow" %></div>
<% end %>
It is for creating a "follow" button to follow other users.
And then in his explanation of the line dealt with the "f.hidden_field", he said,
Finally, you’ll note that the form doesn’t have any content other than the button, but it still needs to send the followed_id, which we accomplish with hidden_field;
My questions are:
Why do we need a hidden_field here to send the followed_id? As far as I see it, the line
<%= form_for current_user.relationships.
build(:followed_id => #user.id) do |f| %>
has already assigned the :followed_id attribute right?
I think those two part of code are different.
<%= form_for current_user.relationships.build(:followed_id => #user.id) do |f| %>
This line creates a new record for the form.
<%= f.hidden_field :followed_id %>
This code create an actual params of your form.
--> You might want to read that to learn more about form_for http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for

Rails "NoMethodError" with sub-resources

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.

Resources