Rails : trying to pass Id from controller to view - ruby

i'm a little noob in ruby..
i want to pass id of object that i just created to view that it will get render via render method
this is my code below
respond_to do |format|
if #object.save
format.html { render "finished_reg",param: #object.id ,notice: 'object was successfully created.' }
#end
in the view
<%= link_to 'Here' ,"/controller/#{:param}" %>
but nothing happen.. how to make that and how can i print this on the view?

#instance_variables persist when going from controller to views. So you can simply do:
<%= link_to 'Here' ,"/controller/#{#object.id}" %>

As nicooga said, all instances variables (the ones that you define with # on your controller) are available on your view and so his code will work. However, in Rails, there's even an easier way to do it: path and url helpers:
http://guides.rubyonrails.org/routing.html#path-and-url-helpers
So your code would look like:
<%= link_to 'Here' ,object_path(#object) %>

Related

RAILS 4: Trying to get the current page to pass to render in an AJAX request

I have a fairly straight forward question.
On my site, within the header is a "invite a colleague" link to a modal that contains a form:
<%= simple_form_for(current_user, :url => send_invite_user_path(current_user), remote: true) do |f| %>
<%= f.label :email %><br>
<%= f.text_field :email, class: 'form-control' %>
<%= f.submit "Send", class: "btn btn-primary ShareSend" %>
<% end %>
Here is the send invite controller
def send_invite
#current_page = URI(request.referer).path
#email = params[:user][:email]
InviteWorker.perform_async(current_user.id, #email)
respond_to do |format|
flash.now[:success] = "Invite sent"
format.html { redirect_to #current_page, :current_page => #current_page}
format.js { render #current_page}
end
end
It works fine when not using AJAX, but I want to try to get it to work via AJAX. The issue is that the "current_page" when I open the modal and try to send via AJAX refers to the "send_invite" action and is looking for a "send_invite" template. I want it to render WHATEVER page the user is on. To add to my difficulty I am using friendly_id.....I tried using
#page_hash = Rails.application.routes.recognize_path(URI(request.referer).path)
To try to extract the user action from the current page path, but obviously this doesn't work with friendly id.
Is there a "Rails way" of capturing the current page (ignoring the modal) and passing this to render....
I hope this is clear...
An AJAX call does not trigger a complete reload of the current page (unless explicitly told to). The request is handled in the background by javascript.
In your case you should add a view called send_invite.js.erb (i guess in your app/views/users folder - assuming that send_invite belongs to UsersController) that has some javascript that notifies the user of a successful invite and closes the modal. This view could be as simple as:
alert("Invite sent!");window.closeMyInviteModal();
This script will be executed if (and each time) the AJAX call succeed.
Clean the js responder in send_invite. This will by default render the send_invite.js view.
format.js { }
See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#a-simple-example

How to pass param from 1 controller to another

I want to pass param from the following link in the view of Client controller
and the hash is #client, I want to pass #client.user_id, if i put (:id => #client.user_id) I am not able the get :id in the other controller Estate where I want to pass this param. What should I do ? Is there a way to do it ?(Two controllers are Client and Estate, I want to pass param from Client view to the Estate controllers create method. There is no nesting of resources here!)
<%= link_to "New Property", new_estate_path(:key => #client.first.user_id) %>
create action
def create
# #estate = Estate.new(params[:estate])
if current_user.Company.nil?
#estate = current_user.estates.build(params[:estate])
else
serve = User.find(params[:key])
debugger
#estate = serve.estates.build(params[:estate])
##estate.user_id = user_id
debugger
end
respond_to do |format|
if #estate.save
if #estate.Mgmt.nil?
EstateMailer.company_confirmation(#estate).deliver
end
format.html { redirect_to #estate, notice: 'Estate was successfully created.' }
format.json { render json: #estate, status: :created, location: #estate }
else
format.html { render action: "new" }
format.json { render json: #estate.errors, status: :unprocessable_entity }
end
end
end
The code you pasted here should work:
<%= link_to "New Property", new_estate_path(:id => #client.user_id) %>
I think the problem is, you are expecting the params in create method but where as it actually goes to new method.
If you are looking for the create method. You can do
<%= link_to "New Property", estates_path(:id => #client.user_id), :method => :post %>
But that is not the right approach to use for POST actions. The right solution would be to use button_to.
<%= button_to "New Property", estates_path(:id => #client.user_id), :method => :post %>
link_to defaults to GET and button_to defaults to POST, as those are their primary usages. You can override :method if you want them to perform other action than their default.
Simply do this
<%= link_to "New Property", new_estate_path(user_id: #client.user_id) %>
In your controller:
params[:user_id]
You problem is that the create action is a POST not a GET. The link_to will only allow GET actions.
I made class variable in the controller outside all the actions.
##key, and in the new action assigned ##key the user_id that was coming through the params, and this ##key in the create action. I don't know if its the right way to do it. But it worked like a charm !

2 instance variables of the same name in different controllers

I finished Michael Hartl's Ruby on Rails Tutorial. Now I'm working on the suggested exercises. The application he builds is basically a Twitter clone where one can post Microposts and they appear in your feed http://ruby.railstutorial.org/chapters/user-microposts#fig-micropost_created
The main page is in home.html.erb from the StaticPagesController and features a Micropost textbox where one can post Microposts. The code for the textbox looks like so:
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
The #micropost variable is initialized in the StaticPagesController like so:
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
end
end
Now inside the MicropostsController there's a create action like so:
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
My question is what is the purpose of the first #micropost variable as opposed to the second?
thanks,
mike
The first #micropost becomes available to the view rendered by the first controller method; the second #micropost becomes available to the view rendered by the second controller method. And it just so happens that the two methods are rendering the same view.
The only wrinkle is that since the second controller is conditional. If the create succeeds (passes validation and saves) then there's a redirect, so there's no proper view (although there will be in a moment, after the client-side redirect). But if it fails, then the view gets an object that contains the user-entered values as well as the validation errors which the view can then show to the user.

No route matches [POST] "/story/new" after submitting form

I've just started "Build Your Own Ruby on Rails" and I have had to use Google a lot, as the book seems to have a bunch of places where the code just doesn't work. This time, I couldn't find an answer. Okay, so here's the deal. I have a form that looks like this:
new.html.erb:
<%= form_for :story do |f| %>
<p>
name:<br />
<%= f.text_field :name %>
</p>
<p>
link: <br />
<%= f.text_field :link %>
</p>
<p>
<%= submit_tag %>
</p>
<% end %>
It shows up fine when I go to localhost:3000/story/new. The thing is, when I try to type stuff into the form and press "submit," I get this error:
Routing Error
No route matches [POST] "/story/new"
My routes.rb looks like this:
FirstApp::Application.routes.draw do
resources :story
story_controller looks like this:
def new
#story = Story.new(params[:story])
if request.post?
#story.save
end
end
The story_controller stuff for new is straight out of the book. I thought I might have had a solution here, but no dice. Any help would be greatly appreciated.
I'm guessing you meant (note the at sign):
<%= form_for #story do |f| %>
That'll probably take care of your routing issue, but as John mentions, your controller action is a bit off, too. The new action should only load a dummy model and display the new.html.erb page - the saving should take place in a separate action, called create.
Hope this helps!
Edit: Minimal controller code:
class StoriesController < ApplicationController
def new
#Make a dummy story so any default fields are filled correctly...
#story = Story.new
end
def create
#story = Story.new(params[:story])
if(#story.save)
#Saved successfully; go to the index (or wherever)...
redirect_to :action => :index
else
#Validation failed; show the "new" form again...
render :action => :new
end
end
end
First off, Rails is relies on convention over configuration when using singular vs plural names. If you want to follow convention, you have to change the line in your routes.rb to resources :stories, which would generate following routes:
stories GET /stories(.:format) stories#index
POST /stories(.:format) stories#create
new_story GET /stories/new(.:format) stories#new
edit_story GET /stories/:id/edit(.:format) stories#edit
story GET /stories/:id(.:format) stories#show
PUT /stories/:id(.:format) stories#update
DELETE /stories/:id(.:format) stories#destroy
Note, that in this case you would have to rename your controller to StoriesController. However, your routes.rb has resources :story, which generates following routes:
story_index GET /story(.:format) story#index
POST /story(.:format) story#create
new_story GET /story/new(.:format) story#new
edit_story GET /story/:id/edit(.:format) story#edit
story GET /story/:id(.:format) story#show
PUT /story/:id(.:format) story#update
DELETE /story/:id(.:format) story#destroy
As you can see, indeed, there is no route for POST /story/new. I guess, the error that you are getting is triggered by following code in your controller:
if request.post?
#story.save
end
It is quite wrong, because you trying to check for POST request inside the action that is routed to by GET. Just remove this code from your new action and add create action to your StoryController like this:
def create
#story = params[:story]
if #story.save
redirect_to #story, notice: "Story created"
else
render action: "new"
end
end
This should resolve your issue for now. But I strongly recommend using plural stories for your resources, since it will be back to haunt you again.
This is the part that you (and me) have missed from the guide:
There's one problem with this form though. If you inspect the HTML
that is generated, by viewing the source of the page, you will see
that the action attribute for the form is pointing at /articles/new.
This is a problem because this route goes to the very page that you're
on right at the moment, and that route should only be used to display
the form for a new article.
The form needs to use a different URL in order to go somewhere else.
This can be done quite simply with the :url option of form_for.
Typically in Rails, the action that is used for new form submissions
like this is called "create", and so the form should be pointed to
that action.
Edit the form_for line inside app/views/articles/new.html.erb to look like this:
<%= form_for :story, url: stories_path do |f| %>

How to do a Switch based on controller with ruby on rails?

How could one do switch in ruby on rails something like:
case controller "home"
do home
case controller "about"
do about
else
do home
I currently have this code:
<% case current_page(:controller) %>
<% when "forums" %>
<%= render :partial => 'shared/sidebar/sidebar_forums' %>
<% when "events" %>
<%= render :partial => 'shared/sidebar/sidebar_events' %>
<% else %>
<%= render :partial => 'shared/sidebar/sidebar_frontpage' %>
<% end %>
Quoting from http://rails.nuvvo.com/lesson/6371-action-controller-parameters:
The params hash will always contain the :controller and :action keys, but you should
use the methods controller_name and action_name instead to access these values. Any other parameters defined by the routing, such as :id will also be available.
So you should definitely be able to access it via params[:controller], and, if the controller_name method is in scope in a view, you should use that instead.
As for the switch syntax itself, you do need to do it like
case controller_name
when "home"
do_home
when "about"
do_about
else
do_default
end
You could do some hacking and get
case true
when controller "home"
do_home
when controller "about"
do_about
else
do_default
end
But why?
Whenever you had to do something like this, that means there is something not right with the application design. Not that I have never done that in the past but I dont do this now and it is being frowned upon.
Instead of doing what you are doing now, if you namespace your controllers appropriately according to their responsibilities, after all they are just classes and handle the requests coming from the users,etc., then you may not have to do this switch statement. For example, after namespacing them you may have different layouts made of different partials for your views which may not require you to do this switching in your controller/views hence keeping the code clean.

Resources