How Does the ActiveResource Get Call show find(:first) or find(:last) requests? - sinatra

I am developing a Sinatra server that can accept calls from ActiveResource, but can"t determine how to identify Get calls specificying :first or :last.
In Rails 3
User.find(:first) => localhost.com/user.xml
User.find(:last) => localhost.com/user.xml
This works exactly as it should according to the examples in the ActiveResource documentation.
It is clear what path they request (the same one), but it is not clear what happens to the :first or :last elements. I can not find them in the request object on the Sinatra server. Does anyone know what happened to those references?
Thanks for your help.

Code from ActiveResource library
def find(*arguments)
scope = arguments.slice!(0)
options = arguments.slice!(0) || {}
case scope
when :all then find_every(options)
when :first then find_every(options).first
when :last then find_every(options).last
when :one then find_one(options)
else find_single(scope, options)
end
end
last and first just methods from Enumerable module

Related

How to switch from Sqlite to Postgres while installing Warden on Sinatra on Heroku

This is partly a problem-solving question, partly a "I'm trying to understand what's going on" question. I hope that's allowed. Basically, I'm trying to get Warden user authentication to work with Ruby/Sinatra and Postgres on Heroku.
I got a lot of help from this handy (but oldish) tutorial.
From some Rails experience I am a bit familiar with Active Record. The tutorial didn't mention anything about creating a migration for the User class. I went ahead and made my own migration, with my own properties ("name", "email", "password"), only to discover later that, lo and behold, the properties I put in that migration weren't being used by (and in fact were rejected by) the actual model in use. When I examined the object instances in the database, I found that they had only the properties Warden provided for me ("username" and "password").
I'm just trying to understand what happened here. I migrated down my (apparently unnecessary and ignored) Users migration, and nothing happened. I mean that I was able to create User instances and log in using them just as before.
Then it occurred to me that this old Warden tutorial (from 2012) uses something called DataMapper, which does what Active Record would do today. Is that right? They are both "ORMs"? I'm still confused about why Sinatra completely ignored the User migration I did. Maybe it's just using a different database--I did notice wht might be a new db.sqlite database in my main file. Pretty sure the one I created for Active Record was db/madlibs.sqlite3.
Although it works on my local machine, I'm pretty sure it won't work on Heroku, since they don't support sqlite (pretty sure). That then means I'll have to go back to the Warden documentation and figure out how to get it to work with my Postgres database...right? Any pointers on how to get started with that? Since this will be my first project using any authentication library like Warden, it's pretty intimidating.
Here's what I have so far (repo):
app.rb:
require 'sinatra'
require 'sinatra/activerecord'
require 'sinatra/base'
require './config/environment'
require 'bundler'
Bundler.require
require './model'
enable :sessions
class Madlib < ActiveRecord::Base
end
class SinatraWardenExample < Sinatra::Base
register Sinatra::Flash
end
use Warden::Manager do |config|
config.serialize_into_session{|user| user.id }
config.serialize_from_session{|id| User.get(id) }
config.scope_defaults :default,
strategies: [:password],
action: 'auth/unauthenticated'
config.failure_app = self
end
Warden::Manager.before_failure do |env,opts|
env['REQUEST_METHOD'] = 'POST'
end
Warden::Strategies.add(:password) do
def valid?
params['user']['username'] && params['user']['password']
end
def authenticate!
user = User.first(username: params['user']['username'])
if user.nil?
fail!("The username you entered does not exist.")
elsif user.authenticate(params['user']['password'])
success!(user)
else
fail!("Could not log in")
end
end
end
...non authentication routes...
post '/auth/login' do
env['warden'].authenticate!
flash[:success] = env['warden'].message
if session[:return_to].nil?
redirect '/'
else
redirect session[:return_to]
end
end
get '/auth/logout' do
env['warden'].raw_session.inspect
env['warden'].logout
flash[:success] = 'Successfully logged out'
redirect '/'
end
post '/auth/unauthenticated' do
session[:return_to] = env['warden.options'][:attempted_path]
puts env['warden.options'][:attempted_path]
flash[:error] = env['warden'].message || "You must log in"
redirect '/auth/login'
end
get '/protected' do
env['warden'].authenticate!
#current_user = env['warden'].user
erb :protected
end
model.rb (just the User model):
require 'rubygems'
require 'data_mapper'
require 'dm-sqlite-adapter'
require 'bcrypt'
DataMapper.setup(:default, "sqlite://#{Dir.pwd}/db.sqlite")
class User
include DataMapper::Resource
include BCrypt
property :id, Serial, :key => true
property :username, String, :length => 3..50
property :password, BCryptHash
def authenticate(attempted_password)
if self.password == attempted_password
true
else
false
end
end
end
DataMapper.finalize
DataMapper.auto_upgrade!
It seems like this repo might have solved the problems I'm facing now. Should I study that? The Warden documentation itself is pretty forbidding for a relative beginner. For example, it says "Warden must be downstream of some kind of session middleware. It must have a failure application declared, and you should declare which strategies to use by default." I don't understand that. And then it gives some code...which I also don't quite understand. Advice?? (Should I be working with a teacher/mentor, maybe?)

How to use net/xhr.getRequestCount()

