我老板的网站是一个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%的模型,并没有找到任何可以帮助我在网络上的东西。
如果有人看到我的错误,或知道如何解决问题,或者有更简单的方法来允许用户编辑自己的个人资料,请提供帮助。
答案 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 %>
感谢您的回答。
我希望这篇文章能帮助其他人解决与我相同的问题。