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.