Newbie question: Integrating Authlogic plug-in more deeply

I have training app with "Projects" set up with nested "Tasks". I have integrate authlogic gem so that the app supports "Login/off" & "Register/Modify Profile" per ryanb's railscast. I am now trying to use authlogic and set up UI's so that after a user logs in, then the user can go to a UI of "My Projects" and then do all the CRUD they need to do on their own projects (current_user), but the user will only have read access to projects that are not theirs (not current_user). All users will have their Projects in the same data model (or that's what I'm attempting to do). I created a "myprojects" controller, copied over the project controller code & have been trying to work with "current_user.projects", but I'm getting an error since the Project is an undefined method.

How does one do this? Is there a way to pass the Project controller & views the "current_user.projects" data to re-use the Project controller & views? I know I'll have to put condition logic in to display or not display the 'Edit' paths, I'm just buggered on how to pass the subset of data if this is the way to go. Do I need the Myprojects controller or am I barking up a wrong tree? Do named routes come into play here? Enquiring minds want to know as a famous tabloid once advertised...

Thanks in advance!!

Following is my code: --------------------Project controller-------------------- class ProjectsController < ApplicationController   def index     @projects = Project.all

    respond_to do |format|       format.html # index.html.erb       format.xml { render :xml => @projects }     end   end

  def show     @project = Project.find(params[:id])

    respond_to do |format|       format.html # show.html.erb       format.xml { render :xml => @projects }     end   end

  def new     @project = Project.new

    respond_to do |format|       format.html # new.html.erb       format.xml { render :xml => @project }     end   end

  def edit     @project = Project.find(params[:id])   end

  def create     @project = Project.new(params[:project])

    respond_to do |format|       if @project.save         flash[:notice] = 'Project was successfully created.'         format.html { redirect_to(@project) }         format.xml { render :xml => @project, :status => :created, :location => @project }       else         format.html { render :action => "new" }         format.xml { render :xml => @project.errors, :status => :unprocessable_entity }       end     end   end

  def update     @project = Project.find(params[:id])

    respond_to do |format|       if @project.update_attributes(params[:project])         flash[:notice] = 'Project was successfully updated.'         format.html { redirect_to(@project) }         format.xml { head :ok }       else         format.html { render :action => "edit" }         format.xml { render :xml => @project.errors, :status => :unprocessable_entity }       end     end   end

  def destroy     @project = Project.find(params[:id])     @project.destroy     flash[:notice] = 'Project was successfully deleted.'     respond_to do |format|       format.html { redirect_to(projects_url) }       format.xml { head :ok }     end   end end

--------------------Myprojects controller-------------------- class MyprojectsController < ApplicationController   def index     @myprojects = current_user.Project.all #<-------- 'Project' reference here is getting an undefined method error

    respond_to do |format|       format.html # index.html.erb       format.xml { render :xml => @myprojects }     end   end

  def show     @project = current_user.Project.find(params[:id])

    respond_to do |format|       format.html # show.html.erb       format.xml { render :xml => @myprojects }     end   end

  def new     @project = Project.new

    respond_to do |format|       format.html # new.html.erb       format.xml { render :xml => @project }     end   end

  def edit     @project = current_user.Project.find(params[:id])   end

  def create     @project = Project.new(params[:project])

    respond_to do |format|       if @project.save         flash[:notice] = 'Project was successfully created.'         format.html { redirect_to(@project) }         format.xml { render :xml => @project, :status => :created, :location => @project }       else         format.html { render :action => "new" }         format.xml { render :xml => @project.errors, :status => :unprocessable_entity }       end     end   end

  def update     @project = current_user.Project.find(params[:id])

    respond_to do |format|       if @project.update_attributes(params[:project])         flash[:notice] = 'Project was successfully updated.'         format.html { redirect_to(@project) }         format.xml { head :ok }       else         format.html { render :action => "edit" }         format.xml { render :xml => @project.errors, :status => :unprocessable_entity }       end     end   end

  def destroy     @project = current_user.Project.find(params[:id])     @project.destroy     flash[:notice] = 'Project was successfully deleted.'     respond_to do |format|       format.html { redirect_to(myprojects_url) }       format.xml { head :ok }     end   end end

