I am using Rails 4 and I have played with AJAX. I have successfully got it to work. The page that have Ajax links on it is the show.html.erb. It has a feed which have posts, and the posts has comments. To avoid loading everything I use Ajax for loading pieces of the post list and the comment list. Much like Facebook does.
I have organised it the following way: the pages controller checks if there is an ajax_action query parameter present. If it does it renders the JavaScript-response. It checks with a before_action. The value of the ajax_action are load_posts, load_comments and load_replies. They map to private methods in the pages controller.
Does this sound like a good approach when I need different Ajax methods on the same page? Or do you do it another way?
code from the pages controller:
before_action :delegate_ajax, only: :show
def delegate_ajax
ajax_action = params[:ajax_action]
unless ajax_action.nil?
ajax_handlers = {'load_posts' => 'load_posts', 'load_comments' => 'load_comments'}
send(ajax_handlers[ajax_action])
end
end
def load_posts
# Some logic (hidden for now)
respond_to do |format|
format.js { render 'load_posts', layout: false }
end
end
def load_comments
# Some logic (hidden for now)
respond_to do |format|
format.js { render 'load_comments', layout: false }
end
end
At least doing it like this keeps the routes.rb oblivious to all the AJAX routes.
Related
To avoid diving into a front-end framework for the time being, I'm building a single page application using only Rails and jQuery.
Here's the basic structure:
controller
class MainController < ApplicationController
def index
respond_to do |format|
format.html
end
end
def complex_query_1
#items = # complex query
respond_to do |format|
format.js { render 'refresh.js.erb', :locals => { :items => #items } }
end
end
def complex_query_2
#items = # a different complex query
respond_to do |format|
format.js { render 'refresh.js.erb', :locals => { :items => #items } }
end
end
end
application.js
$(document).ready(function() {
showActivityIndicator();
$.get(Routes.complex_query_1_path());
});
When a user first visits the app, they are shown #items from complex_query_1. To avoid a long time for the query to run, I've implemented a more "SPA" style of loading:
When the user visits the app, the index action is fired and serves the base layout.
Then a loading indicator and POST request for complex_query_1 are fired via js.
The action responds to js and refreshes the view via jQuery.
All internal links are AJAX so the base layout is never reloaded, preserving the "SPA" feel.
I've hit a roadblock with routing from outside the app. For example, if I navigate to /complex_query_2 from outside the app, no html layout is served. I could specify the format.html layout, but then the long query has to load before the html is served.
Is there an alternative/better way to structure the app for an SPA feel?
One solution some apps use is using fragments in the url to determine how the application should respond.
So your external link should be
/index#complex_query_2
The index path would provide the html layout, and you can parse the url in javascript to get the complex_query_2 part. Then use this to determine what action should be taken.
I haven't been able to find any useful resources online on how to do this. Basically what I'm trying to do is run a simple jQuery $('#test-div').show(); when my def show_div controller action is complete.
I've tried the following and it doesn't work. It actually renders HTML which is confusing to me. when I explicitly state that the method respond with js.
users_controller.rb
def show_div
#user = User.first
respond_to do |format|
format.js {}
end
# also tried
# render :js => "$('#test-div').show();"
end
show_div.js.erb
$('#test-div').show();
render :text should do what you are asking for -- just return raw text (which in your case happens to be JavaScript code) without doing anything to it.
maybe someone did this before me, i cant handle with this.
I have system where many users, admins. Im using extJS, JSON, Rails.
So, my question is: How in rails i can do that www.mysite.com/user/54/?format=ext_json&_dc=1306937167419&start=0&limit=50&fields=["respondent[email] CAN SEE ONLY ADMINS and just average users can see text "Sorry, only admins" ??
if simple, *.json pages can see only admins.
this is my controller
def uz
#answers = Question.find(params[:id])
if session[:user].is_admin == 1
end
respond_to do |format|
format.ext_json { render :json => #answers.to_ext_json(:class => Answer, :include => [:respondent]) }
end
end
im tried this (create before_filter) but nothing
def checking
if session[:user].is_admin == 1
WHAT TO DO HERE
end
end
You can create before_filter in controller where you can check format, action and session and return 404 error page
http://apidock.com/rails/ActionController/Filters/ClassMethods/before_filter
before_filter :admin_required
...
private
def admin_required
case params[:format].to_sym
when :ext_json
#....redirect with eror or something if not admin
end
end
I want people to be able to perform operations in ruby scripts using an API.
What options do you have in rails?
What if I want certain operations to be authenticated?
You can make any resource RESTful in rails by using resources in the routes.rb file. So if you have a table called items, then you could go resources :items. This will automagically make your controller accept any of the seven standard RESTful actions, new, create, index, etc.
Rails can deal with lots of different formats out of the box, html, json, xml, etc. So if you want someone to search your items, the code would look something like this when you go to a url that looks something like mydomain.com/items.json?search_term=HelloWorld:
class ItemsController < ApplicationController
def index
#item = Item.find_by_name(params[:search_term])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #item}
format.json { render :json => #item } # this will get returned
end
end
end
If you want operations to be authenticated, then you could use something like the omniauth gem to do OAuth authentication via facebook, or something like that. You'll need some sort of library on your client side to manage the session as well, unless you recommend doing something icky like passing your user/pass in the URL.
I'd like my application to display different data on the frontpage depending on whether the user has been logged in or not.
def index
if current_user
# render another controllers action
else
# render another controllers action
end
end
I can achieve this by using render_component. However it has been obsolete for some time. Although I can still use it as a plugin, I'm interested if anyone has a better approach.
Just take in mind that rendering another controller's view directly is not an option.
Thanks.
Just use your index method as a public proxy to the specific view you want to render.
def index
if user?
logged_in
else
logged_out
end
end
private
def logged_in
# stuff
render :action => "logged_in"
end
def logged_out
# stuff
render :action => "logged_out"
end
If it is a relatively small subsection of data, I'd probably do that in a view helper.