how to pass data between views/pages in Ruby on rails? - ruby

I have a ruby on rails app. I have a view that lists hyperlinks as such, this view is also rendered via same controller/action . when user clicks hyperlinks displayed on this page they go to the same controller/action, with a different id parameter. I want to be able to tell in my controller/view how user gets to these pages, i.e. whether user clicked on one of these hyperlinks vs user came through a different source?
<div id='list'>
<a href='controller/action/1'> some link 1 </a>
<a href='controller/action/2'> some link 2 </a>
</div>

Best approach is to add an URL parameter to the links.
<div id='list'>
<a href='controller/action/1?via=from_view'> some link 1 </a>
<a href='controller/action/2?via=from_view'> some link 2 </a>
</div>
Edit
You can access this URL parameter in your controller with params. Simple example:
class MyController < ApplicationController
def show
#via = params[:via] || "external"
end
end
<% if #via == "from_view" %>
<p>Hello coming from the view!</p>
<% elsif #via == "external" %>
<p>Hello coming from external!</p>
<% end %>
<div id='list'>
<a href='controller/action/1?via=from_view'> some link 1 </a>
<a href='controller/action/2?via=from_view'> some link 2 </a>
</div>

You can easily pass URL parameters into Rails URL helper.
For example:
<%= link_to "Link Title", some_url_helper_path(:param1 => "value1", :param2 => "value2") %>
Then you will be able to pass the parameters from the view to the controller's action.

Where the user came from is part of the HTTP spec (the referrer header) and you can access that in your controller with request.referer - you can then check if that value matches the page you want to target.
If your controller has #origin = request.referer You can then use if #origin == 'http://example.com/page-1’ in your view to switch what is being rendered.
This way you don’t have to remember to decorate all of your links with the extra param; rely on the fact that the browser is automatically adding it to headers for you.
Also see:
How to get request referer path?
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer

Related

Sinatra - delete action

I have basic Store app - I want to be able to add product to basket and then delete it using Sinatra. My adding works, but I can't make delete to work too. I had special function for that, but now I just want to see whether delete route works at all. My main app has many routes, and part I'm talking about is:
post '/basket' do #it works, adds to basket and redirects
AddToBasket.new(params).call
redirect '/'
end
delete "/basket/delete" do #it doesn't work at all and doesn't redirect
basket = BASKET.find{|p| p.id == params["id"]}
BASKET.delete(basket)
redirect "/"
end
In HTML I have:
<% basket.each do |b| %>
<form action="basket/delete" method="post">
<input type="hidden" name="_method" value="delete">
<input type="hidden" name="id" value=<%= b.id %>>
<button type="submit">Delete</button>
</form>
<% end %>
As you can see, after clicking on "Delete" button, I'm sending "id" in my params helper.
basket = BASKET.find{|p| p.id == params["id"]}
should find one specific item with this id and delete it from my big array BASKET. But it doesn't work, after clicking on "Delete" I'm otransferred to basket/delete page and I have an error, because post for basket/delete doesn't exist. It should redirect me to my index page. What's more, it doesn't delete my basket item, it still exists. I'll appreciate any help.
You need this component in your middleware pipeline use Rack::MethodOverride
Another way seems to be put set :method_override, true in your Sinatra::Base class
See this also

Ruby on rails: Button_to Check post result and update current page

In my UI, I have a table of items. Each row has a favorite button. I am using button to make a rails call to add the db association.
I've been looking into how to check the result of the post response in my button to call.
If it succeeds, I want to disable the favorite button on my page and if it doesn't I want to nothing. Is there a way to check the post response in my button to call and is there a way to stay on the page?
Heres a sample of what I have
<%= button_to create_favorite_path(res.id), class: "favorite-btn-#{res.id} btn btn-default" do%>
<i class="glyphicon glyphicon-star-empty"></i>
<% end %>
To stay on the page when you click the button, you need to add remote: true to your button call. This will make your button request an AJAX call by default.
Read more about the button_to helper here.
<%= button_to create_favorite_path(res.id), remote: true, class: "favorite-btn-#{res.id} btn btn-default" do%>
<i class="glyphicon glyphicon-star-empty"></i>
<% end %>
Then to see the response of this AJAX request, you'll need to write some javascript.
In your application.js or whatever javascript file you have on this page:
$(document).on('ajax:success', 'form', function(event, data, status, xhr) {
// do something with data or status
});
Read more about working with javascript in Rails here.

Rails 3 each method and Ajax