--------------------Project model-------------------- class Project < ActiveRecord::Base   validates_presence_of :name

# allow ordering of tasks by step_number   has_many :tasks, :dependent => :destroy, :order => 'step_number ASC'   accepts_nested_attributes_for :tasks, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true

  def task_attributes=(task_attributes)     task_attributes.each do |attributes|      tasks.build(attributes)     end   end

  # Following statements tie Projects to users   belongs_to :user

end

--------------------User model-------------------- class User < ActiveRecord::Base   # following line commented out. Came from authlogic, but not sure what it means…   # attr_accessible :username, :email, :password

  # Added following line from railscast demo. Note: http://github.com/binarylogic/authlogic_example   # has an optional block for passing other config options, but didn’t go there for now…   acts_as_authentic

  has_many :projects end

--------------------Myprojects controller-------------------- class MyprojectsController < ApplicationController   def index     @myprojects = current_user.Project.all #<-------- 'Project' reference here is getting an undefined method error

    respond_to do |format|       format.html # index.html.erb       format.xml { render :xml => @myprojects }     end   end

Would that not need to read

@myprojects = current_user.projects.all

PS i'll be impressed if i'm right being new to rails myself! :slight_smile:

Jon Cox wrote:

--------------------Myprojects controller-------------------- class MyprojectsController < ApplicationController   def index     @myprojects = current_user.Project.all #<-------- 'Project' reference here is getting an undefined method error

    respond_to do |format|       format.html # index.html.erb       format.xml { render :xml => @myprojects }     end   end

Would that not need to read

@myprojects = current_user.projects.all

Or just current_user.projects , since that already returns a collection.

PS i'll be impressed if i'm right being new to rails myself! :slight_smile:

Then prepare to be impressed. Good catch!

Best,

DOH!! I will have mastered rails when I KNOW where to Capitalize AND where to put an 's' in or not! Thanks!!

I worked past this error, was able to get the 'index' showing, but when I go to the 'show' or 'edit' views, I get an error where the "Project" index ID is WAY out of bounds (I don't think my dev db has gone beyond 20 id's):

      ActiveRecord::RecordNotFound in MyprojectsController#show       Couldn't find Project with ID=36732470 AND (`projects`.user_id = 2)

The user_id is passing fine, but the project ID is corrupted. I've tweaked my 'Show' definition to be current_user.project.find(params [:id]), current_user.Project.find(params[:id]), current_user.Projects.find(params[:id]) but these only result in "No Method" errors. Also, the "destroy" works fine.

Any thoughts why the index is not getting passed correctly for 'Show' & 'Edit', but it's fine for the 'destroy'?

Myprojects controller is looking like this:

Souschef wrote:

DOH!! I will have mastered rails when I KNOW where to Capitalize AND where to put an 's' in or not! Thanks!!

I worked past this error, was able to get the 'index' showing, but when I go to the 'show' or 'edit' views, I get an error where the "Project" index ID is WAY out of bounds (I don't think my dev db has gone beyond 20 id's):

      ActiveRecord::RecordNotFound in MyprojectsController#show       Couldn't find Project with ID=36732470 AND (`projects`.user_id = 2)

[...]

Are you using fixtures? If so, then high id numbers like this are normal.

If not, then something else is going on.

Best,

Are you using fixtures? If so, then high id numbers like this are normal.

If not, then something else is going on.

I haven't tackled fixtures yet so I'm not consciously using one, unless there is something in authlogic that's using one that I'm not aware of...

Souschef wrote:

Are you using fixtures? If so, then high id numbers like this are normal.

If not, then something else is going on.

I haven't tackled fixtures yet

Good: fixtures are crap. Use factories instead.

Bad: that suggests that you're not developing test-first yet. Get the habit *now*.

so I'm not consciously using one, unless there is something in authlogic that's using one that I'm not aware of...

There shouldn't be. Sounds like you have a problem elsewhere.

Best,

