Conditionally adding a link to a form -- how?

Hi Colin,

I had to work on adding authenticated users to my app, so I had to
back-burner the conditional-link issue. I nevertheless would like to
keep trying to learn how to do this. Maybe CSS is the way to make the
link switch between visible or not depending on context. (Just my
inspiration at the moment.)

Also, you mentioned that I needed have my switch initialized to
false, because nil will result in the same thing, so I just
commented it out in VendorController. Seems to clear up one problem.

Your first attempt just above is already a class variable, as it
starts with @ so I don't follow you here.

Yes you are right of course, forgot to engage brain. There is no need
for a class variable, an instance variable is what you want.

Colin

Following up on what Bob Smith posted on 4/21 and Hassan Schroeder on
4/24,
here's what I've got working:

======= app\views\vendors\show.html.erb =====
[snip]
<%= link_to 'Edit', edit_vendor_path(@vendor) %> | <%# From scaffold -
%>
<%= link_to 'Back', vendors_path %> <%# From scaffold -%>

<%# params['show_new_expense_page'] = true %>

<% if params['show_new_expense_page'] -%>
    >
    <%= link_to 'New Expense', '/expenses/new' %>
<% end -%>

<% params['show_new_expense_page'] = false %>

============== end ===================

With the "params ... = true" line commented out, I get two links:
Edit | Back

Un-commented, I get three links as desired, and they all work:
Edit | Back | New Expense

My intention is to have the "New Expense" link visible when a
particular link was previously clicked in the following page:

======= app\views\expenses\new.html.erb =====
[snip]
    <% @current_vendors =
Vendor.find(:all, :order=>"nickname").collect { |v|
      v.nickname + parens(v.qbname) } %>
    <%= f.select :vendor, @current_vendors %>
    <% params['new_expense_page'] = true -%>
    <%= link_to 'New
Vendor', :controller=>'vendors', :action=>'new' %>
[snip]
================= end =================

But the "params ... true" setting is not conveyed to the app\views
\vendors\show.html.erb page.

1. Can this be fixed?
2. If not, will using session rather than params work?
3. Or can I access the "previous page" value in the app\views\vendors
\show.html.erb page and test whether the previous page was app\views
\expenses\new.html.erb?

Again, thanks to all of you for your past responses. I'd be grateful
for any additional ideas you may offer.

Following up on what Bob Smith posted on 4/21 and Hassan Schroeder on
4/24,
here's what I've got working:

======= app\views\vendors\show.html.erb =====
[snip]
<%= link_to 'Edit', edit_vendor_path(@vendor) %> | <%# From scaffold -
%>
<%= link_to 'Back', vendors_path %> <%# From scaffold -%>

<%# params['show_new_expense_page'] = true %>

<% if params['show_new_expense_page'] -%>
>
<%= link_to 'New Expense', '/expenses/new' %>
<% end -%>

<% params['show_new_expense_page'] = false %>

============== end ===================

With the "params ... = true" line commented out, I get two links:
Edit | Back

Un-commented, I get three links as desired, and they all work:
Edit | Back | New Expense

My intention is to have the "New Expense" link visible when a
particular link was previously clicked in the following page:

======= app\views\expenses\new.html.erb =====
[snip]
<% @current_vendors =
Vendor.find(:all, :order=>"nickname").collect { |v|
v.nickname + parens(v.qbname) } %>

Nothing to do with your problem but you should definitely not be doing
finds in the view, this should be in the controller.

<%= f.select :vendor, @current_vendors %>
<% params['new_expense_page'] = true -%>
<%= link_to 'New
Vendor', :controller=>'vendors', :action=>'new' %>
[snip]
================= end =================

But the "params ... true" setting is not conveyed to the app\views
\vendors\show.html.erb page.

1. Can this be fixed?
2. If not, will using session rather than params work?
3. Or can I access the "previous page" value in the app\views\vendors
\show.html.erb page and test whether the previous page was app\views
\expenses\new.html.erb?

The solution has been suggested several times already in this thread,
I will try again.
In the _controller_ method that is rendering the page that has the
conditional link displayed set a variable
@show_new_expense_page = true
at the point in the code where you know that you wish to show the link.
In the view then just use if @show_new_expense_page on the link display.

Please try this and get back if you have problems, or ask for
clarification if you do not understand it (if so which bit do you not
understand). The approach you are trying to use is not the best way.

Colin

forgot to engage brain

