undefined method `activated?' - ruby-on-rails

I'm trying to implement Authlogic in Rails 3 and have just been having headache after headache...I'm extremely new to rails, so please forgive me for not being an expert. I followed the railscast on the subject which has been really helpful, but as soon as i submit my create new user form via the actual website I get this:
undefined method `activated?'
app/controllers/users_controller.rb:37:in `create'
Any help would be SO appreciated...had a headache with this tonight...
Code from create method:
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Registration successful."
else
render :action => 'new'
end
end

If anyone else hits this issue - regenerate your user_session model and fill it with:
class UserSession < Authlogic::Session::Base
def to_key
new_record? ? nil : [ self.send(self.class.primary_key) ]
end
end
This fixed it for me...seems to be an error surrounding that model at the very least so take it back to basics!

The problem for me was the existence of a user_sessions table. If you created the UserSession model through a generator, you have a migration that creates that table.
Simply deleting the table (both in test and development databases) and the migration file solved the problem for me.
Cheers,
-- José

Related

getting Id from created record in rails

New web developer here, and I think I may be missing some very fundamental knowledge. Given the code
> def create
> #post = Post.new(post_params)
> if #post.save
> redirect_to #post
> else
> render "new"
> end
end
after saving the post, it redirects to show page, due to this "redirect_to #post", how can I do the same thing with "redirect_to: action => "show", :id => 5" I have to pass the ID now, how to retrieve the ID from #post object?
so only I can pass the Id to redirect page.
can I stop the compiler here, like debugger in js?
To answer your question of "I may be missing some very fundamental knowledge" yes, you might be. An object in Rails like #post is usually a database record. You can access any of it's columns in the DB by using the column name as a method:
#post.id
returns:
5 #or whatever the post id is.
If your post table has a column of "title" you can access it with
#post.title
returns:
"This is an awesome post"
I would highly recommend you view some Ruby and some Rails tutorials. Everything in Ruby is an object. Rails uses a lot of conventions so you can do things without having to write code for it, it's already there for you. When you get into Rails ActiveRecord Relations you'll see that relations expand this to give you related table information as methods. For Example:
Post.rb
...
belongs_to :user
User.rb
...
has_many :posts
Gives you methods like:
#post.user #returns the user object with all of its info
#post.user.username #returns the value of that column for that user
#post.user.posts #returns an array of Post objects that belong to the owner of that post.
Ruby has a pry-byebug gem for debugging. It's a combination REPL (Pry) and core debugger (byebug) that work very powerfully together.
Getting the id of a successfully saved ActiveRecord model is just #post.id, however the rails methods like redirect_to will take the object itself just fine, as #Beartech has mentioned, above. The documentation shows a variety of ways to use it, for convenience:
redirect_to action: "show", id: 5
redirect_to #post
redirect_to "http://www.rubyonrails.org"
redirect_to "/images/screenshot.jpg"
redirect_to posts_url
redirect_to proc { edit_post_url(#post) }

Rails help integrating nested? user specific uploads into an existing app

My app allows users to log in and have sessions. I have a user controller and a sessions controller, mainly developed from railscasts "authorization from scratch".
I recently added the ability to upload files to S3 using a jquery uploader... Again lots of this comes from railscasts "uploading to amazon S3".
The problem is my uploads are not user specific. Right now my "upload" controller has an "authorize" before_filter to ensure you must be logged in to access the uploader; however once a user uploads a file, ALL users see the upload! Not good! I need to ensure users only see the respective files they upload.
I've tried a few things but none seem to work. I'm looking for some direction on how to ensure users only see the files they upload. I'm following different railscasts and rails documentation on nesting resources (I think that is how I have to do this?) but I keep missing something as there seems to be lots of changes that I don't 100% understand. I fix one error, then hit another, and am wondering if I'm even going down the right path or maybe I'm missing something?
The way I thought this should work is to first nest the resource:
resources :users do
resources :cust_uploads
end
Then I modified the models as below and ran "rake db:migrate" to tie them together... I may need to manually modify a migration file with a foreign id field?:
class User < ActiveRecord::Base
has_secure_password
attr_accessible :email, :password, :password_confirmation
validates_uniqueness_of :email
has_many :CustUploads
end
class CustUpload < ActiveRecord::Base
attr_accessible :cust_file_url, :name
before_create :default_name
belongs_to :User
def default_name
self.name ||= File.basename(cust_file_url, '.*').titleize if cust_file_url
end
end
This gives me tons of path errors which I'm fighting through now... as my new_cust_upload_path is probably something like new_user_cust_upload_path
I also think my forms and controllers need lots of modification....
I'm using form_for
<%= form_for(#cust_upload) do |f| %>
Which I think should now be #user.cust_upload?
controllers at the moment:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
session[:user_id] = #user.id
redirect_to root_url, notice: "Thank you for signing up!"
else
render "new"
end
end
end
class CustUploadsController < ApplicationController
before_filter :authorize
def index
#cust_uploads = CustUpload.all
end
def show
#cust_upload = CustUpload.find(params[:id])
end
def new
#cust_upload = CustUpload.new
end
def create
#cust_upload = CustUpload.create(params[:cust_upload])
end
def edit
#cust_upload = CustUpload.find(params[:id])
end
def update
#cust_upload = CustUpload.find(params[:id])
if #cust_upload.update_attributes(params[:cust_upload])
redirect_to #cust_upload_url, notice: "Cust upload was successfully updated."
else
render :edit
end
end
def destroy
#cust_upload = CustUpload.find(params[:id])
#cust_upload.destroy
redirect_to cust_uploads_url, notice: "Cust Upload was successfully destroyed"
end
end
Any direction will be greatly appreciated. I've been through many tutorials and can make simple things work from scratch, I just can't seem to integrate this functionality with my existing app. There is something here I can't wrap my brain around and I'm hoping someone can provide me with that Eurika moment! Thanks
EDIT
routes.rb and my models appear to have the appropriate connections (code below). When in terminal I type "rake routes" I get a list as expected (see below) however I get and error: "No route matches {:action=>"show", :controller=>"cust_uploads"}" for a link with user_cust_uploads_path. There is a show template in the cust_uploads path and rake routes says it exists! What am I missing?
user_cust_uploads GET /users/:user_id/cust_uploads(.:format) cust_uploads#index
POST /users/:user_id/cust_uploads(.:format) cust_uploads#create
new_user_cust_upload GET /users/:user_id/cust_uploads/new(.:format) cust_uploads#new
edit_user_cust_upload GET /users/:user_id/cust_uploads/:id/edit(.:format) cust_uploads#edit
user_cust_upload GET /users/:user_id/cust_uploads/:id(.:format) cust_uploads#show
Considering you want to achieve
Users who upload stuff should only see them.
Why don't you associate the uploads with a specific user id and then when showing them in the view pull them from their own id (current_user.uploads)

How do I log create actions?

I am trying to create a logging feature on my RoR application that logs all the actions performed by the user on a given controller in a model. I tried implementing it with filters but they didn't solve my problem because they didn't allow me to properly log "create" actions.
"Create" actions are tricky because, when the before/after filters are called the action hasn't been saved yet, therefore, I don't have the corresponding id of the model (which I need).
I know I could use "after_commit", but this would greatly increase the complexity of the logging feature, since the "parameters" saved in each log entry are exposed to the controller, but not to the model.
Is there a way to dynamically add an "after_commit" filter to an instance of ActiveRecord?
Read this, I think this is nice solution: Notifications
This is how i log, i have a users controller create action like this:
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Welcome, #{#user.username}"
redirect_to(:controller => "users", :action => "home")
session[:id] = #user.id
else
render("home")
end
end
Now i would like to log that a user was created, then i do this:
First create an AuditLogger class in User.rb(model):
class User < ActiveRecord::Base
...some stuff other....
class AuditLogger < Logger
def format_message(severity, timestamp, progname, msg)
"#{timestamp.to_formatted_s(:db)} #{severity} #{msg}\n"
end
end
Then back to the controller(users.rb)
def create
#user = User.new(params[:user])
if #user.save
logfile = File.open("#{Rails.root}/log/my_log.log", 'a')
audit_log = AuditLogger.new(logfile)
audit_log.info "#{#user.firstname} was created successfully"
redirect_to(:controller => "users", :action => "home")
else
render("home")
end
end
Also you will need to create a file in your log directory called my_log.log. Hopefully it should be able to log. I know its not the best solution and there i are better ways of doing it, but at the time i needed something to work urgently, so i stuck with it.
Checkout these links:
rails logging tips
alternative logging solution

Post Redirect Get pattern in Rails

How can I implement PRG in Rails?
I used PRG in Rails, but I am not totally convinced it's right. I was wondering is there any better way to handle it in Rails?
I don't know how popular PRG pattern is and why one has to religiously stick to the "redirect" on failure aspect of it (actually, one good reason is sometimes you dont want to deal with the "setup" complexity at create failure and keep things dry).
What you basically need is to transfer the params for :user to new. I think #Hitesh's solution above is quite close.
class UsersController < ApplicationController
def new
if flash[:user_params]
#user = User.new(flash[:user_params])
#user.valid?
else
#user = User.new
end
end
def create
#user = User.new(params[:user])
if #user.save
# clears previously stored user if there is any
flash[:notice] = "User created."
redirect_to '/'
else
flash[:error] = "Error saving User"
flash[:user_params] = params[:user]
redirect_to :action => :new
end
end
end
Use the session, Luke
The way you implemented it in your blog post is quite fine, however you may want to use session instead of flash to store your #user and optionally use the ActiveRecord session store to keep cookies from getting bloated.
From ActionController::Base documentation
ActiveRecord::SessionStore - Sessions are stored in your database, which works better than PStore with multiple app servers and, unlike CookieStore, hides your session contents from the user. To use ActiveRecord::SessionStore, set
config.action_controller.session_store = :active_record_store
in your config/environment.rb and run rake db:sessions:create.
So you should…
class UsersController < ApplicationController
def new
#user = session[:user] || User.new
end
def create
#user = User.new(params[:user])
if #user.save
# clears previously stored user if there is any
session[:user] = nil
redirect_to '/'
else
session[:user] = #user
redirect_to :action => :new
end
end
end
I'm no expert in these matters, but this looks good. From what I understand flash is a part of the session. So the answers telling you to switch to session seem a bit misguided. In this case you want the data to be cleared after the redirect. Other than shoving it in the session, I'm not sure where you would put it.
As far as your cookie size increasing, well, the default session provider for Rails is a cookie in Rails 3. You could swap the session provider out if you wanted to keep the data server side. It is encrypted though, so you are probably okay with the data in the cookie, unless size is an issue.
use below code
class UsersController < ApplicationController
def new
#user = User.new(session[:user_param])
session[:user_param]=nil
end
def create
#user = User.new(params[:user])
if #user.save
# clears previously stored user if there is any
flash.discard(:user)
redirect_to '/'
else
session[:user_param] = #user
redirect_to :action => :new
end
end
end
It is true, though, that you should not do redirect_to '/'. You should define root in your routes file and then do redirect_to root_path.
Edit: Oops, that was supposed to be a comment to SpyrosP's answer.
Also: Here is some excellence guidance on flash. Particularly this may ease your mind:
The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc.
The interesting things there is that, yes it is a part of the session, so answers to "use the session instead of flash" are misguided, as Justin Etheredge's answer already put it. The other thing is that it says it is useful for storing messages instead of only for storing messages. With the added "etc" it would lead me to believe that it is within the intended usage to store user information in there as well.
One last thing, I would agree with Aditya Sanghi that you should just store the user parameters and not an entire user object in the flash.
I didn't read the question properly.
The validation failure you have necessitates going to a different page where a different process will occur. You tried to update a domain object, it doesn't exist. The usual response to a validation failure is to re-render the page, but you need to go to the create page.
The flash hash seems wrong for this. I'd agree with the idea of stuffing your entered data into the session and redirecting.

uninitialized constant with rails friendships

I'm new to rails and getting the following error:
NameError in FriendshipsController#create
uninitialized constant FriendshipsController
this also shows up:
{"authenticity_token"=>"eQvv3flATE+P1TEErOWP/6fM8dEOIBxltobCxtM/F18=",
"friend_id"=>"32"}
When I click on the "Add Friend" Link on my users show page. I am following the railscast about self referential associations to a T, but I keep getting this error and I can't find any information about it, not even what "uninitialized constant" means. I've gathered from the internet that it MAY be related to the acts_as_authenticated plugin, but I followed the one fix I found and it didn't work.
Here is the code from my user/show.html.erb page:
<%= link_to "Add Friend", friendships_path(:friend_id => #user.id), :method => :post %>
and the code from my friendships controller:
def create
#friendship = current_user.friendships.build(:friend_id => params[:friend_id])
if #friendship.save
flash[:notice] = "Added friend."
redirect_to root_url
else
flash[:error] = "Unable to add friend."
redirect_to root_url
end
end
Where am I going wrong here. I haven't the faintest clue what is causing this. Please let me know if I am missing any needed code.
Difficult to tell. You should post the top part of your class... requires, class definition, includes, and anything else you have that is outside of your methods, as well as the create method.
Rails is complaining because you have used a constant before initializing it.
puts SomeConstant
# before
SomeConstant = 10
In this case the constant is a controller Class Name - FriendshipsController
Check if the class name is correct, i.e. you have a controller with that name in your app\controller directory.
I think you run
rails g controller Friendship
while you should have used
rails g controller Friendships
thats why all files are now singular
You can still go through and change all files though

Resources