用户编辑配置文件故障

时间:2011-12-20 13:05:18

标签: ruby-on-rails ruby edit

我老板的网站是一个RubyOnRails应用程序。我的老板让我为用户创建一种编辑自己个人资料的方式(比如更改密码,更改电子邮件等)。

已经有用户创建系统和身份验证系统。

我创建了用于编辑个人资料,视图和模型的新操作。

我尝试了许多不同的方法来使编辑系统正常工作,但没有一种方法可行。 有时该过程可以完成(提交表单并重定向到控制器的索引),但在用户的值中没有编辑任何内容。

以下是Error Log

Processing AccountController#edit (for MyIP at Today_Date Current_Hour) [PUT]
    Parameters: {
        "user_edit"=>{
            "city"=>"My City", 
            "country"=>"My Country", 
            "newsletter_subscription"=>"0", 
            "password_confirmation"=>"[FILTERED]", 
            "street"=>"My Street", 
            "last_name"=>"My Last Name", 
            "password"=>"[FILTERED]", 
            "login"=>"My.Login", 
            "first_name"=>"My First Name", 
            "email"=>"myemail@mydomain.com"
        }, 
        "commit"=>"confirm_edit", 
        "action"=>"edit", 
        "_method"=>"put", 
        "authenticity_token"=>"My_Too_Long_Authenticity_Token", 
        "local"=>"fr", 
        "controller"=>"account"
    }