The documentation for the net/xhr module includes a method called getRequestCount() supposed to
Return[s] the number of XMLHttpRequest objects that are alive (i.e., currently active or about to be).
Both calling
const xhr = require("sdk/net/xhr");
var x = new xhr.XMLHttpRequest();
x.getRequestCount();
and
xhr.getRequestCount();
failed with a TypeError. In the debugger, you see that neither XMLHttpRequest nor its prototype have such function. (jpm version 1.0.5)
How are you supposed to use it?
Apparently this function was removed quite a while back(https://hg.mozilla.org/mozilla-central/rev/b57750ca97bf from 2013) and nobody remembered to update the documentation.
So in short: you're not supposed to use it.

Rails 4 with CanCan: unknown attribute error after including load_and_authorize_resource

I'm working in Rails 4 and have gotten CanCan to work well with instructions from this issue, except for one use case that I think might be relatively common.
I have a Comment model, which has_many :comments, through: :replies for nested comments. All of this is working well, until I add load_and_authorize_resource to my comments controller. The problem seems to stem from a hidden field sending an optional :parent_comment_id attribute to my create action.
I've permitted this attribute via strong parameters:
def comment_params
params.require(:comment).permit(:content, :parent_comment_id, :post_id, :comment_id, :user_id)
end
So that I can create the association if a :parent_comment_id is included:
if comment_params[:parent_comment_id] != nil
Reply.create({:parent_comment_id => comment_params[:parent_comment_id], :comment_id => #comment.id})
end
But once I add load_and_authorize_resource, I get an unknown attribute error for :parent_comment_id. What am I missing?
Solution came to me in my sleep. Here's what I did to solve the problem:
The only reason comment_params wasn't normally having a problem on create, was because I was excluding the extra :parent_comment_id parameter, like this:
#comment = post.comment.create(comment_params.except(:parent_comment_id))
When CanCan used the comment_params method however, it did no such sanitation. Hence, the problem. It would have been messy to add that sanitation to CanCan on a per-controller basis, so I did what I should have done all along and instead of passing the :parent_comment_id inside :comment, I used hidden_field_tag to pass it outside of :comment and accessed it through plain, old params.
I hope this helps someone else who makes a similar mistake!

How to add some extra parameter in the airbrake parameters for JS errors

When we are sending the airbrake error to the airbrake server, by default it includes the controller name and action name.
But the question is that I want to add some extra parameters like username, email of the current user. If anyone has any idea please suggest how to do that?
In my layout application.html:
- if ['development'].include?(Rails.env)
= airbrake_javascript_notifier
= render :partial => 'layouts/airbrake_notifier'
and in the partial I have written:
Airbrake.errorDefaults['name'] = "#{current_user.name}";<br/>
Airbrake.errorDefaults['email'] = "#{current_user.email}";<br/>
Airbrake.errorDefaults['phone'] = "#{current_user.phone}";<br/>
Airbrake.errorDefaults['title'] = "#{current_user.title;<br/>
Not a great solution, but the Airbrake Knowledge Base recommends essentially patching the airbrake gem source of the lib/airbrake/notice.rb file.
def initialize(args)
...
self.parameters = args[:parameters] ||
action_dispatch_params ||
rack_env(:params) ||
{'username' => current_user.name}
It would certainly be better to have this be configurable without patching source.
What I've done instead is simply add a few pieces of data to the session (current_user.name mainly), since session data is sent with the request. I wouldn't do this for more than a few little pieces of data.
We've just added getting current users into the Airbrake Gem.
https://github.com/airbrake/airbrake/wiki/Sending-current-user-information
You'll soon be able to sort by current user in an upcoming redesign of the UI.

Difference between uri_for and uri_for_action

What is the difference between $c->uri_for and $c->uri_for_action methods of Catalyst.
Which one to use? And why?
#Devendra I think your examples could be somehow misleading if someone reads them.
uri_for expects path (and not action). It return an absolute URI object, so for example it's useful for linking to static content or in case you don't expect your paths to change.
So for example, let say you've deployed your application on domain example.com and subdir abc (example.com/abc/): $c->uri_for('/static/images/catalyst.png') would return example.com/abc/static/images/catalyst.pn, or for example: $c->uri_for('/contact-us-today') would return example.com/abc/contact-us-today. If you decide later to deploy your application under another subdirectory or at / you'll still end up with correct links.
Let say that your contact-us action looks like: sub contact :Path('/contact-us-today') :Args(0) {...} and you decide later that /contact-us-today should become just /contact-us. If you've used uri_for('/contact-us-today') you'll need to find and change all lines which points to this url. However you can use $c->uri_for_action('/controller/action_name') which will return the correct url.
dpetrov_ in #catalyst says:
If the paths are likely to change, uri_for_action is better idea.
I found below difference between $c->uri_for and $c->uri_for_action
Consider
Othercontroller.pm
__PACKAGE__->config(namespace => 'Hello');
.
.
.
sub bar: Local{
$c->res->redirect($c->uri_for('yourcontroller/method_name'));
$c->res->redirect($c->uri_for_action('yourcontroller/method_name'));
}
Yourcontroller.pm
sub method_name: Local{
print "In Yourcontroller:: method_name"
}
In case of $c->uri_for the url changes to
http://localhost:3000/Hello/yourcontroller/method_name
However for $c->uri_for_action the url changes to
http://localhost:3000/yourcontroller/method_name
So the namespace gets added in case of uri_for.