I am new using Ruby On Rails so this question may seem stupid. I've been searching a lot tutorial and sort of understand what I could do, but what the code looks like exactly? how i should implement this and where to put them still confuse me.
I have a database called note which has two attributes, :note whose type is text and a foreign key called user_name whose type is string. In the main.html.erb, I have my main page and also a note pad whose is a text area. here's part of main
<div class="four columns" id="note">
<textarea id="area" style="width:250px; height:300px;" placeholder="Your notes starts here"><%= #note %></textarea>
<div id="clear" class="primary btn pretty">Clear</div>
<div class="secondary btn pretty"><%= link_to 'Save', controller: 'main', action: 'update_note', :remote => true, :method => :put %></div>
</div>
By the way, I'm using Gumby. so My button is called "Save". I want the user to input their note in the txtfiled and when they click the "save" button, it will update the note database in the row according to the user_name.
So my question is, should I write a action on main_controller or notes_controller. How should I do it. Sample could would be much helpful since I tried different way and it is really frustrating.
I tried putting the code in the main_controller like this:
def update_note
#note = Note.find_by(user_name: session[:user_name])
respond_to do |format|
if#note.update_attributes(params[:note])
format.html { redirect_to #note, :notice => 'Note was successfully updated.' }
format.js
else
format.html { render :action => "edit" }
format.js
end
end
end
as well as tried to put code in notes_controller. but I get "No route match"
I totally mess up. And it'd due tomorrow! thanks for any help. It's so nice to refers me some link of tutorial but the anything related to my code would be more helpful!
Thanks!
You would have to use a form for this or you can also do it by using Jquery Ajax.
First add a gem 'jquery-rails' to Gemfile and then do bundle install.
in Gemfile:
gem 'jquery-rails'
Next require both jquery and jquery_ujs into your /app/assets/javascripts/application.js manifest like this:
//= require jquery
//= require jquery-ujs
in /views/layouts/application.html.erb:
<%=javascript_include_tag "application.js"%>
#I guess it will be already there
in /views/main/home.html.erb
<%= form_tag({:controller=>'main',:action=>'update_note'},:method=>:post,:id=>"update_note",:name=>'note_form',:remote=>true) do %>
<div class="four columns" id="note">
<textarea id="area" name="note" style="width:250px; height:300px;" placeholder="Your notes starts here"><%= #note %></textarea>
<div id="clear" class="primary btn pretty">Clear</div>
<div class="secondary btn pretty"><%= submit_tag 'Save' %></div>
</div>
<%end%>
<div id="updated">
</div>
in main_controller.rb
def update_note
#note = Note.find_by(user_name: session[:user_name])
if #note.update_attributes(params[:note])
#updated = "true"
format.js
else
#updated = "false"
format.js #this will load update_note.js.erb
end
end
Create a file update_note.js.erb under ../views/main/
Now in app/views/main/update_note.js.erb:
<%if #updated == "true"%>
$('#updated').html("Your post has been successfully updated").show();
<%elsif #updated == "false"%>
$('#updated').html("Your post could not be updated").show();
<%end%>
And at last add this in /config/routes.rb:
#in Rails 3
#match "main/update_note" => "main#update_note"
#in Rails 4
match 'main/update_note' => 'main#update_note', :via => [:post]
Open this home page where you have the update_note textbox, open up console in Chrome/ Firefox. Now check under Net tab in the console (in Firefox) or Network tab (in Chrome) and check for the request being made when you click on Save button. Let me know if you find any difficulty.
Related
I got error when using controller to read text file:
#my_page.html.erb
<input id="test_input" >
#controller.rb
def my_page
File.open($directory+'\test.TXT', 'r') do |f1|
$line = f1.readlines
f1.close
end
respond_to do |format|
format.js
end
end
#my_page.js.erb
el = document.getElementById(test_input);
el.innerHTML='<%=$line$>';
It load blank page without input and I don't know why, Please correct me if I'm wrong.
I think I understand what you are doing. Here is what you can do.
#controller.rb
def my_page
#text= File.open('your_file.txt').read
end
#my_page.html.erb
<input id="test_input" value="<%= #text %>" />
When you refresh your page, the text should show up on your page. No need to use Javascript now. You should use it when you are requesting the resource using AJAX.
If you would like to update the value of the text box, you need to add a new action in your controller and update your routes.rb accordingly. Also, it's always a good idea to use form helpers that Rails provide to utilize security feature (CSFR token), as shown below. If you have a model for the text field, you can use a form_for helper. You can read about them in
http://guides.rubyonrails.org/form_helpers.html
Here is the code, nonetheless.
#my_page.html.erb
<%= form_tag save_text_path do %>
<%= text_field_tag :test_input, #text %>
<%= submit_tag "Update" %>
<% end %>
# in your controller
def save_text
updated_text = params[:test_input]
# do something with the text
end
# in your routes.rb
post "save_text" => "your_controller_name#save_text", as: "save_text"
I am using below button_to tag inside view file (index.html.erb)
<textarea rows="2" cols="20"><%=#write_date%></textarea>
<%= button_to t(:get_date_write_new),channel_get_dates_path(#channel, :write => 1) %>
when i click the button it will get date from device and prints it on screen.
my question is that how do i make call to function "channel_get_dates_path(#channel, :write => 1)" continuously, and display the date in textarea without refreshing the page. by pressing the button only once?
my controller file:
class GetDatesController < ApplicationController
include DateUtilities
before_filter :require_user, :set_channels_menu
def index
#channel = current_user.channels.find(params[:channel_id])
#write_date = #channel.get_dates.write_dates.first
end
def create
#channel = current_user.channels.find(params[:channel_id])
#get_date = #channel.get_dates.write_dates.first
if (#get_date.nil?)
#get_date = GetDate.new
#get_date.channel_id = #channel.id
#get_date.user_id = current_user.id
#get_date.write_flag = params[:write]
end
#get_date.get_date = generate_get_date
#get_date.save
redirect_to channel_get_dates_path(#channel)
end
end
and i have date generation file(myapp/lib) as:
module DateUtilities
def generate_get_date
require 'rubygems'
require 'socket'
hostname = '127.0.0.1'
port = 2000
streamSock = TCPSocket.new( hostname, port )
streamSock.write "ON"
while line = streamSock.gets
k = line
end
k
end
end
In order to change the page without refreshing it, you need AJAX.
This can be done quite easily in rails by passing a :remote => true attribute in a form :
<%= form_tag(myupdate_path, :remote => true) do %>
<%= form_tag(channel_get_dates_path(#channel, :write => 1), :remote => true) do %>
<input type="submit" value="Get Today's Date">
<input id="thedate" type="text" value="<%=#write_date%>">
<% end %>
<% end %>
The remote option will call the myupdate method in your controller, and tell it to render a javascript view instead of a html view. Let's say you have in your controller :
def myupdate
#thedate = params['wathever'] # get the params from the form
end
Then you can add your javascript method in myController/myupdate.js.erb ( instead of myupdate.html.erb). Assuming you're using jquery, this would be
$("#thedate").val("<%= #thedate %>") # dynamically update
By doing this you're able to get the params from the form, process it as you want with a controller, and tell javascript to update your page according to whathever you just put in your instance variable.
Edit : I used your form as the example. Hopefully the javascript is now more clear : the idea of the javascript view is to get the "thedate" html element in your page, and set its value according to the updated instance variable #thedate. This is where you tell javascript to dynamically update your page.
Hope this helps
#Aurel,thanks for your suggestions. i followed your steps.
in my view file changed the code as:
<%= form_tag(channel_get_dates_path(#channel, :write => 1), :remote => true) do %>
<input type="submit" value="Get Today's Date">
<input type="text" value="<%=#write_date%>">
<% end %>
after this when i press the submit button the update method is called(and i can see that device is sending the date), but the date is not displaying in text field. when i refresh the page the last obtained date from device is displayed in text field.
Is it possible to display the date every time when press submit button?
I am using Ruby on Rails 3 with Prototype/Scriptaculous and I am trying to update a 'div' content after that ActiveRecord values are changed, without reload the page.
In the "edit.html.erb" I have:
...
<div id="test_id">
<%= #account.name.to_s %>
</div>
<%= link_to_function( "Make test" ) do |page|
page.replace_html :test_id, #account.name.to_s
end %>
...
Before clicking on "Make test" I update the '#account.name' value, even via AJAX. Then, clicking on "Make test", the template doesn't changes.
These are steps:
I show the page
I update '#account.name' via AJAX
I click on "Make test"
'div' with 'id="test_id"' doesn't change!
What am I doing wrong?
P.S.: I think that #account is not reloaded in the page, also if his values are changed in the database. If so, what should I do?
I have seen the Railscasts "AJAX with RJS" and I followed an example in that (it is like the my), but it doesn't work for me.
If you have rendered edit.html.erb when the value of #account.name is "George", the HTML will remain the same (with the value "George") until you refresh it. Your call to link_to_function is, on page load, rendering an html link that calls javascript that replaces the inner html of the "test_id" div with 'George'. Unless you replace that HTML, it will always replace the inner html of that div with 'George'.
It's hard to recommend a solution without knowing exactly what you'd like to do...
updated to have more detail:
If you are making an AJAX call that changes the value of the account name on the server to "Fred", and want that change to appear on the page, you should refresh the parts of the page that use that value in that same AJAX call (that same controller action).
Your link_to_function generates HTML like this (if #account.name was 'George' when the page was rendered):
<a onclick="try { Element.update("test_id", "George"); ... >Make test</a>
It is not an ajax call, it is just a link that executes javascript. If you want to make it an ajax call that finds the latest value of the account name and refreshes the test_id div, do something like this:
<%# you need prototype included, but it should probably be in application.rhtml %>
<%= javascript_include_tag "prototype.js" %>
<div id="test_id">
<%= #account.name.to_s %>
</div>
<%= link_to_remote "Make test", :url => { :controller => "account", :action => "change_name" } %>
The 'Make test' link will now perform an AJAX call to the 'change_name' method in the 'account' controller. This method would look something like this:
def change_name
# here you would load the account from the db; I'm cheating
#account = Account.new(:name => "Fred")
render :update do |page|
page.replace_html :test_id, :text => #account.name.to_s
end
end
I am learning Ruby and Rails.
I have a Ruby on Rails project that tracks jobs a server is running. Right now, when I manually create a new job, it announces:
flash[:notice] = "Created job job number #{update.id}."
I would like to turn the #{update.id} into a link to the job on the job list.
The URL for going to the job is jobs/list?job=1234 where 1234 is the update.id that is displayed in the flash notice.
Is it possible to put a link into a flash[:notice] statement? Or do I need to re-work how this message is being displayed in order to turn it into a link?
Don't forget to add .html_safe at the end of the notice, if you're using Rails3.
So it would say flash[:notice] = "Your message".html_safe
The #template instance variable is no longer available in Rails 3.
Instead you can use this in your controller:
flash[:notice] = "Successfully created #{view_context.link_to('product', #product)}.".html_safe
Hope this helps :)
I may be missing something obvious, but you should just be able to do
flash[:notice] = %Q[Created job number #{update.id}]
and then just make sure you're not escaping the content of the flash when you display it in your view.
As nas commented, link_to is not available from your controller unless you include the appropriate helper module, but url_for is. Therefore I'd do pretty much what Emily said except use url_for instead of hardcoding a URL.
e.g. if a job were defined as a resource in your routes:
link = "#{update.id}"
flash[:notice] = "Created job number #{link}"
The selected answer didn't work for me. But the answer from this post worked. I'm using Rails 4.2.4 by the way. With guidance from the answer I linked, here's how I did it:
View
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name %>">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<div id="flash_<%= name %>"><%= sanitize(msg) %></div>
</div>
<% end %>
Controller
flash[:success] = "Blah blah. #{view_context.link_to('Click this link', '/url/here')}"
The magic is the sanitize method.
I didn't need to use .html_safe as well.
Building on Dorian's answer, here's an internationalized flash with a link in it:
flash[:notice] = t('success', go: view_context.link_to(t('product'), #product)).html_safe
Where your translation (e.g. a YAML file) might contain:
en:
success: "Successfully created a %{go}"
product: "product"
it:
success: "%{go} creato con successo"
product: "Prodotto"
You can use an alias in your controller to the link_to function, or the RailsCast recipe:
"Created job job number #{#template.link_to update.id,
:controller => 'jobs', :action => 'list', :job => update.id}."
http://railscasts.com/episodes/132-helpers-outside-views
You can always use the Rails link_to helper:
flash[:notice] = "Created job job number #{link_to update.id, :controller => 'jobs', :action => 'list', :job => update.id}."
I am running into a strange problem.
I simply want to display a loading icon on the page when pressing a button.
If my call to form_remote_for contains Ajax options then the RJS script does not work.
This works ("loading" is hidden by the controller and RJS):
View:
<%=form_remote_for(:job, #job, {:url => {:action=>:create}}) do |f| %>
[...]
<div id="loading">Loading...</div>
controller:
def create
render :action => "create.js.rjs"
end
RJS:
page.hide 'loading'
This does not work (just adding :loading=> and loading is shown by the view but not hidden back by the controller as it was before):
<%=form_remote_for(:job, #job, {:url => {:action=>:create}}, {:loading=>"$('loading').show()"}) do |f| %>
[...]
<div id="loading" style="display:none;">Loading...</div>
So if my call to form_remote_for contains Ajax options then the RJS script does not work. Why?
Change your form to:
<% form_remote_for (:job, #job, :url => {:action => :create}, :loading =>"$('loading').show()") do |f| %>
# ...
<% end %>
Make sure create is:
# POST /jobs
# POST /jobs.xml
def create
render :action => "create.js.rjs"
end
And make sure your create.js.rjs is:
page.hide 'loading'
This scenario works for me. As you had it, it was returning the erb in the template because it was posting to "new" -- based on a quick scaffold implementation I did. Now I might still be missing something because as I said before the massive edit, I'm new, but this should get you going.
EDIT: Removed "is this your code?" post.
While not directly answering your question of "why" it isn't working, have you looked at using the :loaded parameter to hide the loading DIV rather than rely on the rjs file?
Assuming your using prototype you should use the Ajax.Responders to do the show/hide:
Ajax.Responders.register({
onCreate: function() {
Ajax.activeRequestCount++;
if($('loading') && Ajax.activeRequestCount>0) {
Effect.Appear('loading',{duration:0.4,queue:'end'});
};
},
onComplete: function() {
Ajax.activeRequestCount--;
if($('loading') && Ajax.activeRequestCount==0) {
Effect.Fade('loading',{duration:0.4,queue:'end'});
};
}
});
You can stick it in public/javascripts/application.js
Unobtrusive javascript - will work on any page with a hidden loading div and ajax events.