Let's say before a user is allowed to view the creation page of a Model, they are required to accept some terms. The workflow would be like:
User clicks on "create MODEL" -> Brought to a terms page, must accept before moving on -> MODEL creation page
If a user copies the url to the creation page, they should be redirected to the terms page.
What's the best way of going about this? I was thinking of using the session variable somehow...but I can't think of a clever enough idea. Any suggestions?
You can have the following routes:
get 'terms' => 'MODEL#terms'
get 'new' => 'MODEL#terms'
post 'new' => 'MODEL#new'
The "create MODEL" should send a GET request for /terms. Accepting the terms should POST to /new. If the user pasted /new in the URL, he'll be directed to terms instead.
Alternatively (or additionally), you can have the /terms POST a variable, :terms_accepted => true to the MODEL creation page, and on that page, check if :terms_accepted == true. If not, redirect to the terms page.
You can add the acceptance of the terms to the model itself, then you don't need a construction with an extra page and redirect if someone enters in the wrong place. Instead the user can only submit the form for creation when he/she accepts the terms.
You can add the following to the model:
class Model < ActiveRecord::Base
validates :terms_of_service, :acceptance => true
end
And then make sure you have the checkbox for this in the new %{model} form.
Also see: http://guides.rubyonrails.org/active_record_validations_callbacks.html#acceptance and Accept terms of use rails
Related
Due to business logic, I want certain resources in my Rails app to be able to be created and updated from various forms. So for example, I have a resource Business, and depending on whether the user has just signed up or has been on the site for a while, a Business can be created from /account_setup (first time user) or /businesses/new (existing users).
I want to have both forms post to the same :create method and I want the method to be smart enough to figure out which page did the posting so it can render that page if it fails a validation. Just for clarity:
GET /account_setup => POST /businesses => businesses#create => {fail} => render 'account_setup'
GET /businesses_new => POST /businesses => businesses#create => {fail} => render 'new'
Since both are looking to create a Business, it's pointless to have two separate controller methods, and I'm assuming there's a Rails-y way to solve this. What's a good way to detect which of my two forms did the post?
Use request.original_fullpath in businesses#create or embed values specific to the pages(controllers) that show the forms using hidden_field.
You can put hidden fields in the form which will store the type of the form. Keep in mind, if it's a new user then you will have to create the user before creating business assuming the models are associated.
I am a new rails developer and I have a rails app where I allow users to make a post while allowing them an option to check a checkbox. I want to be able to manually review all posts that are checked by users during their posting process. Right now everything is getting posted successfully but I want this review process in place for all checkmarked posts. What is the simplest and easiest way to put this review in place?
Here's what the post controller is right now
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Shared!"
redirect_to root_path
else
#feed_items = []
render 'static_pages/home'
end
end
For this, you better keep data-type of "reviewed" field as "boolean" (in migration files).
For putting up check box in your view, check:
http://guides.rubyonrails.org/form_helpers.html#helpers-for-generating-form-elements
Also, note that IF YOU WANT to validate the presence of boolean field (where the real values are true and false), you can't use:
validate :field_name, :presence => true
this is due to the way Object#blank? handles boolean values. false.blank? # => true
In this case, you can use:
validates :field_name, :allow_nil => true, :inclusion => {:in => [true, false]}
You can omit ":allow_nil => true", from above validation statement if you are assigning false as default value to newly created posts (and that you would require to do before validations get triggered).
I'm not talking in perspective of RoR, but in general implementation
In the database, add a field called 'Reviewed'. It holds a 'Y' or 'N'. default should be 'Y'.
Now, while saving or Updating the post make the check box flag a Y or N into this field and
in the Model, Only query for posts with 'Reviewed' = 'Y'.
This way, if the user does not check the box, the default value is 'Y' and the posts shows up, but if the user checks the box, the value shall be 'N' and you develop a review interface (i hope you already did) where after review, you mark it to 'Y'.
This is as simple as it can get. If you need to add more information on who review it, when it is reviewed etc, you can add more DB fields to store that.
Update
I work on ColdFusion technology and we have CFWheels framework which is inspired by RoR.
Based on the experience, I suggest you to use the Form helpers.
Try this code
<%= check_box_tag(:post_reviewed) %>
<%= label_tag(:post_reviewed, "Review this post") %>
And for more details, read check box tag in ruby on rails and check box form helper
I am trying to construct my first new action in rails, thanks to the help of people here I have now got the vast majority working, but due to my mis-understanding of exactly how things work the action is not performing the desired action.
I have a database called Items, which contains :id, :external_url and :click_count
My goal is to have a link which when clicked on, the user is directed to the external url and :click_count is incremented by 1.
As it stands, I have the following:
view
<%= link_to image_tag( item.picture.to_s + ".gif"), items_clickcountplusone_path(:id => item.id)%>
items_controller
def clickcountplusone
clickeditem = Item.find(params[:id])
redirect_to clickeditem.external_url if clickeditem.update_attribute(:click_count, clickeditem.click_count + 1)
end
routes.rb
get 'items/:id' => 'items#clickcountplusone', :as => :items_clickcountplusone
Using this code, the page itself loads with all the links visible.
However, when I click on a link I get directed to items/whateveridiclickedon NOT the external URL and furthermore the :click_count value does not increase from its initial value.
Am I doing this correctly? In particular is the routes line ok, it currently appears as though i am instructing it to be directed to a specific page on my site for the item, which was not my intention... Also, what is wrong with the if statement meaning the count doesn't increase?
Many thanks for your patience
The mapped route "items/:id" is already associated with the show action and have precedence.
Try associating it with another URL.
get 'items/:id/visit' => 'items#visit', :as => :items_visit
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.
Using Ruby on Rails I want a confirmation page before creating an ActiveRecord object. The user will see a preview of the item they are creating before submitting and the object being saved in the database
A common pattern;
User visits /entry/new
User enters details and clicks submit
User is redirected to /entry/confirm which displays the entry and clicks submit or edit to correct mistakes
Object is saved
How would you implement it?
Another option to solve this issue adding by a virtual confirmation attribute to your model. This way, there is no need to create a separate action for this:
class MyRecord < ActiveRecord::Base
attr_accessor :confirmation
validates_acceptance_of :confirmation, :on => :create
end
Now, your new object will not save correctly because the validation will fail on the confirmation field. You can detect this situation and present something like this:
<% form_for(#my_record) do |form| %>
...
<%= form.check_box :confirmation %> Really create this record.
<%= submit_tag('Confirm') %>
<% end %>
I would probably add a "preview" action to the routes.rb file for that model:
map.resource :objects, :new => { :preview => :post }
You would get to this preview action by POSTing the preview_object_url named route. You would need to essentially create the Object in the same way you would in your create action, like this:
def preview
#object = Object.new(params[:object])
end
This page would then POST to the create action, which would then create the Object. It's pretty straight forward.
http://api.rubyonrails.org/classes/ActionController/Resources.html
A few options
1- store the object you want to create in the session until you hit the confirm page, then just save it
2- pass around the object w/ each Post/submit from new -> details -> confirm
I would probably go with 2, since I am not prone to saving state with the session.
I'm not sure how to do this (RoR is new to me) but you could just specify the action for /new as /confirm, and then it calls create.
Right?