Calling 2 different views in controller rails - ruby-on-rails

I have 2 versions of the same pages in my rails app and I would like for them to alternately load when the same page is called.
So for example: On page load index view comes up. On reload or refresh the alt_index page loads. How can I accomplish this? I am sure it can be accomplished in a controller action but not sure how.
class ComingSoonController < ApplicationController
def index
render('alt_index' || 'index')
end
end
This only renders the alt_index page I need it to alternate.

I suggest that you randomly select one of the templates to render with Array#sample instead of trying to alternate between them:
render ['alt_index', 'index'].sample

Related

Best way to create views based on a theme

I need to create separate view pages for a controller that I have.
I have a CustomerController that, based on the customer I need to create custom pages, these pages have to be stored as a file not from the db.
So normally I would have this:
class CustomerController < ApplicationController
def show
#customer = Customer.find(param["id"])
end
end
And the views would be located at:
/views/customer/show.html.erb
What I want to do is have the view pages like:
/views/customer/1/show.html.erb
/views/customer/2/show.html.erb
/views/customer/3/show.html.erb
How can I reference the specific view pages to load from within the action?
Is there a way to just pass the value 1,2,3 to the view folder path?
You can specify a template to render in the show action. Rails, without you explicitly calling render, will render the template that corresponds to that specific action...so, in your case, it will automatically render customers/show.html.erb (Note: Your controller should be plural...ie CustomersController, not CustomerController)
To override this, you can do something like this
def show
#customer = Customer.find(params[:id])
render "customers/#{#customer.id}/show.html.erb"
end

redirect_to(:back) same part of page?

I have a social feed.
If the user scrolls down a lot it is annoying to the user that by liking/commenting he is redirected to the top of the page instead of in the same part of the page to where he had scrolled to.
Is there any way to do this? Otherwise I'll just use paginate to make the pages smaller, which isn't ideal because that also takes away from user friendliness.
class ActivitiesController < ApplicationController
def index
#activities = Activity.order("created_at desc").where(user_id: current_user.following_ids)
end
def show
redirect_to(:back)
end
end
I've been on a roll with questions please check them out if you have time :)
Assuming that is being redirected to the top of the page because the page is being reloaded after a comment/favorite, you could try performing these actions using ajax instead.
This way, the page won't reload and you can modify the DOM to reflect the user's actions with javascript.
Here's some more information on ajax in rails:
http://guides.rubyonrails.org/working_with_javascript_in_rails.html
First generate anchors in your page by giving them ids. For example:
<div id="activity5">
..
</div>
Then in your controller, redirect to that part by using an anchor option:
redirect_to(request.env["HTTP_REFERER"] + '#activity5')
Note: redirect_to(:back) is the same as redirect_to(request.env["HTTP_REFERER"])
Having said that, using Javascript and AJAX is probably a better option.

Show top posts in a proper way Rails