I'm trying to implement some Ajax in my app. A strange behaviour occurs!
It's a daycare application. When you show a specific daycare of a specific date you can add some children.
Originally a list of the children of the database is generated and when you click on one of them the page reload and a new child appears in the attendance list of the daycare. It's working fine, i just wanna add some ajax to be more userfriendly !
When you click on child to add him to the daycare, a daycare_item is created ( join table, an id of the child and the id of the daycare ).
I make the changes to make it ajax ready:
partial for the list
format.js in the daycare_item controller
remote true on the link.
It works, no more reload! But the list is updated only when you click a second time on the children list ( the last child added doesn't appears yet ). The js transaction works and if you refresh manually the page, the missing child appears.
I tried few things and here are my results:
In my partial there are
<% #daycare.daycare_items.each do |c| %>
<li><%= c.child.firstname ></li>
<% end %>
This produce the "lag" effect with one children who is not showing ( until a full refresh )
But if i put a
<%= #daycare.daycare_items.count %>
the code is update in time !
I see nothing strange in the logs.
I'm asking why the .each method make a difference?
A var was stoping a part of the code to be executed, the var wasn't wrong and doesn't generate an error.
The elements involved:
daycare_items controller
def create
#daycare = Daycare.find(params[:daycare_id]) # for Ajax
#daycare_item = DaycareItem.new(params[:daycare_item])
....
end
the create.js.erb
$('#children-list').html(" <%=j render partial: 'daycares/daycare', locals: { daycare: #daycare } %> ");
the view daycares#show
<div id="children-list">
<%= render #daycare %>
</div>
the partial ( a part of ) _daycare.html.erb
<p>counting test:<%= daycare.daycare_items.count %></p>
# here was something like this <%= #waiting.count %> #waiting is define in the daycare controller but not in the daycare_items controller
<p>
<% daycare.daycare_items.each do |dci| %>
<%= dci.enfant.prenom %>
<% end %>
</p>

Created objects do not save in database

What did I do:
create a new ruby app rails new campaigns_manager
move to campaigns_manager directory, generate first scaffold campaigns
rails generate scaffold campaign name:string and migrate
add root route root to: 'campaigns#index', as: 'campaigns'
Such a few strings of code. Then I start server to test it. Everything looks and works ok, but when I try to add a new campaign, nothing saves. After pressing "Create campaign" button I receive in console something like that:
Started POST "/" for 127.0.0.1 at 2012-04-25 22:30:40 +0300
Processing by CampaignsController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"sKom3YBDEbOcqbSt3gLGWPqBNeqkEw6M59hlwrmH4tM=", "campaign"=>{"name"=>"test"}, "commit"=>"Create Campaign"}
Campaign Load (0.3ms) SELECT "campaigns".* FROM "campaigns"
Rendered campaigns/index.html.erb within layouts/application (0.9ms)
Completed 200 OK in 37ms (Views: 35.4ms | ActiveRecord: 0.3ms)
then I redirect to campaigns list and there is no new campaign. Table campaigns in db\development.sqlite3 is empty.
Furthermore, I add print methods to campaigns controller to check if I call correct methods. And I see, that create method is not called when I press "Create campaign" button.
My campaigns/new view:
<h1>New campaign</h1>
<%= form_for(#campaign) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= link_to 'Back', campaigns_path %>
Why cannot I save my campaigns to database?
The problem is in the routes.rb file.
root to: 'campaigns#index', as: 'campaigns'
The alias as: 'campaigns' tries to consume all requests. There is no need to add an alias to your root directive, it already has one by default: as: 'root'
Your routes.rb file has to look something like this:
resources :campaigns
root to: 'campaigns#index'
More on Routes in Rails Guides
It would help to see the view code in campaigns/new, but clearly the form there is posting to /, which you can see from the log, is being handled by the index action (which is as it should be according to your routes). You have to make sure your form in campaigns/new is posting to /campaigns (which in Rails RESTful routing resolves to the create action). If you're using form_for (which I think is what the scaffold generates), it should look something like this:
<%= form_for #campaign do |f| %>

Rails forms -- accessing a variable that is not part of the form

I want to make a form for submitting the info needed to create an instance of model X and save it to the database, but I have a slight problem: I know how to add form fields like text areas and what not and then how to make those values accessible when the create method is called, but what if I want to also send make a value that is not part of the form accessible? For example, what if I want to be able to access some text in a <div> of my html document and send that to the create method for model X (so it can be stored in like a content variable or something)? How do I do that?
Short answer is you can't - to send data to the server, it has to be in an form field.
Longer answer - there are ways around this and you have several options - put the text in a textarea and style it to look like an div, or put it in a hidden field when the template is created, or use javascript to copy it into a hidden field ... all depends on what you are trying to do really. Perhaps you could give some more detail?
In your model you want to use attr_accessor
What you can do is use attr_accessor which creates a virtual attribute that you can use in the model but is discarded after that.
For example:
app/models.post.rb
class Post < ActiveRecord::Base
attr_accessor :some_variable
#now you can access 'some_variable' this variable in the model
#try Post.some_variable in the console
end
app/views/posts/_form.html.erb
<div id="form">
<div class="field">
<%= f.label :some_variable %>
<%= f.text_field :some_variable %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</div>

Resources