Render object attributes on the same site with click - ruby-on-rails

There's this button / link in my web app. It's a button for a pizza - margherita with price, ingredients, and category, all already loaded to the db. Clicking this button loads the item's id to params, which is then used to find the object.
I want the click to launch the following chain of events:
Load the id
Find the object by id
Instantly render the object and its attributes in adjacent div on the same site.
Is this possible without JavaScript, just Ruby on Rails?
I am stuck at point 3. I have an idea, but incomplete. Please, give me a hint.
PS. My idea is to render views for index and show in separate divs next to one another.
#NickM, I added your code and it's throwing ActionController::UnknownFormat error, pointing at respond_to do |format| in show_pizza method.
Here's my pizzas/index.html.haml:
%h1= t :all_pizzas
- #pizzas.each do |pizza|
= render pizza
.orders
%h1 Orders
And pizzas/_pizza.html.haml:
%tr
= link_to pizza.name, show_a_pizza_path(pizza.id), :method => :post
%br/
I am getting this error upon clicking the link in _pizza.html.erb. My show_pizza.js is now:
pizza_div = $("#orders");
pizza_div.html( "<%= j render( :partial => 'pizzas/pizza', :locals => { :pizza => #pizza } ) %>" );
What am I missing? Sorry, I don't know js.

The short answer is no. When the link is clicked you will need to either render another page or handle the data returned by the controller with Javascript. The best option would be to set up an action that responds with JSON and parse what you get back on the front end.
Even after your P.S. you will have to handle the response from the server with Javascript, unless you are okay with rendering a new page. You need to post some code, preferably routes and controller action. This would also work:
<%= link_to("Show Pizza", show_a_pizza_path(#pizza.id), :method => :post, :data => {:remote => true}) %>
routes.rb
post 'show_pizza/:id' => "pizzas#show_pizza", :as => :show_a_pizza
pizzas_controller.rb
def show_pizza
#pizza = Pizza.find(params[:id])
respond_to do |format|
format.js
end
end
views/pizzas/show_pizza.js
pizza_div = $("#the_name_of_your_div");
pizza_div.html( "<%= j render( :partial => 'pizzas/pizza', :locals => { :pizza => #pizza } ) %>" );
and then put the pizza markup in /views/pizzas/_pizza.html.erb

Related

How to implement this nested linked_to_function?

In my view I want the user to be able to browse a catalog of products. The hierarchy is as following:
Category
Product
AdditionalInfoForm
In my main view I render a partial for the categories:
#opContent
= render :partial => 'op_main_categories'
The op_main_categories partial is defined as following:
- #controller.getPortalCategories.each do |c|
= link_to_function "#{c.name}", :class => 'opCategoryHeaderText' do |page|
- partial = escape_javascript(render :partial => 'op_secondary_categories', :locals => { :c => c })
- page << "$('opContent').update(\"#{partial}\")"
When the user clicks a link in the above partial, the products are rendered by means of the op_secondary_categories partial:
- #controller.getPortalProductsForCategory(c).each do |p|
= link_to_function "#{p.name}", :class => 'opCategoryHeaderText' do |page|
- partial = escape_javascript(render :partial => 'op_did_line', :locals => { :p => p })
- page << "$('opContent').update(\"#{partial}\")"
op_did_line is plain text for now:
%p Yes, this is form! Hello?
This setup will generate the following link (for one category):
<a class="opCategoryHeaderText" onclick="$('opContent').update("<a class=\"opCategoryHeaderText\" href=\"#\" onclick=\"$(\'opContent\').update("<p>Yes, this is form! Hello?</p>\n"); return false;\">IPSDN + PVC 3yr<\/a>\n<a class=\"opCategoryHeaderText\" href=\"#\" onclick=\"$(\'opContent\').update("<p>Yes, this is form! Hello?</p>\n"); return false;\">PVC<\/a>\n"); return false;" href="#">PVC</a>
Adding the second tier of link_to_function breaks all of the code. I am no longer able to browse the hierarchy. When there is only one link_to_function present, I can browse.
This project is still using Rails 2.3. What is a better way to implement this?
My problem was solved using the answer in page.insert_html does not insert html with link_to_function (rails) by "Jose"
The code provided in the answer was put in rails/lib/rails_ext.rb

Make a Select Box that Calls a Method

I have a rails app with working reports that have tags. In the Report/Index.html.erb I want the user to be able to sort the reports by selecting a tag. They may only select one tag at a time so I feel that a select box would work best. I currently have this:
<%= select("preferences", :tag_with,
["Politics", "Technology", "Entertainment", "Sports", "Science", "Crime",
"Business", "Social", "Nature", "Other"], :prompt => "Filter Feed by:" )%>
I have a working preferences controller with a method call tag_with that updates the current tag. This code, however, only generates the select box. I want it to be that when the user selects one of the tags, it calls the tag_with method from the preferences controller.
I generated a series of link_to lines that complete the task, however I would really like a select box.
<%= link_to "Politics", :action => "tag_with", :tag => "Politics", :controller =>"preferences" %>
<%= link_to "Entertainment", :action => "tag_with", :tag => "Entertainment", :controller =>"preferences" %>
<%= link_to "Science", :action => "tag_with", :tag => "Science", :controller =>"preferences" %>
<%= link_to "Technology", :action => "tag_with", :tag => "Technology", :controller =>"preferences" %>
And so on for each tag. This works fine but is bulky and undesirable. Is there a way to do the same thing through a select box?
In your reports.js.coffee file, or whatever other js file you want.
jQuery ->
$('select#preferences').change ->
$.get 'preferences/tag_with',{ term: $('option:selected', this). val() }
Or, if you want to use regular javascript:
$(function(){
$('select#preferences').change( function() {
$.get('preferences/tag_with',{term: $('option:selected',this).val()});
});
});
A link is a GET request. The jQuery .change() method fires whenever someone makes a change. The $.get method sends a GET request to a URL and can pass data (the second argument). This data becomes your params hash, so in the example above you would get:
params[:term] #=> the value attribute of whatever option was selected by the user
See the jQuery docs on .change() and $.get() for more help.
Update
For this to refresh the page, the easiest thing would be to extract the table that you want changed into a partial, let's assume it's called _report.html.erb. The partial should look something like this:
<div id="report">
<%= render #report %>
</div>
*Note: render #report is just short for render :partial => 'report'. See http://guides.rubyonrails.org/layouts_and_rendering.html*
In your preferences controller, tag_with option you should be sure to set the #report object (or whatever else is delivering the data to your partial).
Then you should make a file called views/preferences/tag_with.js.erb and put something like this in it:
$('div#report').html('<%= escape_javascript( render #report ) %>');
This will update the report container with the new content.

Rails 3.1 pass data through a post

In my application, I've a 'warehouse' model that own several fields such as id,name,description, etc, and a boolean field called 'done'.
In my view, I want to insert a button or link field,which, when clicked, should set (through HTTP POST method) warehouse.done = true
How can I do this?
Notes: User cannot input warehouse.done field so I suppose to pass it to application as hidden field
Use link to with remote option.
<%= link_to "Vote", {:controller=>"your_controller_name", :action => 'vote',:id=>#warehouse.id, :vote=>true}, :remote=> true, :method => :put %>
In your controller
def vote
#warehouse = Warehouse.find(params[:id])
#warehouse.update_attribute(:vote, params[:vote])
respond_to do |format|
format.js
end
end
In your routes file
resources :your_controller_name do
collection do
put 'vote'
end
end
In your voting view page add new DIV to display flash notice.
<div id="flash_notice" style="display: none;"></div>
Create new RJS template "vote.js.erb" with following code.
$("#flash_notice").html("You have voted successfully");
$("#flash_notice").show("slow");
Let me know if you have any problem.
I made a couple of assumptions on the views, controller.
html
DONE
<input id="warehouse-id" type="hidden" value="24">
js
$(document).ready(function() {
$('#set-warehouse-done').click(function() {
$.ajax({
url: '/warehouse/' + $('#warehouse-id').attr('value');
type: 'POST'
data: done: true
});
});
}
warehouse_controller.rb
def update
#warehouse = Warehouse.find(params[:id])
if params[:done]
if #warehouse.update_attributes(:done, params[:done])
flash[:notice] = 'Warehouse updated successfully'
else
flash[:error] = 'Could not update warehouse'

My remote form submission is trying to render the pages/_page.js.haml file, but I want it to be pages/_page.html.haml

I'm using haml so hopefully you can understand the html going on here. It's easier to read in my opinion but some people don't like it :p
I have a form on my edit page that looks like this:
.center_col
-# I got into this weird habit of using "data-remote" for remote submission, w/e
= form_for #content, :html => {"data-remote" => true, :id => "page_editor", "data-page-id" => #content.id} do |f|
%h2
= f.label :textile, "Text", :class => 'inline'
(Parsed with
= link_to("Textile", "http://redcloth.org/textile/", :class => 'external') + ")"
%ul.fields
%li.field
= f.text_area :textile, :class => "full-field", "data-remote-preview" => preview_page_path(#content)
= display_error(:content, :textile)
%li.submit.left
= f.submit "Save Changes", :class => "rm_lr_margin"
When you submit the form I want the controller action to be rendering the _page partial. Right now the controller action is attempting to render 'pages/_page.js.haml', but I want to use 'pages/_page.html.haml' because I have an after-success jquery hook that automatically replaces the content in the edited area of the page with the new text.
Here's my action:
def update
load_content(params[:id])
#content.textile = params[:page][:textile]
if #content.save
render :partial => "pages/page", :content_type => "text/html", :layout => false, :locals => {:page => #content}
else
render :action => 'edit', :layout => false
end
end
Elsewhere...
def load_content(page_name)
#content = Page.find_by_name!(page_name)
#page = #content.name
end
So this is all working. Except it's rendering the wrong view :( When you first get to the page a section of it is populated using the 'pages/_page.html.haml' partial, and when you update the content with this ajax action I would like to use that same partial instead of having to duplicate the contents verbatim under the name 'pages/_page.js.haml'. Does anyone know what I'm missing here to make the action render haml content, not js content? When I perform the update right now it gives me this error:
Template is missing
Missing partial pages/page with {:formats=>[:js, "application/ecmascript", "application/x-ecmascript", "*/*"], :locale=>[:en, :en], :handlers=>[:rxml, :haml, :builder, :rjs, :rhtml, :erb]}
If I copy the html.haml file and name is .js.haml it works as expected.
This is the jquery I'm using to handle the events that rails.js is giving me when the form is submitted:
$('form#page_editor').live({
"ajax:beforeSend": function(xhr, settings){
$.facebox.loading();
},
"ajax:success": function(e, data, status, xhr){
$.facebox.close();
$('#page_' + $(this).attr('data-page-id')).replaceWith(data);
},
"ajax:error": function(e, xhr, status, error){
$.facebox(xhr.responseText);
}
});
Don't think that part was relevant but it shows you when in the JS I'm updating the content on the page. I suspect the problem is either in my action's render call, or the view's form_for call. Any help would be appreciated :)
You can ask for a specific format:
render :partial => "pages/page.html"

Displaying Data in form after using activerecord

I have a form that the user is going to interact with, by updating, etc. The data is being pulled from the database, so that the user can see previous data and add new ones as well. So basically when I try to execute the code below, I get an error, saying that there is no method...
#display = Sales.find(:all, :conditions => ['year =?', _year])
render :partial => "display" #which renders the table that has the form in it.
<td><%= text_field 'display', 'price'%></td> #is the input field
I have price as a column in my database :S
Thanks for the help guys! Merry X-mas
The display variable is an Array. You'll need to pass the results of the Sales.find in the :collection parameter of render partial:
#display = Sales.find(:all, :conditions => ['year =?', _year])
render :partial => "display", :collection => #display
That should render the partial once for each item that is returned by Sales.find

Resources