The happens to me all the time. I retired a decade ago and I often
can't remember what I did or intended five minutes ago. I've
developed some techniques for combating this weakness, e.g.. when
programming I log screen-shots of what I did and what I got as a
result. It has a two-fold benefit: (1) if something goes awry, I can
accurately recall what led up to the problem; and (2) if I can't
remember how to do something I "know" how to do, I can search my log
mechanically to get a clue.

Cheers,
Richard

I think I see the cause of lack of communication between params in
1) app\views\expenses\new.html.erb; and
2) app\views\vendors\show.html.erb

The are two distinct params, viz:
one in an instance of app\controllers\expenses_controller.rb;
the other in instance of app\controllers\vendors_controller.rb;

And if I we overcome that problem, perhaps there's an even bigger
problem:
my app is intended to be installed on a server, includes the database.
But the app is to be users of several classes on the network.
Wouldn't the use of params fail in that case, but be ameliorated by
use of sessions?

Am I all wet about this?

Thanks in advance,
Richard

RichardOnRails wrote:

forgot to engage brain

The happens to me all the time. I retired a decade ago and I often
can't remember what I did or intended five minutes ago. I've
developed some techniques for combating this weakness, e.g.. when
programming I log screen-shots of what I did and what I got as a
result.

Can I suggest that you supplement this with automated tests and version
control?

It has a two-fold benefit: (1) if something goes awry, I can
accurately recall what led up to the problem; and (2) if I can't
remember how to do something I "know" how to do, I can search my log
mechanically to get a clue.

Cheers,
Richard

Best,

Yes. I think you are totally missing how the Web works :slight_smile:

The params hash represents name/value pairs passed from a client
(browser, typically) to your server, either as a GET request's query
string, or as body parts of a POST request.

So the life of a params hash is one request. If you want something
to persist beyond that, put it in session, store it in the DB or use a
hidden field in a form.

Or copy it into an @ variable in the controller action to make it
available in the rendered view. But I believe for the OP's problem he
does not require to use params (or persistence) at all. See my
previous post.

Colin