More info: I viewed page source for the index page & the funky references are being passed to it. Looking at the paths it's easy to see why the "delete" works & the 'show' & 'edit' don't. The href number changes each time for the 'Show' (embedded in the project title) & 'Edit' the index is called. Here's a list:   <tr>     <td><a href="/myprojects/37127550">Clean Room</a></td>     <td><a href="/myprojects/37127550/edit">Edit</a></td>     <td><a href="/projects/8" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE}   </tr>

  <tr>     <td><a href="/myprojects/37127550">Clean House</a></td>     <td><a href="/myprojects/37127550/edit">Edit</a></td>     <td><a href="/projects/12" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE}   </tr>

  <tr>     <td><a href="/myprojects/37127550">Mom's project</a></td>     <td><a href="/myprojects/37127550/edit">Edit</a></td>     <td><a href="/projects/16" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE}   </tr>

Yes, shame on me for not starting w/ TDD... will get there once I can get some rails basics under the belt...

Souschef wrote:

More info: I viewed page source for the index page & the funky references are being passed to it. Looking at the paths it's easy to see why the "delete" works & the 'show' & 'edit' don't. The href number changes each time for the 'Show' (embedded in the project title) & 'Edit' the index is called. Here's a list:   <tr>     <td><a href="/myprojects/37127550">Clean Room</a></td>     <td><a href="/myprojects/37127550/edit">Edit</a></td>     <td><a href="/projects/8" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE}   </tr>

  <tr>     <td><a href="/myprojects/37127550">Clean House</a></td>     <td><a href="/myprojects/37127550/edit">Edit</a></td>     <td><a href="/projects/12" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE}   </tr>

  <tr>     <td><a href="/myprojects/37127550">Mom's project</a></td>     <td><a href="/myprojects/37127550/edit">Edit</a></td>     <td><a href="/projects/16" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE}   </tr>

I'll try to look at this in more detail later.

Yes, shame on me for not starting w/ TDD... will get there once I can get some rails basics under the belt...

Wrong order. TDD *is* basic. Stop writing app code till you have tests in place.

Best,

In Ruby, every object has an attached object_id reference. Those long numbers are the ruby object_id's. You more than likely are referencing the object_id mistakenly.

As an example:

irb irb(main):001:0> my_object = "" => "" irb(main):002:0> my_object.object_id => 23323808

notice the 8 digit object_id number

.. and yours:

37127550

.. 8 digits.

More info: I viewed page source for the index page & the funky references are being passed to it. Looking at the paths it's easy to see why the "delete" works & the 'show' & 'edit' don't. The href number changes each time for the 'Show' (embedded in the project title) & 'Edit' the index is called. Here's a list: <tr> <td><a href="/myprojects/37127550">Clean Room</a></td> <td><a href="/myprojects/37127550/edit">Edit</a></td> <td><a href="/projects/8" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE} </tr>

<tr> <td><a href="/myprojects/37127550">Clean House</a></td> <td><a href="/myprojects/37127550/edit">Edit</a></td> <td><a href="/projects/12" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE} </tr>

<tr> <td><a href="/myprojects/37127550">Mom's project</a></td> <td><a href="/myprojects/37127550/edit">Edit</a></td> <td><a href="/projects/16" onclick="if (confirm('Are you sure?')) {DELETED EXTRA CODE HERE} </tr>

What does the code in your view look like for these?

Colin

What does the code in your view look like for these?

Colin

Hi Colin - I haven't done anything with the views since my goal is to re-use the 'project' views (i.e. use the 'myprojects' controller to get the subset of data (i.e. current_user data) then call the 'project' views with the subset of project data). When I do run the app, I'm getting the basic rails scaffolding view for the index... Thanks!

Interesting Alpha Blue, it does look like that. Where might I be mis- referncing the object other than the myproject controller?

Interesting Alpha Blue, it does look like that. Where might I be mis- referncing the object other than the myproject controller?

Souschef wrote:

Interesting Alpha Blue, it does look like that. Where might I be mis- referncing the object other than the myproject controller?

It can be an easy mistake to miss.

I found an old cart model a long time ago and for some strange reason, I saved it because it had this particular issue you are having.

cart.items.each_with_index do |item, index|   item_id = Product.find_by_title(item.title)   values.merge!({       "amount_#{index+1}" => item.price,       "item_name_#{index+1}" => item.title,       "item_number_#{index+1}" => item_id,       "quantity_#{index+1}" => item.quantity     }) end