I have a method in my posts_controller to display most viewed posts.
def top
#posts = Post.all.order("post.views DESC").page(params[:page]).per(10)
end
In routes I have
resources :posts do
collection do
get :top
end
end
The problem is: when i go to /posts/top i have an error: Missing template posts/top, application/top Do I need to write view files for my every method (top isn't the only one) or I can somehow display them in my index file without duplication of code?
Just render the index template at the end of your method:
def top
#posts = Post.all.order("post.views DESC").page(params[:page]).per(10)
render :index
end
I would suggest you to have a close look to rails layouts and rendering documentation. You will get your answer as well concept behind them. Below is the snippet of doc.
In most cases, the ActionController::Base#render method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behavior of render. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.

Groupon Alert Rails

I am new to rails so please be patient. I am open to suggestions on how to do this differently.
I would like to render 2 separate controller actions in one layout in rails.
I have 2 controllers: Coupons, and MainAlert. In the body of my application wide layout page I have a <yield > which loads the index action of Coupons or MainAlerts depending on the request (e.i. localhost/coupons or localhost/MainAlerts).
However, I would like to load the index action of Coupons or MainAlert or other controller (depending on request) but ALWAYS load the _form(where user creates new alert) at the very top on a I will hide and show.
"Get deals by email (+)" option at groupon.com
How do I load both controller action (index from Coupons and the _form (new? create?) from MainAlerts in the layout. The values of the MainAlert form need to be save to the DB if user hits submit.
I am open to suggestions on how to do this differently.
Thank you for you time everyone. =)
I'm kind of a newbie too, so expect more nifty answers.
But one way to solve this would be to use an before_filter in the Application Controller to always set up a new MainCoupon instance variable as every action is serviced. After that you could use render 'maincoupon/form' to render the form in the layout. The form should work as intended because the need instance variable was set up by the before_filter.
It could look something like this:
# application_controller.rb
class ApplicationController < ActionController::Base
# other stuff
before_filter :new_coupon
# other stuff
def new_coupon
#maincoupon = MainCoupon.new
end
end
In the layout you could have
<% = render 'maincoupons/form' %>
Or better yet, using HAML, just:
= render 'maincoupons/form'
In general your new action is associated with a view where the user enters information into a form. The new action in the controller creates a new object #maincoupon = MainCoupon.new of the desired to type, which is used as a "scaffold" for building the form.
When the user submits, the form information is packaged sent as a parameter to the create action, which takes the information sent from the form and uses it to create a new object of the desired type.
#maincoupon = MainCoupon.new(params[:maincoupon])
After that it uses the #maincoupon.save method to save it the to the database.
You can try the corresponding model methods out yourself in the console (rails console).
For example:
> A = User.new
Would create a new user, but doesn't save it to the db.
You could continue like this:
> A.name = "Apa"
> A.save
This will create and save it straight away.
> User.create(:name => "Apa")

Identical Files behave differently due to link with controller

I am building my first app with ROR and stumbled upon a couple of problems due to my understanding of the MVC
I have a page to add a new item, and this works fine, rails magically hooks it up to the items controller and somehow by magic it knows to look in the method 'new' as the page is called new.
But this layer is confusing me, as i need to now create a different version of new, same functionality but with a different look so to use a different layout to application.html.erb
So i attempt to create a copy of new.html.erb and create bookmarklet.html.erb - both contain exactly the same code: a link to a form. but of course bookmarklet will error on me because it does not have that link in the controller - how do i 'wire' up bookmarklet so that i can call the new method and so that it can behave in a similar way to the identical new.html.erb
Also, how can i tell the new bookmarklet.html.erb to ignore the application.html.erb and get its layout from another file?
thanks in advance
The magic happens in the routes. Rails uses something called RESTful routes, which is taking HTTP verbs and assigning standard actions to it. the new action is a GET request in HTTP speak, and if you are using scaffolding or following REST, will have the ruby call to build a new object in the controller, as an instance variable so you can use it in your view.
You have to tell rails routes that you want to BREAK this arrangement and to let /items/bookmarklet be used in the controller.
In your routes.rb file replace resources :items with
resources items do
member do
get 'bookmarklet'
end
end
In your controller put:
def bookmarklet
#item = Item.new
render :template => "bookmarklet", :layout => "different_layout" # or you can put this on the top of the controller, which is my style, but whatevs.
end
You should look into partials, if you are doing this as they clean up your code immensely.
A better way to think of things is to start with the controller instead of the view html.erb files. So each public method in your controller is effectively a page or action in the site. When you need a new action or page, add the method to the controller first. Then create the relevant view files.
So in your controller you'll need something like:
def bookmarklet
#item = Item.new(params[:item])
#item.save
render :template => "items/bookmarklet.html.erb", :layout => "different_layout.html.erb"
end
Normally you don't need to call render manually in the controller, but since you want a different layout than the default you need to specify it using render.

Resources