My impression is that the OP is trying to set a variable in one view
(and yes, that's the wrong place to do it regardless):

  app\views\expenses\new.html.erb

and have it show up in another:

  "But the "params ... true" setting is not conveyed to the
       app\views\vendors\show.html.erb page."

Hence the issue of persistence...

I believe he has been trying to do that, but is that what he needs to
do? Can he not just set the condition variable in the controller
action? With a parameter on the link calling the action if necessary.

Colin

Not according to the examples provided -- there's a link shown to e.g.
/vendors/new, which would presumably lead to a POST request to a
`create` action, which would then redirect to a new GET request for
/vendor/:id `show` - which is where the OP says he wants that value
available.

You may be right, I did not read as much into the OPs question as you
have. I assumed that _any_ redirect to show from the create should
include the extra link, rather than specifically a create initiated
from the link you mention. If my interpretatioin is correct then he
can just specify a parameter in the redirect_to :action => 'show' in
the create action. If your interpretation is correct (which it may
well be having re-read the original post) then I agree with your
analysis. I would probably put something in the session for this
case.

Over to you Richard - what is your requirement in this regard.

Colin

Hi Colin,

Hi Marnen,

Can I suggest that you supplement this with automated tests and version
control?

Absolutely! That's definitely on my agenda. But this (first) Rails
app is intended to automate a substantial part of burden my son faces
in managing his small business. So, I'm focused on getting "version
1" of this app developed and deployed to prove that "help is on the
way."

Using BDD and Subversion are my goals, but the learning curve for
effective use is time taken from a delivery date. I just spent more
than a week learning how to introduce navigation subtleties into my
app. I probably left this problem for "version 2" but I was annoyed
that my years of 20th Century computer-consulting skills were
inadequate for the 21st Century Web.

Now that I got a glimpse into handling this navigation problem, I off
to work on the last functionality required before version 1
deployment: authenticated users.

With thanks for your interest in my humble efforts,
Richard

Something is still not working as you think it is. An @ variable set
in a controller action only has life into the rendered view from that
action, there should be no need to reset it for another action. I
suggest you use ruby-debug (look at the rails guide on debugging,
google rails guides if necessary) and break into you actions and views
and work out what is going on. Also study the log file to see exactly
what is happening.

I have just seen your next post in reply to Marnen's suggestion on
testing. I suggest you run for cover.

Colin

RichardOnRails wrote:

Hi Marnen,

Can I suggest that you supplement this with automated tests and version
control?

Absolutely! That's definitely on my agenda. But this (first) Rails
app is intended to automate a substantial part of burden my son faces
in managing his small business. So, I'm focused on getting "version
1" of this app developed and deployed to prove that "help is on the
way."

As I've said before, you really must implement version control *today*.
It will take at most an hour or two, and it will make version 1 easier
to develop. Don't wait another minute.

Using BDD and Subversion are my goals,

Not Subversion, please. Use Git.

but the learning curve for
effective use is time taken from a delivery date.

Wrong! If you take a few minutes to sharpen the saw, you will fell the
tree faster.

I just spent more
than a week learning how to introduce navigation subtleties into my
app. I probably left this problem for "version 2"

Yes, you probably should have.

but I was annoyed
that my years of 20th Century computer-consulting skills were
inadequate for the 21st Century Web.

Don't let annoyance drive you into decisions that even you know are bad.

Now that I got a glimpse into handling this navigation problem, I off
to work on the last functionality required before version 1
deployment: authenticated users.

Authlogic. Done.

With thanks for your interest in my humble efforts,
Richard

Good luck! It's always nice to see someone seriously learning.

Best,

Yes. I think you are totally missing how the Web works :slight_smile:

Funny, but oh so true!

The params hash represents name/value pairs passed from a client
(browser, typically) to your server, either as a GET request's query
string, or as body parts of a POST request.

This is definitely one of the things I haven't gotten into my head.

put it in session

I'm ready to add some version of an authenticated user, Authlogic, I
think. That should give me a session as my repository

store it in the DB

Ok, I could script/generate another a model, etc for another table
with CRUD methods.

hidden field in a form.

I see plenty of info on this via Google, which I'll look into in time.

OK, I see several potential solutions to my problem. I'm going to
suspend this issue until I complete the user's creation and packaging
a version 1 deliverable.

Many thanks,
Richard

Something is still not working as you think it is.

You're right about that, especially the practice of setting @xxx in
one controller and (correctly) referencing it's value in second
(unrelated by hierarchy) controller. I think that can only work by
meta-programming magic. I'm going to post a question about that at
some future time when I'm not consumed by the need for a deliverable.

... there should be no need to reset it for another action.

I left the conclusion out of my description of the problem, which
stated in full is:
Failure to employ this reset leads to, e.g.
clicking "New Expense" in app\views\expenses\new.html.erb,
clicking "Vendor" in app\views\expenses\new.html.erb
clicking "Show" on any of the vendors displayed in app\views\vendors
\index.html.erb.
leads to three links, "Edit | Back | New Expense" where there should
only be two: "Edit | Back"

Adding the reset clause led to correct behavior in a couple of tests,
I believe. In light of your misgivngs, I thought I should remove all
the params I introduced earlier. Now, the extra link appears again
at times I deem to be inappropriate. So either I was wrong before or
introduced another error.

In any case, I can't spend any more time on this. As I just posted
Hassan, I'll get back to this issue after I finish adding
authenticated users and package a "ver. 1" deliverable.

I have just seen your next post in reply to Marnen's suggestion on
testing. I suggest you run for cover.

I'm a mere needle in a haystack comprised hundreds of millions of
Americans. Finding me to inflict punishment for violating "good
practices" will be inordinately difficult :slight_smile:

Thanks again for you continued contribution to my Rails education. I
hope you don't find me incorrigible nor ineducable.

Best wishes,
Richard

The "session" concept doesn't imply "authentication" -- it's a Rails
built-in feature. And again it's just a hash.

Set a value:
   session["somevar"] = "somevalue"

Read it anywhere:

   session["somevar"]

That's all there is to it. (Yes, there is a 4k limit to data stored in the
default Session::CookieStore -- shouldn't be a problem for you in
this example at least. But the API docs are your friend.)

HTH, and good luck,

Hi Hassan,

The "session" concept doesn't imply "authentication" -- it's a Rails
built-in feature.

I didn't think that one needed an authenticated user in order to have
a session. But I definitely thought one needed to have a User defined
in order to have session defined. So I was surprised that
"session[:symbol] = value" worked fine.

The app I'm working on will be stored on a server to be accessed by
perhaps 25 to 50 users on desktops connected through a LAN. Since
we're on the topic, do I have to do any thing special to ensure that
each user has a distinct session inaccessible to all other users?
(I'll check the Rails' docs later.)

I am going to add Authlogic gem tomorrow, I think, so that the app can
provide secure user-login. I expect Authlogic will hook-up with the
already-working session mechanism.

Thanks for getting me going on the session approach. I've just got to
diagram the flow of control in my app (or maybe jot down a finite
state machine) to figure out where to stick my
session[:show_link]=true/false expressions.

Best wishes,
Richard