Wicked Rails Gem Help Wiring Up - ruby-on-rails-3

I want to do a multi-step form for taking in new information. One page I want to collect name/contact info, the next page I want to collect medical history, the third page demographic information.
I've installed the Wizard gem and generated a dedicated controller. All of the tutorials I've seen on it apply to devise and the signup process so I'm a little bit lost on the controller actions and the instance variables and how I should be writing them.
Was wondering if anyone has a tutorial other than a sign-up one that could maybe help me along in learning how to get this all wired up.
Any pointers or assistance is appreciated.
EDIT:
I think my problem is in the controller for my wizard.
In the show and update actions the demo shows to declare the variable of
#user = current_user
That's great, but it's a helper method that I don't need. I need to create a patient, store the patient_id in a session which I do in my create action in my main patients controller. Then somehow pass that over to the patientsteps controller.
Here's what I've tried in patientsteps
class PatientstepsController < Wicked::WizardController
before_filter :authenticate_user!
steps :medical, :summary
def show
#patient = Patient.find(params[:patient_id])
render_wizard
end
def update
#patient = Patient.find(params[:id])
#patient.attributes = params[:patient]
render_wizard #patient
end
end
When I do this, I get cannot find a patient without and ID. I understand that I'm doing this wrong, but I'm not sure how to pass in the patient_id that was created in my patients controller create action.
Patients Controller Create:
def create
#patient = Patient.new(params[:patient])
if #patient.save
session[:patient_id] = #patient.id
redirect_to patientsteps_path, notice: "Patient was successfully created."
else
render :new
end
end

In your show action, instead of params[:patient_id] you should use session[:patient_id], because the id of the patient is stored in the session, not in the params hash.
Then in the update action, you will receive the patient id in params[:patient_id], not [:id], because wicked uses params[:id] to identify which step the wizard is on.

Related

Get current user in a model in Rails3

I am using ActiveAdmin. I need to store the User that created or updated every record.
So I added user_created_id and user_updated_id to every model.
On before_save I want to store the information about current_admin_user. The problem is that I cannot access current_admin_user in a model.
Is there a way to do that without breaking MVC?
I found this: http://rails-bestpractices.com/posts/47-fetch-current-user-in-models
But I am not sure if it is safe.
Any help?
Do it in controller (it's the reason that controller exist) before save:
def create
#my_model = MyModel.create params[:my_model]
#my_model.user_created = current_user
#my_model.save
end
The same with the update method.

Rspec controller spec

I am new to Rspec please tell me what would be the controller Spec for the following two methods In index method only login page is seen by entering the username control goes to login method and find the name of person. If person is find then control goes to people path otherwise it goes back to root path that is index page it self.
class HomeController < ApplicationController
def index
end
def login
#person = Person.find(:all, :conditions => ['people.name =?', params[:person][:name]] )
if #person.blank?
redirect_to root_path
else
redirect_to people_path
end
end
end
Please help me.
Thanks.
Your rspec controller tests could be like this:
describe HomeController do
render_views
it "Logs in Person with non-blank name" do
person = Factory(:Person, name: "non-blank name")
get :login
response.should redirect_to(people_path)
end
it "does not log in Person with blank name" do
person = Factory(:Person, name: "") # blank name
get :login
response.should redirect_to(root_path)
end
end
Refer to rails controller specs for details.
EDIT:
Factory: the code that creates objects (test objects in this case). This is a preferred method for creating test objects because you can customize your code to create objects with varying attributes with least duplication.
Fixtures: If you are not using factories, you can specify the attributes for each of the objects you are going to create. For more than 2-3 object, this data quickly becomes unmanageable to maintain (for example, when you add an attribute, you need to make changes for each of these objects).
Stubs: If you prefer not to create database records while creating model objects, you can stub the model code white testing controllers.
For more information, refer:
1. testing guide
2. asciicast (Note: this code refers to an older version of FactoryGirl gem. Refer below for up-to-date API of FactoryGirl)
3. FactoryGirl Readme

working on rails 3 tutorial by hartl and stuck on 12.3.4 - New Status Feed

I'm stuck on the last exercise in the Hartlt book 12.3.4 where you define the status feed for yourself and the users you are following. I'm a Rails newbie so just let me know if I need to post additional information.
When I tail the development log I can see will_paginate fire the SQL to gather the initial records, and the initial page looks fine when it is served up. When I click a link to go to any another page, it appears will_paginate doesn't fire the SQL to get retrieve more data from the database as the next page is server up fine, but there is no data.
There are also no new entries in the development log and maybe I'm wrong, but I think this indicates will_paginate didn't hit the database.
I tried to include all the relevant code snippits below. Happy to send anything that's missing.
Here is my pages_controller.rb
def home
#title = "Home"
if signed_in?
#micropost = Micropost.new
#feed_items = current_user.feed.paginate(:page => params[:page])
end
end
Here is my user.rb
def feed
Micropost.from_users_followed_by(self)
end
Here is my microposts.rb
scope :from_users_followed_by, lambda { |user| followed_by(user) }
private
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
:user_id => user)
end
NOTE: In the video tutorial (chapter 12, time = 02:06:00) and the book (page 517, listing 12.44) Harlt uses the variable "followed_ids" instead of "following_ids". In the virgin sample code you can download from his site the variable name is "following_ids", and I have tried it both ways - but it fails.
Bottom line - the dev log shows will_paginate retrieving the first batch of data, but it never goes back to the database for additional data.
Can anyone suggest what I can take a look at to resolve my problem?
Many thanks.
do you have more records than will fit on one page?
If not, it may be that will_paginate is doing a count first.
Then deciding not to load any records.
Get into the console and try it out.
$ rails console
user = User.find(23)
# the same user you're logged in as
user.feed.count
# is it more than one page?
user.feed.paginate(:page => 1)
# 20 records?
user.feed.paginate(:page => 2)
# nothing?
Also:
in your example scope :from_users_followed_by, lambda { |user| followed_by(user) } is redundant.
You may as well just say;
def feed
Micropost.followed_by(self)
end

