How to send data to another controller without GET method using link? - ruby-on-rails-5

I am using Rails 5.2.2. I have users, authors and books tables. Every user can only see the records which saved by themselves.
Books table has user_id and author_id foreign keys. I need to save that data automatically.
In my books_controller.rb file I created a set_defaults method to add this data automatically like,
def set_defaults
params[:book][:user_id] = current_user.id
end
There is no problem with the user_id but I don't know how to access the author id.
I added a link under the authors#show page and want to add book to author using that link.
So how can i get the author_id with the safe way?
Add a Book
This redirects to http://localhost:3000/authors/8/books/new
I don't want to use the id from link and don't want to use get method.
I only want to use the link (Add a book) to save a book.So how can i pass that author object to controller ?

In your html form:
<%= form_for [#author, #book] do |f| %>
# Your Book fields here
<% end %>
In your controller (without an authorization gem)
class AuthorsController < ApplicationController
def show
#author = current_user.authors.find(params[:id])
end
def create
#author = current_user.authors.find(params[:id])
#book = Book.new(book_params)
if #book.save
# handle save
else
# handle error
end
end
private
def book_params
params.require(:book).permit(:title .....)
end
end

Okay i found a solution but i am not sure that it's a good practice. Any better solutions will be appreciated.
I created a global variable in author show.html.erb page :
$current_author = #author
And i used it in books_controller.rb
params[:book][:author_id] = $current_author.id

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 active record object in application controller

I'm adding a site-wide form for asking questions on a rails site. The models/views/controllers for the resource question are already created. Going to question/new shows the form as you'd expect. Now I want to display a site-wide question form (the only difference with this one is that it only shows mandatory fields). Question: should I create a new question object in application_controller and pass that to the rails form_for helper, or should I create a new _form2 partial(in the question view) and just include that in my site-wide template?
Thank you.
Create a question_form partial in the views/shared folder, and reference that from the site wide template.
Edit: in reply to where to get the #question variable from
You have two options in my mind, you can load the variable in ApplicationController:
class ApplicationController < ActionController::Base
before_filter :load_question
def load_question
#question = Question.new
end
...
end
(You should be careful of conflicts with the #question variable in this case)
Or probably better, you can create a method in ApplicationHelper:
module ApplicationHelper
def question_form
question = Question.new
raw render 'shared/question_form', :question => question
end
...
end
Then in your view, instead of referencing the partial, you reference the helper:
<%= question_form %>
In this case you would need to reference the variable in the partial as a local variable, so question instead of #question.
Hope that helps.

Rails - How to include a hyperlink in a text field

I have a notices model which contains records of notices for each user. Each notice record contains a message which is a text field with the notice message. These messages look like:
"#{current_user.username} liked your photo '#{#photo.name}."
In the example above, I would like the user and the photo to also be hyperlinks to that user and photo.
Here is a snippet from my likes_controller which generates a notice when a new like is created:
class LikesController < ApplicationController
def create
#photo = Photo.find(params[:id])
#like = Like.new(:photo_id => #photo.id, :user_id => current_user.id)
if #like.save
#notice = Notice.new(:user_id => #photo.user_id, :message => "#{current_user.username} liked your photo '#{#photo.name}'
end
Any thoughts on how I can include links in the message; is this even possible? Thanks.
Adding a link to your message is a rendering issue. In my opinion, you're rendering the message too soon, I would render it in the view.
If you change your Notice model so that it contains a the user_id and the like_id, you can render the notice text in the view (which also lets you localize the text later, should it prove necessary).
Rendering in the view lets you use the standard link_to helper to generate your links.

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)

Rails 3 subsequent forms submission (second dependent on first)

I am trying to achieve a subsequent form submission. To clarify things -
I submit a form for #post
then once that #post is created I would immediately (under the hood) like to submit the form for #associations.
The catch is, this second form submission would require the post_id field from the newly created #post.
What would be the best way to achieve this? Would nested forms help me pull the newly created #post.id? Kindly help me with this.
If this is something that should happen whenever you create a Post, then you should use active callbacks to achieve that :
class Post < ActiveRecord::Base
after_create do |post|
# create your association using post.id
end
end
or, you can write it like that also :
class Post < ActiveRecord::Base
after_create :after_create_post
def after_create_post
# create your association using self.id
end
end
Otherwise, if this is something specific to a controller action, you should simple do something like this :
class PostsController < ApplicationController
def create
#post = current_user.posts.build(params[:post])
# then use the #post.id to build your association. something like
#post.associations.build(:prop1 => 'value1', :prop2 => 'value2')
end
end
Hope this helps!