SitePoint Sponsor

User Tag List

Results 1 to 7 of 7
  1. #1
    SitePoint Zealot ricklach's Avatar
    Join Date
    Nov 2004
    Location
    Victoria BC
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Controller/View logic problem

    In the person controller I have the following statement:
    Code:
    @person = Person.find @params['id'], :include => [ :residence, :memberships, :donations ]
    This, I believe left joins all the tables in the [] brackets. In the donations table I have a field called "deleted" with a Y or N value (I never want to delete this information for auditing purposes - just hide it from being displayed by regular users). In regular usage the statement selects the record of the person and if an donation item is marked "deleted" the @person.donations.blank? will always be true if one or more records is marked with a "deleted=Y". So using @person.donations.blank? in a View will never give me a "false" value so I can print out the first option in an if-else-end construct. Here is a bit of code from the "edit view":
    Code:
    <% if @person.donations.blank? %>
    		<td colspan="2" align="left">This person has not made any donations. Create
    		 a donation now? 
    		 <%= link_to_function 'Add New Donation', "window.open('#{url_for :controller => 'donations', :action => 'new', :person_id => @params[:id] }', 'donation', 'height=500,width=600,resizable,scrollbars')" %>
    		<%= link_to_image "new", :controller=>"donations", :action=>"new", :id=> @person.id %> </td>
    	<% else %>
    		<td colspan="2" align="left">
    		<table border="1">
    			<tr>
    				<th class="heading-subtle">Type</th>
    				<th class="heading-subtle">Payment</th>
    				<th class="heading-subtle">Amount</th>
    				<th class="heading-subtle">Start Date</th>
    				<th class="heading-subtle">End Date</th>
    				<th class="heading-subtle">Frequency</th>
    				<th colspan="3" class="heading-subtle">Action</th>
    			</tr>
    		<% @person.donations.each do |d| %>
    			<% if d.deleted != 'Y' %>
    			<tr>
    				<td class="heading-subtle"><%= d.donation_type %></td>
    				<td class="heading-subtle"><%= d.pay_method %></td>
    				<td class="heading-subtle"><%= fmt_dollars(d.amount) %></td>
    				<td class="heading-subtle"><%= d.startdate %></td>
    				<td class="heading-subtle"><%= d.enddate %></td>
    				<td class="heading-subtle"><%= d.frequency %></td>  
    etc...
    So the question is how can I modify the statement "if @person.donations.blank?" to check and see if there are only deleted records or modify the controller so that a person is chosen even if all the donation records are marked as "deleted". Could I construct something like
    Code:
    if (count(donations.deleted = 'N') >= 1, donations= 'true', donations = 'false')
    and if so what is the syntax.

    Rick

  2. #2
    SitePoint Evangelist
    Join Date
    Jun 2004
    Location
    California
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Specify in your conditions for the "find" that you only want the donations where deleted == 'N':

    Code:
    @person = Person.find @params['id'], :include => [ :residence, :memberships, :donations ], :conditions => '`donations`.deleted == \'N\''
    The table for the SQL query might be wrong, it might not be `donations`.deleted but its something close to that.
    Happy switcher to OS X running on a MacBook Pro.

    Zend Certified Engineer

  3. #3
    SitePoint Zealot ricklach's Avatar
    Join Date
    Nov 2004
    Location
    Victoria BC
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In the wee hours I thought of this problem some more. Correct me if I am wrong but in the solution you have given what happens if there are no donation records or if there are only donation records that have been deleted. I think that no person records will be returned in those cases which of course is not the desired outcome. I think what I really should be doing is getting three record sets: one of person and residence info - this is always unique; if there is membership data then a membership recordset that I can iterate over to give a history; and, if there are donations that have the condition where deleted=N then a donation recordset. So in the controller I would have:
    Code:
    @person = Person.find @params['id'], :include => [ :residence, :memberships, :donations ]
         @residence = Residence.find(@person.residence_id)
         @membership = Membership.find(:conditions => [ "person_id = ?", @person.id]
         @donation = Donation.find(:conditions => [ "person_id = ?", "deleted = " @person.id, 'N']
    If this sounds correct to you can you give me some help with the syntax- at this point it is still my nemesis.

    Rick

  4. #4
    SitePoint Evangelist
    Join Date
    Jun 2004
    Location
    California
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    yes you could do that but I would think that that will use a lot of DB queries and therefore slow down the site... Maybe you can do this:

    Code:
    @person = Person.find @params['id'], :include =>[ :residence, :memberships, :donations ]
    @person.donations.instance_eval do
      def blank?
        return self.collect { |d| d.deleted == 'N' ? d : nil }.compact.length == 0
      end
    end
    I think that would work...Now just call @person.donations.blank? as you normally would.
    Happy switcher to OS X running on a MacBook Pro.

    Zend Certified Engineer

  5. #5
    SitePoint Zealot ricklach's Avatar
    Join Date
    Nov 2004
    Location
    Victoria BC
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Mitch,

    Sorry to be a pain but I tried to find some of the expressions you used in the API (eg. instance_eval, collect) to get a better appreciation of just what that code is doing. In the macro sence I believe I see it but could you explain just what is happening?

    Rick
    Ruby, Ruby when will you be mine

  6. #6
    SitePoint Evangelist
    Join Date
    Jun 2004
    Location
    California
    Posts
    440
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ricklach
    Mitch,

    Sorry to be a pain but I tried to find some of the expressions you used in the API (eg. instance_eval, collect) to get a better appreciation of just what that code is doing. In the macro sence I believe I see it but could you explain just what is happening?

    Rick
    I'm glad you asked

    You can read about it here:
    http://rubycentral.com/ref/ref_c_obj...#instance_eval
    It basically evaluates the code given within the scope of the instance of that object, so you can define new methods, change instance variables, etc. from outside the object by using the instance of it.

    What I did, which is untested but it theoretically should work, is redefine the blank? method to instead of checking whether the array is empty, it redefines the array to make all donations that are deleted to be "nil". You can read about the array#collect method here:
    http://rubycentral.com/ref/ref_c_array.html#collect
    So the actual array is not altered, it creates a new array to return with the changes (collect! would change the actual array, but we don't want that).

    Then you have an array something like [donation, nil, nil, donation, donation, nil] and the count will still give you what you started with, so you want to get rid of the nils. Ruby provides a method to do this array#compact:
    http://rubycentral.com/ref/ref_c_array.html#compact
    After that I just ask for the length of the new array Which only contains undeleted donations.
    Happy switcher to OS X running on a MacBook Pro.

    Zend Certified Engineer

  7. #7
    SitePoint Zealot ricklach's Avatar
    Join Date
    Nov 2004
    Location
    Victoria BC
    Posts
    116
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Mitch,

    Thanks for the explaination and yes it did indeed work as you suggested. However, one problem begets another and in an effort to gain a fuller understanding of just what I am doing I would like to prevail on you and your knowledge one more time. It seem as though I had everything working until I went to do an edit and then save the edited record. Everything seems to work but I am afraid, or at least think I have cocked-up the simplest and most elegant way of doing things. Here is my code for the controller for create, edit and update:
    Code:
    def create
        # will load an existing address if it exists, else create a new one
    	@residence = Residence.find_or_create_by_number_and_aptnum_and_postalcode(params[:residence][:number], params[:residence][:aptnum], params[:residence][:postalcode])
    	@voter = @residence.voter.build(params[:voter])
    	if @voter.save and @residence.save
    		flash[:notice] = 'The voter was created successfully!'
    		redirect_to :action => 'list'
    	else
    		render :action => 'new'
    	end
     
      end
    
      def edit
        @voter = Voter.find @params['id'], :include =>[ :residence, :memberships, :donations ]
        @voter.donations.instance_eval do
    	def blank?
    		return self.collect { |d| d.deleted == 'N' ? d : nil }.compact.length == 0
    	end
        end
        #@voter = Voter.find @params['id'], :include => [ :residence, :memberships, :donations ]
        #@voter = Voter.find @params['id'], :include => [ :residence ]
        @session[:fullname] = @voter.firstname + @voter.lastname
        @residence = Residence.find(@voter.residence_id)
        #@memberships = Membership.find(:all, :conditions => [ "voter_id = ?", @params['id']])
        #@donation = Donation.find(:all, :conditions => [ "voter_id = ? AND deleted = 'N'", @params['id'] ])
      end
    
      def update
        @voter = Voter.find(params[:id])
        #@voter = Voter.find @params['id'], :include => [ :residence, :memberships, :donations]
        @residence = Residence.find(@voter.residence_id)
        @residence.update_attributes(params[:residence])
        if @voter.update_attributes(params[:voter]) || @residence.update_attributes(params[:residence])
          flash[:notice] = 'The voter record was successfully updated.'
          redirect_to :action => 'list', :id => @voter
        else
          render :action => 'edit'
        end
      end
    The commented stuff is experimentation. In the edit, new screen for the partial I have the following code:
    Code:
    	<tr>
    		<td align="right" class="heading-subtle">Gender</td>
    		
    		<td align="left"  ><%= options = [["Select a Gender", ""]] + Dropdown::GENDER 
    			select("voter", "gender", options) %></td>
    		
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Salutation</td>
    		
    		<td align="left"><%= options = [["Select a Salutation", ""]] + Dropdown::SALUTATION 
    			select("voter", "salutation", options) %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">First Name</td>
    		<td align="left"><%= text_field "voter", "firstname", "size" => 30, "maxlength" => 30 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Middle Name</td>
    		<td align="left"><%= text_field "voter", "middlename", "size" => 30, "maxlength" => 30 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Last Name</td>
    		<td align="left"><%= text_field "voter", "lastname", "size" => 30, "maxlength" => 35 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Apt Number</td>
    		<td align="left"><%= text_field "residence", "aptnum", "size" => 8, "maxlength" => 8 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Pre-Compass</td>
    		
    		<td align="left"><%= options = [["Select a pre-compass direction", ""]] + Dropdown::COMPASS 
    			select("residence", "precompass", options) %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Street Number</td>
    		<td align="left"><%= text_field "residence", "number", "size" => 10, "maxlength" => 10 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Street Name</td>
    		<td align="left"><%= text_field "residence", "streetname", "size" => 30, "maxlength" => 30 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Street Type</td>
    		
    		<td align="left"><%= options = [["Select a street type", ""]] + Dropdown::STREETTYPE 
    			select("residence", "streettype", options) %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Post-Compass</td>
    		
    		<td align="left" class="heading-subtle"><%= options = [["Select a post-compass direction", ""]] + Dropdown::COMPASS 
    			select("residence", "postcompass", options) %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Apartment Name</td>
    		<td align="left"><%= text_field "residence", "aptname", "size" => 30, "maxlength" => 30 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">City</td>
    		<td align="left" ><%= text_field "residence", "city", "size" => 30, "maxlength" => 50 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Province</td>
    		<td align="left" class="heading-subtle"><%= get_setting('prov_name')  %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Postal Code</td>
    		<td align="left"><%= text_field "residence", "postalcode", "size" => 6, "maxlength" => 6 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Primary Language</td>
    		<% @voter.primary_language.nil? ? @voter.primary_language = 'English' : @voter.primary_language %> 
    		<td align="left"><%= options = [["Select a Primary Language", ""]] + Dropdown::LANGUAGE 
    			select("voter", "primary_language", options) %></td>
    		
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Secondary Language</td>
    		<% @voter.secondary_language.nil? ? @voter.secondary_language = 'English' : @voter.primary_language %> 
    		<td align="left"><%= options = [["Select a Secondary Language", ""]] + Dropdown::LANGUAGE 
    			select("voter", "secondary_language", options) %></td>
    		
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Birthdate</td>
    		<td align="left"><%= date_select 'voter', 'birthdate'  %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Occupation</td>
    		<td align="left"><%= text_field "voter", "occupation", "size" => 20, "maxlength" => 20 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Citizenship</td>
    		<td align="left"><%= text_field "voter", "citizenship", "size" => 1, "maxlength" => 1 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Home Phone</td>
    		<td align="left"><%= text_field "voter", "ph_home", "size" => 12, "maxlength" => 12 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Office Phone</td>
    		<td align="left"><%= text_field "voter", "ph_office", "size" => 12, "maxlength" => 12 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Mobile Phone</td>
    		<td align="left"><%= text_field "voter", "ph_mobile", "size" => 12, "maxlength" => 12 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">FAX</td>
    		<td align="left"><%= text_field "voter", "ph_fax", "size" => 20, "maxlength" => 20 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Pager</td>
    		<td align="left"><%= text_field "voter", "ph_pager", "size" => 20, "maxlength" => 20 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Email</td>
    		<td align="left"><%= text_field "voter", "email", "size" => 30, "maxlength" => 30 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Alternate Email</td>
    		<td align="left"><%= text_field "voter", "alt_email", "size" => 30, "maxlength" => 30 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">IMID Name</td>
    		<td align="left"><%= text_field "voter", "imid", "size" => 20, "maxlength" => 20 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">IMID</td>
    		<% @voter.imtype.nil? ? @voter.imtype = 'None' : @voter.imtype %> 
    		<td align="left"><%= options = [["Select an IM Type", ""]] + Dropdown::IMTYPES 
    			select("voter", "imtype", options) %></td>
    		
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Alternate IMID Name</td>
    		<td align="left"><%= text_field "voter", "alt_imid", "size" => 20, "maxlength" => 20 %></td>
    	</tr>
    	<tr>
    		<td align="right" class="heading-subtle">Alternate IMID</td>
    		<% @voter.alt_imtype.nil? ? @voter.alt_imtype = 'None' : @voter.alt_imtype %> 
    		<td align="left"><%= options = [["Select an alternate IM Type", ""]] + Dropdown::IMTYPES 
    			select("voter", "alt_imtype", options) %></td>
    		
    	</tr>
    	
    	<tr>
    		<td align="right" class="heading-subtle">Homepage URL</td>
    		<td align="left">
    		<%= text_field "voter", "homepage", "size" => 30, "maxlength" => 100 %></td>
    	</tr>
    	
    	<tr>
    		<td align="right" class="heading-subtle">Notes</td>
    		<td align="left"><%= text_area 'voter', 'notes', "rows" => 3  %></td>
    	</tr>
    Now this did work whenever I did an edit but now it does not seem to save the record after edit. However, more importantly, you will see how I have identified the voter and residence tags in the partial and in the controller. I have the sneaking suspision that there is a better way of doing this but I am not sure what it is or how to express the syntax in the controller and the partial. It seems to me that everything in the partial should be prefixed with voter (as opposed to voter and residence) and then the params array plugged into the two tables through some magic. Can you guide me here?

    Rick
    Ruby, Ruby when will you be mine


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •