Web app design questions - RoR 3 - ruby-on-rails-3

This is my first web app that i am developing and i have some design questions, i have a few book about RoR3 but i dont seem to find answers to my questions.
My application is based on Ruby on rails 3
I am not looking for detailed answers here, if you can just point me to a topic name that i could learn about that can answer my qustions, such as "names resources" , "hidden fields" .....
My questions:
1- How to send information between View A and controller B. Example, i am on the View for "Company" when i click create employee i am calling the "new view" for the employee so i am now on a different view, how can i pass to the new employee action the ID of the company? Since i am now on a different view ? i don’t want to use nested resources
What are the different ways to send information across different controllers/views
2- ruby URLs: i can view am item in my model via the URL: http://localhost:3000/Companies/1
I don’t want the url to contain the index of the item, each company has a name and i want to display this name in the url such as http://localhost:3000/Companies/myCompany
How can i change the url structure of rails?

For your first question, you can pass the parameters with the link (assuming you have employee and company variables accessible to your view):
Edit: this should work:
= link_to "create employee", :controller => "employees", :action => "new", :company_id => #company.id
And in the Employees controller:
def new
company_id = params[:company_id]
# check that company_id is not nil before doing stuff with it
end
I'm not sure why doing this ignores any extra parameters:
= link_to "create employee", new_employee_path, :company_id => #company.id
For your second question, this is what you're looking for.

Pass the company id as parameters at create employee link .
In the controller ,receive the params like
def new
company_id = params[:company_id]
....
end
For using some string instead of id , use gem 'friendly_id'
Make sure your reference string should be unique.

Related

Wicked Rails Gem Help Wiring Up

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.

Rails 3.2.12 controller action hiding from URL

I have scaffold 'Category' which has table 'categories' and fields like category_name etc.
Now on my home page, I am showing all records.
If I click on 'show' of any particular category, my URL looks like this -> "http://www.abc.com/categories/1" where 1 is the id.
Here instead of "categories/1", I want the url to be in this format : "http://www.abc.com/#{category_name}".
I use friendly id but that makes my URL like this "http://www.abc.com/categories/#{category_name}".
I want to hide controller name and id from url and only display the category name
You can add something like
match '/:path' => 'categories#show', as: :category
in your route. be warned that this should be placed at the bottom of your route so it takes least priority because it will match the index action of all your controllers. Use it like
category_path(category_name)
Or
"/#{category_name}"
You may also need to remove the show mapping to the show action so it doesn't conflict with the named_route generated by adding the as: :category option
resources :categories, except: [:show]

