Ajax and Ruby on Rails with local variable? - ajax

I really don't get how to use Ajax with Ruby on Rails. I must be missing something simple.
What I want to do is to ask the user to select a date, and then make a table of documents appear, but only with the selected date (Date is an attribute of Document).
My idea is to create a local variable witch is not in my database, store the selected date in it, and then create a loop in my view saying for example #document.where(:date = date).each...
In app/controllers/documents_controller.rb, I have :
class DocumentsController < ApplicationController
def information
#documents = Document.all
#date = params[:date]
respond_to do |format|
format.html # index.html.erb
format.js{}
format.json { render json: #documents}
end
end
end
And in app/views/documents/_information.js.erb, I have:
<%= form_tag(document, :remote => true) do %>
<%= label_tag(:date, "The selected date is:") %>
<%= text_field_tag(:date) %>
<%= submit_tag %>
<% end %>
In the end, I have a field where the user puts his date, but the submit button doesn't do anything.
What do I miss ?

As discussed you need to change the flow of your app.Lets go through steps one by one
a. create your input field where you are selecting your date field. You already have your form for that
<%= form_tag(you_path_for_information_method, :remote => true) do %>
<%= label_tag(:date, "The selected date is:") %>
<%= text_field_tag(:date) %>
<%= label_tag(:portfolio, "Add portfolio") %>
<%= text_field_tag(:portfolio) %>
<%= submit_tag %>
<% end %>
In controller
def information
#documents = Document.all
#date = params[:date]
#portfolio = Portfolio.find(params[:portfolio])
respond_to do |format|
format.js{}
end
end
In your information.js.erb you can have:
$("#some_id_of_parent").html("<%=j render partial: "your_partial", locals: {portfolio: #portfolio} %>")

Related

Missing Params on Post in Rails?

I'm learning Ruby on Rails at the moment and we're making a blog app to learn about crud actions and such and I'm stuck on this create method in my controller not working as it does in the course. I'm having trouble the create method in this controller:
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
end
def index
#articles = Article.all
end
def new
end
def create
#article = Article.new(params.require(:article).permit(:title, :description))
#article.save
redirect_to #article
end
end
I get this error when trying to create an article:
ActionController::ParameterMissing in ArticlesController#create
param is missing or the value is empty: article
It seems to be getting hung up on the first line of the create method but I'm not sure why it doesn't think there's an article... Here's my new article view as well for further reference:
<h1>Create a new Article</h1>
<%= form_with scope: #article, url: articles_path, local: true do |f| %>
<p>
<%= f.label :title %><br/>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br/>
<%= f.text_area :description %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
Check whether your parameters coming under hash with key article like this -
{"article"=>{params}}
Also initiate Article object in new action.
You can redefine the params to permit like this:
in controller new method create object
#article = Article.new
and in form HTML add one more option use method: "post"

Trying to get nested objects to be given parent ids

Alright, So I have days, tracks, and events. When I create a track, it is given the proper day_id along with its own track_id . When I try to create an event, I want it to be given the appropriate day_id and/or track_id.
So when I pull up a day it should only show the tracks and events that as associated with the day. An event should exist in a track, which exists in a day.
So, this is basically a calendar that shows a daily schedule of different tracks, and the events within the tracks.
Also, my events table in my db has a track_id and a day_id.
Here is my routes.rb
resources :days do
resources :tracks do
resources :events
end
end
My new/create methods from my events_controller.rb
def new
#day = Day.find(params[:day_id])
#track = Track.find(params[:track_id])
#new_event = Event.new
end
def create
#day = Day.find(params[:day_id])
#track = Track.find(params[:track_id])
#events = #track.events
#new_event = Event.new(params.require(:event).permit(:name,:start_time, :end_time))
if #new_event.save
flash[:notice] = "Saved"
redirect_to #day
else
flash[:error] = "Error"
render :new
end
end
And here is where I am trying to create a new event in my events.new.html.erb
<%= form_for [#day, #track, #new_event] do |f| %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control', placeholder: "Enter the event" %>
<%= f.label :start_time %>
<%= f.text_field :start_time, class: 'form-control', placeholder: "Enter a start time"%>
<%= f.label :end_time %>
<%=f.text_field :end_time, class: 'form-control', placeholder: "Enter a start time"%>
<%= f.submit "Save", class: 'btn btn-success' %>
<% end %>
Thanks for the help, I'm pretty sure I attached everything that was needed!
You should create the event from the track:
#new_event = #track.events.new
This will create an event with already the appropriate track_id inside.
However, this does work...
#new_event = #track.events.new(params.require(:event).permit(:name, :start_time, :end_time))

Rails 3 render partial outside view?

I am working on a multisite for a client for a skateboarding website. So far everything is great but I am starting to get stuck on the whole partial thing. I have a site and site has_many :albums(Album also belongs to site) but when I try to render albums from a site on the sites homepage i get undefined method `model_name' for NilClass:Class?
I have am trying to render albums/_album.html.erb on the sites/show page to display a site latest's album on the homepage of the site.
Albums Controller
class AlbumsController < ApplicationController
def index
#albums = Album.all
end
def show
#album = Album.find(params[:id])
end
def new
#album = Album.new
end
def edit
#album = Album.find(params[:id])
end
def create
#album = current_site.albums.build(params[:album])
if #album.save
redirect_to albums_path, :notice => 'Album was successfully created.'
end
end
def update
#album = Album.find(params[:id])
if #album.update_attributes(params[:album])
redirect_to album_path(#album), :notice => 'Album was successfully updated.'
end
end
def destroy
#album = Album.find(params[:id])
#album.destroy
end
end
Sites Controller
class SitesController < ApplicationController
def index
#sites = Site.all
end
def show
#site = Site.find_by_subdomain!(request.subdomain)
end
def new
#site = Site.new
end
def edit
#site = Site.find(params[:id])
end
def create
#site = Site.new(params[:site])
if #site.save
redirect_to #site, :notice => 'Signed up!'
end
end
def update
#site = Site.find(params[:id])
if #site.update_attributes(params[:site])
redirect_to #site, :notice => 'Site was successfully updated.'
end
end
def destroy
#site = Site.find(params[:id])
#site.destroy
end
end
Site Show.html
<p id="notice"><%= notice %></p>
<p>
<b>First name:</b>
<%= #site.first_name %>
</p>
<p>
<b>Last name:</b>
<%= #site.last_name %>
</p>
<p>
<b>Subdomain:</b>
<%= #site.subdomain %>
</p>
<%= render :partial => 'albums/album'%>
<%= link_to 'Edit', edit_site_path(#site) %> |
<%= link_to 'Back', sites_path %>
Albums/_album.html.erb
<%= div_for #album do %>
<h2><%= #album.title %></h2>
<%= image_tag #album.photo.url(:small) %>
<% end %>
Am I missing something in my albums controller?
In your show.html, you need to pass in the collection of albums to the render method
<%= render :partial => 'albums/album', :collection => #site.albums %>
Within the _album.html.erb partial, you need to reference the album attribute as a local attribute, like so
<%= div_for album do %>
<h2><%= album.title %></h2>
...
You can read more about partials here 3.4.5 Rendering Collections

Rails 3.1 Ajax forms don't show validation

I'm using updated pre Ruby on Rails on Ruby 1.9.2 (with rvm), and made a new test application with
$ rails generate scaffold Project name:string
and
class Project < ActiveRecord::Base
validates_presence_of :name
end
I change
<%= form_for #project do |f| %>
to
<%= form_for #project, :remote => true do |f| %>
I can now still (without any changes in the controller) add new items to the project. If I try to add with empty in the name field, it will not add anything (validates_presence_of :name stops this), but I don't get any validation error messages. I have tried the same on an application converted from 3.0 I'm working on with same results. Here I had:
class KursController < ApplicationController
# GET /kurs
# GET /kurs.xml
respond_to :js, :html
and:
def update
#kur = Kur.find(params[:id])
#kur.update_attributes(params[:kur])
flash[:notice] = "Lagret" if #kur.save
respond_with( #kur, :layout => !request.xhr? )
end
In 3.1 I get no validation error messages. Is this because of a bug in Ruby on Rails 3.1 or something I should do different?
You are missing to call these errors. Do something like this:
<%= form_for #project do |f| %>
<%= render :partial => 'my_error_messages_for', :locals => {:collection => #project} %>
In "_my_error_messages_for.html.erb":
<% if collection.errors.any? %>
<ul>
<% collection.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
You can create a helper for this work.
I don't believe that Ruby on Rails will automatically include the partial that you've requested. You'll need to add some JavaScript code to get it to work correctly. Something like this I imagine:
// Application.js
$("form").bind("ajax:success", function (event, data, status, xhr) {
$(event.target).replaceWith(data);
});

How can I use do edit-in-place on three different models from a View for a model those three belong_to?

I would like to enable edit-in-place functionality in a View that displays values from different models:
This is what I use currently and it does NOT work, but would like some alternatives:
I have a model called Campaign. In the controller, I do the following to list, in order, the three Models that belong_to a Campaign:
<% #campaign_events = campaign_events %>
<% #campaign_events.each do |campaign_event| %>
<% model_name = campaign_event.class.name.tableize.singularize %>
<p>
<%= link_to campaign_event.title, send("#{model_name}_path", campaign_event) %>
<span class='model_name'>(<%= model_name.capitalize %>)</span>
<%= campaign_event.days %> Days
</p>
<% end %>
campaign_event is a campaign_helper defined as:
module CampaignsHelper
def campaign_events
return (#campaign.calls + #campaign.emails + #campaign.letters).sort{|a,b| a.days <=> b.days}
end
end
I want to be able to click on the numerical value for Days when looking at the view/campaign/show and edit the value for :days (in this case, displayed as campaign_event.days
I'm not really sure about it, but I'll try to help... I believe something like the following may work for you:
# calls controller
in_place_edit_for :call, :days
# emails controller
in_place_edit_for :email, :days
# letters controller
in_place_edit_for :letter, :days
# campaign view
<% #campaign_events = campaign_events %>
<% #campaign_events.each do |campaign_event| %>
<% controller_name = campaign_event.class.name.tableize %>
<% model_name = controller_name.singularize %>
<p>
<%= link_to campaign_event.title,
send("#{model_name}_path", campaign_event) %>
<span class='model_name'>(<%= model_name.capitalize %>)</span>
<%= in_place_editor_field model_name, :days, {},
:url => {
:controller => controller_name,
:action => 'set_#{model_name}_title',
:id => campaign_event.id} %> Days
</p>
<% end %>
There's somethings I don't know exactly how to do:
1) in_place_editor_field model_name
I believe this won't work, but I don't know how to pass the model_name.
2) :action => 'set_#{controller_name}_title'
Not sure about it also. Just doesn't look right.
Anyway, hope it helps you... and forgive me if this is completely stupid.

Resources