NoMethodError (Attempt to call private method):
    app/controllers/account_controller.rb:90:in `edit´
    thin (1.2.7) lib/thin/connection.rb:76:in `pre_process´
    thin (1.2.7) lib/thin/connection.rb:74:in `catch´
    thin (1.2.7) lib/thin/connection.rb:74:in `pre_process´
    thin (1.2.7) lib/thin/connection.rb:57:in `process´
    thin (1.2.7) lib/thin/connection.rb:42:in `receive_data´
    eventmachine (0.12.10) lib/eventmachin.rb:256:in `run_machine´
    eventmachine (0.12.10) lib/eventmachin.rb:256:in `run´
    thin (1.2.7) lib/thin/backends/base.rb:57:in `start´
    thin (1.2.7) lib/thin/server.rb:156:in `start´
    thin (1.2.7) lib/thin/controllers/controller.rb:80:in `start´
    thin (1.2.7) lib/thin/runner.rb:177:in `send´
    thin (1.2.7) lib/thin/runner.rb:177:in `run_command´
    thin (1.2.7) lib/thin/runner.rb:143:in `run!´
    thin (1.2.7) bin/thin:6
    /usr/local/bin/thin:19:in `load´
    /usr/local/bin/thin:19

Rendering /var/rails/MySite/releases/MyApp/public/500.html 
(500 Internal Server Error)

这是控制器的一部分:

1    require "erb"
2    require 'net/http'
3    require 'net/https'
4    class AccountController < ApplicationController
5      include ERB::Util
6      layout "store"
7    
68     def edit_profile
69         @page_title = t(:account_edit_profile)
70         if logged_in?
71             if !session.nil? && session[:dump_user]
72                 @user = retrieveFromSession(:dump_user)
73             else
74                 @user = current_user
75             end
76             begin
77                 rescue ActiveRecord::RecordNotFound
78                     record_not_found
79                     redirect_to(:controller=>:account, :action => :index)
80             end
81         else
82             flash[:notice] = t(:permission_denied)
83             redirect_to(:controller=>:account, :action => :index)
84         end
86     end
85    
86     def edit
87        @page_title = t(:account_edit_profile)
88         if logged_in?
89             if is_active_module? :symbol_private
90                 @user = User.find_by_id!(current_user.id).update(params[:user_edit])
91                 if @user.valid?
92                     session[:dump_user] = Marshal.dump(@user)
93                     redirect_to(:controller=>:account, :action => :edit_confirm)
94                 else
95                     render :action => 'edit_profile';
96                 end
97             else
98                 flash[:notice] = t(:permission_denied)
99                 redirect_to(:controller=>:account, :action => :profile)
100            end
101        else
102            flash[:notice] = t(:permission_denied)
103            redirect_to(:controller=>:account, :action => :profile)
104        end
105    end
106
107    def edit_confirm
108        if logged_in?
109            begin
110                user = retrieveFromSession(:dump_user)
111                session[:dump_user] = Marshal.dump(user)
112                if is_active_module? :symbol_private
113                    finalize_edit
114                end
115                rescue ActiveRecord::RecordNotSaved
116                    flash[:notice] = t :something_went_wrong
117                    redirect_to(:controller=>:account, :action => :profile)
118            end
119        else
120            flash[:notice] = t(:permission_denied)
121            redirect_to(:controller=>:account, :action => :index)
122        end
123    end
124
125    def finalize_edit
126        user=(!user.nil?) ? user : retrieveFromSession(:dump_user)
127        user.save!
128            flash[:notice] = t(:profil_successfully_edited)
129            session[:dump_user]=nil
130            redirect_to(:controller=>:account, :action => :profile)
131    end
132
133 end

以下是“edit_profile”的视图:

1    <div id="title_store">
2        <%= t(:account_edit_profile)%>
3    </div>
4    <div id="paragraph_store">
5        <div>
6            <%
7                labelled_form_for :user_edit, @user, :url =>{:action =>"edit"},
8                :html=>{:multipart=>true, :method=>:put} do |@form|
9            %>
10               <% field_set_tag t(:edit_profile) do %>
11                   <%= @form.text_field :login, :value=>(@user.login), :disabled=>"disabled"%>
12                   <%= @form.text_field :email, :value=>(@user.email) %>
13                   <%= @form.password_field :password %>
14                   <%= @form.password_field :password_confirmation %>
15                   <%= @form.text_field :first_name, :value=>(@user.first_name) %>
16                   <%= @form.text_field :last_name, :value=>(@user.last_name) %>
17                   <%= @form.text_field :street, :value=>(@user.street) %>
18                   <%= @form.text_field :city, :value=>(@user.city) %>
19                   <%= @form.text_field :country, :value=>(@user.country) %>
20                   <%= @form.check_box :newsletter_subscription, :checked => params[:newsletter_subscription]%>
21                   <div id="envoie">
22                       <div id="retour">
23                           <%= link_to t(:cancel), :controller=>:account, :action=>:profile %>
24                       </div>
25                       <div class="submit">
26                           <%= submit_tag t(:confirm_edit) %>
27                       </div>
28                   </div>
29               <%end%>
30           <%end%>
31       </div>
32   </div>

视图位于布局内部,其中有html / head / body以及渲染视图所需的其他项目。

我没有发布帮助器,因为它没有使用。

关于模型,我没有成功,我不明白。我只了解发送表单所需的值的部分,并保存它。

以下是模型:

1     require 'digest/sha1'
2     require 'shared/element'
3     require 'exceptions'
4     require 'rubygems'
5     require 'net/ldap'
6
7     class UserEdit < ActiveRecord::Base
8         has_and_belongs_to_many :roles
9         belongs_to :abonnement 
10        belongs_to :secretariat
11        has_many :news
12        has_many :items
13        has_many :absences
14        has_many :opener, :foreign_key => "opened_by_id", :class_name =>'Task'
15        has_many :closer, :foreign_key => "closed_by_id",:class_name =>'Task'
16        has_many :attributor, :foreign_key => "attributed_to_id",:class_name =>'Task'
17        has_many :static_pages
18        
19        attr_accessible :login,:password,:password_confirmation, :email,:is_ldap_user, :secretariat_id, :newsletter_subscription
20        attr_accessible :first_name, :last_name, :street, :city, :country
21        
22        validates_presence_of        :first_name
23        validates_presence_of        :last_name
24        validates_presence_of        :street
25        validates_presence_of        :city
26        validates_presence_of        :country
27      
28        validates_presence_of     :password,                   :if => :password_changed?
29        validates_presence_of     :password_confirmation,      :if => :password_changed?
30        validates_length_of       :password, :within => 4..40, :if => :password_changed?
31        validates_confirmation_of :password,                   :if => :password_changed?
32        validates_length_of       :login,    :within => 3..20
33        validates_length_of       :email,    :maximum => 50
34        validates_uniqueness_of   :login, :case_sensitive => false
35        validates_uniqueness_of   :email, :case_sensitive => false, :if => Proc.new{|u| configatron.email_uniqueness}
36        validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
37
38      
39        before_save :encrypt_password, :fix_is_ldap_user_attribute
40        before_destroy :check_godness
41        
42        extend Element
43        
44        def self.authenticate(login, password)
45            u = find_by_login(login)
46            if !u
47                raise WrongLoginPassword
48            end
49            
50            if(is_active_module?:ldap)
51                unless u.authenticated?(password) || is_in_ldap?(login,password)
52                    raise LDAPOnlyUser
53                end
54            else
55                raise WrongLoginPassword unless !u.nil? && u.authenticated?(password)
56            end
57            
58            if !u.activated_at
59                raise InactiveAccount
60            elsif u.roles.find_by_title('banned')
61                raise BannedAccount
62            else
63                return u
64            end  
65        end
66        
67        def self.encrypt(password, salt)
68            Digest::SHA1.hexdigest("--#{salt}--#{password}--")
69        end
70        
71        def encrypt(password)
72            self.class.encrypt(password, salt)
73        end
74        
75        def authenticated?(password)
76            crypted_password == encrypt(password)
77        end
78        
79        def remember_token?
80            remember_token_expires_at && Time.now.utc  remember_token_expires_at 
81        end
82        
83        def remember_me
84            self.remember_token_expires_at = 2.weeks.from_now.utc
85            self.remember_token            = encrypt("#{email}--#{remember_token_expires_at}")
86            save(false)
87        end
88        
89        def forget_me
90            self.remember_token_expires_at = nil
91            self.remember_token            = nil
92            save(false)
93        end
94        
95        def self.content_columns
96            @content_columns = super.delete_if do |value| 
97                (value.human_name.downcase == "crypted password") ||
98                (value.human_name.downcase == "salt") ||
99                (value.human_name.downcase =~ /.*token.*/) ||
100               (value.human_name.downcase == 'password reset code') ||
101               (value.human_name.downcase == 'is ldap user') ||
102               (value.human_name.downcase == 'updated at') ||
103               (value.human_name.downcase == "activation code")
104           end
105       end
106        
107       def activate
108           @activated = true
109           self.activated_at=Time.now.utc
110           self.activation_code=nil 
111           true
112       end
113        
114       def recently_activated?
115           @activated
116       end
117        
118       def recently_lost_password?
119           @lost_password
120       end
121        
122       def password_reset?
123           @password_reset
124       end
125        
126       def is_admin?
127           (self.roles.map{ |role| role.title.downcase}.include? 'admin') || is_god?
128       end
129        
130       def is_god?
131           self.roles.map{ |role| role.title.downcase}.include? 'god'
132       end
133        
134       def is_secretary?
135           self.roles.map{ |role| role.title.downcase}.include? 'secretary'
136       end
137        
138       def make_password_reset_code
139           @lost_password = true
140           self.password_reset_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join)
141       end
142        
143       def reset_password
144           self.password = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join).slice(0,8)
145           self.password_confirmation = self.password
146           self.password_reset_code = nil
147           @password_reset = self.password
148           self.save!    
149       end
150        
151       def available_roles
152           if (self.roles.map{ |role| role.title.downcase}.include? 'god')
153               Role.find(:all)
154           else
155               Role.find(:all,
156                   :conditions=>["title != ?",'god'])
157           end
158       end
159       
160       protected
161       
162       def encrypt_password
163           return if password.blank?
164           self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record?
165           self.crypted_password = encrypt(password)
166       end
167        
168       def password_required?
169           if( is_active_module?(:ldap) &&  is_ldap_user == true )
170               return false
171           else
172               (crypted_password.blank? || !password.blank?)
173           end
174       end
175        
176       def make_activation_code
177           self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
178       end
179        
180       private
181       def check_godness
182           raise UnautorizedDeletion if is_god?
183       end
184        
185       def is_valid_secretariat?
186           return true unless is_active_module? :ipmc
187           return true if self.secretariat_id.nil?
188           if Secretariat.find_by_id(self.secretariat_id).nil?
189               errors.add :secretariat_id, :invalid
190               false
191           else
192               true
193           end
194       end
195        
196       def fix_is_ldap_user_attribute
197           self.is_ldap_user = true if is_ldap_user.nil? && is_active_module?(:ldap)
198       end
199       
200       def self.is_in_ldap?(login ,password)
201           ldap = Net::LDAP.new
202           ldap.host = configatron.ldap.host
203           ldap.port = configatron.ldap.port
204           ldap.encryption :simple_tls if configatron.ldap.encryption
205           ldap.auth configatron.ldap.base_dn, configatron.ldap.password
206           begin
207               result = ldap.bind_as(
208                               :base => configatron.ldap.base_dn,
209                               :filter=>"(uid=#{login})",
210                               :password => password
211               )
212               rescue SystemExit
213                   return false
214           end
215           if result 
216               return true
217           else
218               return false
219           end
220       end
221        
222   end

我完全迷失了,我不明白出了什么问题。不理解90%的模型,并没有找到任何可以帮助我在网络上的东西。

如果有人看到我的错误,或知道如何解决问题,或者有更简单的方法来允许用户编辑自己的个人资料,请提供帮助。

3 个答案:

答案 0 :(得分:0)

我看到的第一个奇怪的事情是,在您的控制器中,您使用用户模型和模型您发布的代码名称为UserEdit。

答案 1 :(得分:0)

第二个奇怪的事情是你的形式:do |@form| 这应该是@-变量。只需使用:do |f|

此外,您不需要显式传入值:value=>(@user.login), - 您已经指定该表单是“for”@user,并且表单应该自动获取这些值本身。尝试简化所有这些,看看是否有帮助(它至少有助于提高可读性)。

然后,在导致回溯错误的行上。尝试将其拆分为两行,以查看哪个操作实际导致错误,例如:

@user = User.find_by_id(current_user.id)
@user.update(params[:user_edit])

然而......实际上,如果您只是在寻找与current_user相同的User对象...为什么不只是使用当前用户并跳过查找?毕竟,如果你有current_user,那么你不需要重新加载用户对象。

所以我建议完全用以下代码替换该行:

@user = current_user
@user.update(params[:user_edit])

答案 2 :(得分:0)

好的,我找到了一种方法让我的编辑系统正常工作。

我的错误在于尝试使用我没有100%解读的系统。

最后我简单地做了。

在控制器中:

    def edit_profile
        if logged_in?
            @page_title = t(:account_edit_profile)
            @user = current_user
            if request.post?
                if @user.update_attributes(params[:user_edit])
                    flash[:notice] = t(:profil_succesfully_edited)
                    redirect_to :controller => :account, :action => :profile
                end
            end
        else
            flash[:notice] = t(:must_logged_in)
            redirect_to :controller => :index
        end
    end

在视图中,我使用_form.rhml调用<%= render :partial => "form"%>。 在这种形式中,我写道:

<%= error_messages_for :user_edit %>
<% form_for :user_edit, @user, :html=>{:multipart=>true, :method=>:post} do |f| %>
    <p>
        <%= f.label t(:login) %>
        <%= f.text_field :login %>
    </p>
    <p>
        <%= f.label t(:email) %>
        <%= f.text_field :email %>
    </p>
    <p>
        <%= f.label t(:first_name) %>
        <%= f.text_field :first_name %>
    </p>
    <p>
        <%= f.label t(:last_name) %>
        <%= f.text_field :last_name %>
    </p>
    <p>
        <%= f.label t(:street) %>
        <%= f.text_field :street %>
    </p>
    <p>
        <%= f.label t(:city) %>
        <%= f.text_field :city %>
    </p>
    <p>
        <%= f.label t(:country) %>
        <%= f.text_field :country %>
    </p>
    <p class="checkbox">
        <%= f.check_box :newsletter_subscription, :checked => params[:newsletter_subscription] %>
        <%= f.label t(:newsletter_subscription) %>
    </p>
    <div id="envoie">
        <div id="retour">
            <%= link_to t(:cancel), :controller=>:account, :action=>:profile %>
        </div>
        <div class="submit">
            <%= f.submit t(:confirm_edit) %>
        </div>
    </div>
<% end %>

感谢您的回答。

我希望这篇文章能帮助其他人解决与我相同的问题。