Adding a new record that has a foreign key relationship using new_foo_path(#bar)

I'm trying to add a new location to a restaurant using Ruby on Rails.
In the restaurants#show action I run:
<%= link_to 'Add Location', new_location_path(#restaurant) %>
And I get a URL: http://localhost:3000/locations/new.1, where 1 is the id of the restaurant. But the new location form doesn't appear.
What is the rails way to handle this simple case? Is using new_FOO_path even the right thing to be doing?
In this case, I shouldn't have a drop down to select the restaurant because I want the end user to only be able to add a location to their own restaurant. I would somehow need to have a hidden input with the restaurant ID in the add location form, and also validate the id on the backend.
I would create a nested resource in your routes.rb. Example:
resources :restaurants do
resources :locations
end
Then your link target would be new_restaurant_location_path(#restaurant). In your controller, you can find the restaurant via Restaurant.find(params[:restaurant_id]).
Alternatively, set the restaurant id as a GET parameter with new_location_path(:restaurant_id => #restaurant.id).

REST path for "new from copy"

For certain models, I wish to provide functionality that allows a user to create a new record with default attributes based on copy of an existing record.
I'm wondering what would be the correct restful route for this.
My initial thinking is that it could be a parameter to the new action. I.e. to borrow from the the Rails Guides examples, instead of just:
GET : /photos/new
Also allow:
GET : /photos/new/:id
...where :id is the id of the record to use as a template. The response would be a new/edit form, same as with a plain old new but the values would be pre-filled with data from the existing record. The parameter (or absense of it) could be easily handled by the new controller method.
The alternative seems to be to create a new controller method, for example copy which would also accept an id of an existing record and response with the new form as above. This seems a little 'incorrect' to me, as the record is not actually being copied until the user saves the new record (after probably editig it somewhat).
TIA...
UPDATE: my question is not "how do I do this in rails?", it's "is it RESTful?"
my question is not "how do I do this in rails?", it's "is it RESTful?"
No, it isn't. For that matter, neither is GET /photos/new. Rails seems to be hopelessly mired in the past, where it was considered haute programme for a GET on a URI to return an HTML form which would then POST x-www-form-urlencoded data back to that same URI. The opacity of that POST forces them to invent new verbs-as-URI's like /photos/new, when you could be using PUT instead, or at least POST with the same media type.
The simplest way to make a copy of an HTTP resource RESTfully is:
GET /photos/{id}/ -> [representation of a photo resource]
...make modifications to that representation as desired...
POST /photos/ <- [modified representation]
If you're implementing this for browsers, you should be able to perform those actions via Ajax quite easily, using an HTML page sitting perhaps at /photos/manager.html/ to drive the interaction with the user.
You can try to use nested resources. I'm not exactly sure about structure of you application, but in general using nested photos will look somehow like this:
routes.rb
resources :photos do
resources :photos
end
photos_controller.rb
before_filter :find_parent_photo, :only => [:new, :create]
def create
#photo = Photo.new params[:photo]
if #parent_photo.present?
# fill some #photo fields from #parent_photo
end
#photo.save
respond_with #photo
end
def find_parent_photo
#parent_photo = Photo.find(params[:photo_id]) if params[:photo_id].present?
end
new.html.haml
= form_for [#parent_photo, #photo] do |f|
-# your form code
previously when you wanted to add a link to photo creation you wrote something like that
= link_to "new photo", [:new, :photo]
now if you want to add a link to photo creation based on foto #photo1
= link_to "new photo based on other one", [:new, #photo1, :photo]
You should be able to match a route like so:
match 'photos/new/:photo_id' => 'photos#new
or you could just pass a :photo_id parameter in the url and handle it in the controller:
'/photos/new?photo_id=17'
Example using helper method: new_photo_path(:photo_id => 17)
Edit: I don't know if this conforms to REST
It may be over the top, but you could do something like this:
class PhotoCopiesController < ApplicationController
def new
#photo = Photo.find(params[:photo_id]).dup
end
def create
end
end
and
resources :photo_copies, :only => [:new, :create]
and
= link_to 'Copy', photo_copy_path(:photo_id => #photo.id)

Ruby on Rails 3 multiple tables

This is my first ROR application, so this is probably a basic question. I'm building a review site where users submit reviews.
I have a User model, a Review model, a Location model, and a Category model. The Category model belongs to the Location model, and I have that the Review model belongs to the User model. User has many reviews and Locations has many categories.
So when a user navigates the site they see a directory of locations (~/locations), clicks on a link to a location, which then displays the Categories for that locations (~/locations/:id/categories). When the user clicks on a category (~/locations/:id/categories/:id) I have a new review link on the page which sends the user to a form to create a new review (~/users/:id/reviews/new).
The problem I'm having is how do I send the category_id and location_id along with the user's review. I need the additional ids to show the reviews for the correct category, As of now, the user goes to ~/users/:id/reviews/new to create their review, which allows me to easily grab the user_id. How do I also get the category_id and location_id?
Any input is appreciated.
If the link is on a page where you have both the category and location, one option would be to pass them as query strings by creating your link with something like this:
<%= link_to "New Review", new_user_review_path(#user, :category_id => #category.id, :location_id => #location.id) %>
Then they are available in params
params[:category_id]