Ruby on rails tutorial: where is the user create view created?

Trying to follow along the ruby on rails 3 tutorial, I've completed the sign up process (through chapter 8) but nowhere has a user view: create.html.erb been created. Since 'create' is a section in the user controller, there needs to be a corresponding 'create.html.erb' file in views/users so I get a 'missing template' error when I try to use the tutorial form to create a new user.
Where does the tutorial create the create.html.erb file? I have paged through the tutorial a couple of times and can find no trace of it.
Thanks in advance for any help. --Fred
I am editing the question because for some reason the site will not let me add a comment below the responses to my question.
In UsersController... I have copied the following code directly out of the tutotrial:
def create
#user = User.new(params[:user])
if #user.save
#do something here
else
#title = "Sign up"
render = 'new'
end
end
I get: missing template users/create with {:locale=>[:en, :en].....
So if It is not a missing template issue, what is it?
create is an intermediary action, it does not require a view. in your create function make sure you do a redirect_to or a render view to something. here you can also populate a flash with messages corresponding to the success of the function (validation errors, succes for save etc)
When you create a new record, you actually call the new method, which does have an associated view called new.html.erb. The create method is called when you hit the "submit" button in the new.html.erb view, and there is no view for create - it is just a method that runs without a view.
Same applies for the update method which doesn't have it's own view, but which is "friends" with the edit action, whose associated view is called edit.html.erb.
Delete method is different

making a 'next' link, but (id+1) record might not exist in the database

so i want to make a page the displays a Phrase by select (initially) at random from the database. on that page i want a <%= link_to "next"%> but i was wondering if there was an efficient way to ensure that the next record exists
currently I'm using just
# #phrase is current phrase
<%= link_to "next", phrase_path( Phrase.find( #phrase.id + 1 ) ) %>
yes, i know i should call a #next from the controller, or better yet have a next method in the model to call #phrase.next, but this is for illustrative purposes.
but this often turns up an ActiveRecord::RecordNotFound error because some phrases have been deleted from the db (due to moderation, error, etc...). I could rescue from this and loop that till it works in the controller then pass it or something, but that seems like a bad solution, and not particularly 'railsy'
is there a convenient solution to this anyone has found
figured it out
based on this link which is a little outdated, uses named_scope from back in rails 2. I first rewrote it using the new rails 3 scope style, but then just changed it to a method. just used
def next
Phrase.where("id > ?", self.id).order("id ASC").first
end
def previous
Phrase.where("id < ?", self.id).order("id DESC").first
end
Try creating a next/previous scope on your model, as suggested in http://steve.dynedge.co.uk/2010/01/13/random-previous-and-next-entries-from-active-record-models-using-offset/
This will allow you to do something like:
Phrase.next(5) or Phrase.next(#phrase.id)
Why don't you create a method in the controller called next and pass in the current record id. It would be trivial from there to redirect the user back to the show page for that next resource.
If you are deadset on creating the link in advance, look into creating a helper method to find the next record that exists and make it available in your views. Then you could call that whenever you needed the id of the next available record.
Something like will_paginate might be of help too. I know your page size is just one, but the essence of what you're doing is pagination.