In this example, notice the item_id? It was referencing the object_id instead of the id field. When I changed it to:

cart.items.each_with_index do |item, index|   item_id = Product.find_by_title(item.title)   values.merge!({       "amount_#{index+1}" => item.price,       "item_name_#{index+1}" => item.title,       "item_number_#{index+1}" => item_id.id,       "quantity_#{index+1}" => item.quantity     }) end

.. it referenced the correct id. Keep in mind, this is a really old example and was something someone else built.

But, I would check anything in your controller or model that is referencing name_id instead of name.id and do some troubleshooting in your rails console since you haven't setup any test code for yourself.

Interesting Alpha Blue, it does look like that. Where might I be mis- referncing the object other than the myproject controller?

Alpha Blue you GOT it!! Thanks!! Here was my 'index' code before: <% @projects.each do |projects| %>   <tr>     <td><%= link_to projects.name, :controller => 'myproject', :action => 'show', :id => current_user.projects.id %></td>     <td><%= link_to 'Edit', :controller => 'myproject', :action => 'edit', :id => current_user.projects.id %></td>     <td><%= link_to 'Delete', projects, :confirm => 'Are you sure?', :method => :delete %></td>   </tr> <% end %>

After I changed the :id assignment from 'current_user.projects.id' to just 'projects.id' the correct id number was getting assigned (i.e. the 'show' & 'edit' references in the 'view page source' now matched the delete index number):   <tr>     <td><a href="/myproject/show/13">Wash Dawgs</a></td>     <td><a href="/myproject/edit/13">Edit</a></td>     <td><a href="/projects/13" onclick="if (confirm('Are you sure?')) (DELETED EXTRA CODE HERE)   </tr>

THANKS EVERYONE! THIS NEWBIE GREATLY APPRECIATES YOUR INPUT!!!

Alpha Blue you GOT it!! Thanks!! Here was my 'index' code before: <% @projects.each do |projects| %>   <tr>     <td><%= link_to projects.name, :controller => 'myproject', :action => 'show', :id => current_user.projects.id %></td>     <td><%= link_to 'Edit', :controller => 'myproject', :action => 'edit', :id => current_user.projects.id %></td>     <td><%= link_to 'Delete', projects, :confirm => 'Are you sure?', :method => :delete %></td>   </tr> <% end %>

After I changed the :id assignment from 'current_user.projects.id' to just 'projects.id' the correct id number was getting assigned (i.e. the 'show' & 'edit' references in the 'view page source' now matched the delete index number):   <tr>     <td><a href="/myproject/show/13">Wash Dawgs</a></td>     <td><a href="/myproject/edit/13">Edit</a></td>     <td><a href="/projects/13" onclick="if (confirm('Are you sure?')) (DELETED EXTRA CODE HERE)   </tr>

THANKS EVERYONE! THIS NEWBIE GREATLY APPRECIATES YOUR INPUT!!!

Alpha Blue you GOT it!! Thanks!! Here was my 'index' code before: <% @projects.each do |projects| %>   <tr>     <td><%= link_to projects.name, :controller => 'myproject', :action => 'show', :id => current_user.projects.id %></td>     <td><%= link_to 'Edit', :controller => 'myproject', :action => 'edit', :id => current_user.projects.id %></td>     <td><%= link_to 'Delete', projects, :confirm => 'Are you sure?', :method => :delete %></td>   </tr> <% end %>

After I changed the :id assignment from 'current_user.projects.id' to just 'projects.id' the correct id number was getting assigned (i.e. the 'show' & 'edit' references in the 'view page source' now matched the delete index number):   <tr>     <td><a href="/myproject/show/13">Wash Dawgs</a></td>     <td><a href="/myproject/edit/13">Edit</a></td>     <td><a href="/projects/13" onclick="if (confirm('Are you sure?')) (DELETED EXTRA CODE HERE)   </tr>

THANKS EVERYONE! THIS NEWBIE GREATLY APPRECIATES YOUR INPUT!!!

You are welcome.

The next thing you should do is write some tests for this.