Groupon Alert Rails - ruby-on-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")

Related

using rails how do i only show the id submitted via a text box from a table

I've got a table full of information at the moment, Ideally i need the information from a database table to be viewed via a link.
I only have the controller and some standard html (the html is just a h1 tag at the moment)
The HTML will be standard throughout like a template.
The way i'm seeing what i want in my head is the users will get a link which would be events_prev/{{id from DB here}} and depending on the ID the information on the page will be populated from the corrisponsing DB Row
Heres my controller
class Events::EventsPrevController < ApplicationController
def index
#events = Event.where(id: id)
end
def show
render :nothing => true
end
end
Sorry if its super confusing.
Welcome to rails.
Ok, there's a couple of things that will get you in the right directions. Firstly, you REALLY need to do a little reading to understand how the controller and the routes and the views are linked together in rails, that'll help you tons.
But moving on to your specific issues:
Parameters:
All data passed via a url (get, post, put, doesn't matter the method) is available in the controller in an array object called params - So that means when want to access the data the user submitted, you'll use something like
#event = Event.where(id: params[:id])
Routes:
It looks like you're trying to use the index page. In rails index is a RESTful route which generally points to a collection of model objects. The show route will point to an individual object so you should instead make your link point to the show path instead of the index path.
You can view the routes available on a model on a command line using:
bundle exec rake routes
An example of what your routes might look like:
prev_events GET /prev_events(.:format) prev_events#index
POST /prev_events(.:format) prev_events#create
new_prev_event GET /prev_events/new(.:format) prev_events#new
edit_prev_event GET /prev_events/:id/edit(.:format) prev_events#edit
prev_event GET /prev_events/:id(.:format) prev_events#show
PATCH /prev_events/:id(.:format) prev_events#update
PUT /prev_events/:id(.:format) prev_events#update
DELETE /prev_events/:id(.:format) prev_events#destroy
Link
Based on the routing table, you now should see that the link you need your users to click on might look like this (given that event is your object:
<%= link_to event.title, event_path(event.id) %>
or shortcutted
<%= link_to event.title, event %>
View
For the view this is entirely dependent on the data in the Event model. Since the data is stored in #event you'll simple use the attributes on the event model to render the html however use like, e.g.
<h3><%= #event.title %></h3>
<span><%= #event.start_time %></span>
You should read up on Rails controllers: by default the action index is used to show all of the records and what you're talking about should belong to the show action. The default routes take care of the id passing to your show action.
Index action is mean to show list of items in view and Show action is used to show a single item.
what you are doing in index is actually mean to be in show action.
Reason:
#events = Event.where(id: id)
this line will give u a single record in every case it means it should be in Show action.
your code should look like:
def show
#event = Event.find(params[:id])
[your logic: what you want to do with that #event]
end

Way to see which rails controller/model is serving the page?

This might be a slightly odd question, but I was wondering if anyone know a Rails shortcut/system variable or something which would allow me to keep track of which controller is serving a page and which model is called by that controller. Obviously I am building the app so I know, but I wanted to make a more general plugin that would able to get this data retroactively without manually going through it.
Is there any simple shortcut for this?
The controller and action are defined in params as params[:controller] and params[:action] but there is no placeholder for "the model" as a controller method may create many instances of models.
You may want to create some kind of helper method to assist if you want:
def request_controller
params[:controller]
end
def request_action
params[:action]
end
def request_model
#request_model
end
def request_model=(value)
#request_model = value
end
You would have to explicitly set the model when you load it when servicing a request:
#user = User.find(params[:id])
self.request_model = #user
There are a number of ways that I know of:
First you can do rake routes and check out the list of routes.
Second you could put <%= "#{controller_name}/#{action_name}" %> in your application.html.erb and look at the view to see what it says. if you put it at the extreme bottom you'll always get that information at the bottom of the page.
The controller can be accessed through the params hash: params[:controller]. There isn't really a way to get the model used by a controller though, because there is no necessary correlation between any controller and any model. If you have an instance of the model, you could check object.class to get the model's class name.

I want to pass the name of a calling web page in a form in Ruby on Rails

I am quite new to Ruby. I have a landing page controller and index page that has a button on it that pops up a user input form for email addresses, etc. One of the things I want to capture and write into the database is the name of the originating landing page.
For example:
www,mydomain.com/landngpage/campaign1
Another landing page could be:
www,mydomain.com/landngpage/campaign2
The above form calls a ppc_user controller
www,mydomain.com/lppc_user/new
Can anyone help me on this? I have seen a few examples of passing data using the flash option, but I can't get this to work.
I guess you're looking for request.referer.
It tells you from which page the user comes from.
You could use a hidden field and in fill it with an instance variable created in the controller...
so in your controller index:
def index
#campaign = params[:campaign] # this is whatever parameter you have named that is "campaign1", "campaign2", etc..
end
then in your form:
hidden_field :campaign, #campaign
or with the answer given by apneadiving:
hidden_field :campaign, request.referer
and then whatever controller you are posting your message to will have a param called :campaign containing the URI that it came from or the name of the campaign parameter depending on which one you choose to use.

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.

Passing instance variable from one form to the a different controller's action in Rails

Simple question - I have a form where I create an instance of an object. After I create that object (aka submit the form), I want to redirect to a new form that is associated with a different controller's action and carry that instance variable to populate some of that form's fields.
I know I typically have 2 options, store that instance variable in the session or pass it via params. I can't use sessions (for a variety of reasons I won't bore you with). The params option I am confused on.
I should know this. :( How would you go about doing this? Any examples greatly appreciated!!
Betsy
You'll have two methods on your controller. One for each form (rendered by the associated template). The first form should post to the second action. The second action can then transfer the request parameters into instance variables, to be available within the second template.
class FooController
def bar
# setup instance variables and render first form
end
def baz
#bar_values = params[:bar]
# setup other instance variables and render second form
end
end
UPDATE0 Do it across two controllers using session.
class FooController
def new_baz
# setup instance variables and render the first form
end
def create_baz
# respond to posting of form data
session[:current_baz_values] = params
redirect_to :action => "baq", :controller => "bar"
end
end
class BarController
def baq
#baz_values = session[:current_baz_values]
# setup other instance variables and render the second form
end
end
Could you somehow just do a find of the newly created record in the other controller, and then use that to populate the info you need?
Also, unless you are using AJAX you usually don't want to have modification actions on the show page for a record. Those belong on the edit or update page. If you always want people to be able to edit a record on the same page I would either use some AJAX on the show page, or just always return the edit/update page instead...
If you do not want to use sessions, you could use the flash variable to store your parameter. Something like, flash[:my_params] = params, and then reading it back in the next request with params = flash[:my_params]. The good thing about flash, is that persists for only the next request, and auto-clears after that.
If you are looking for passing values from the client side when using Ajax, then probably setting a hidden field with the parameters is going to pass them on to the next request.

Resources