更多 rails 部分在同一页面上
more rails partials on the same page
我有一个 rails 应用程序。我在 users/:id/show 页面上显示来自不同 类 的更多部分(用户、任务、对话、消息)。我在 users.controller 的 def show 动作中设置了所有实例变量(也适用于其他 类)。
好像有点重,有没有比这更好的方法呢? (我在 AJAX 调用中使用了@task 和@message。)
def show
@user = User.find(params[:id])
if Task.between(current_user.id, @user.id).present?
@tasks = Task.uncompleted.between(current_user.id, @user.id).order("created_at DESC").includes(:assigner).paginate(page: params[:page], per_page: 12)
@task = Task.new
if Conversation.between(current_user.id, @user.id).present?
@conversation = Conversation.between(current_user.id, @user.id).first
@messages = @conversation.messages.includes(:user)
@message = Message.new
respond_to do |format|
format.html
format.js { render :template => "tasks/update.js.erb", :template => "tasks/destroy.js.erb", layout: false }
end
end
else
redirect_to user_profile_path(@user)
end
end
更新:
users/show:
<%if @conversation%>
<%= render 'conversations/show' %>
<% end %>
<tbody class="newtaskinsert2">
<%= render partial: "tasks/task_between", collection: @tasks, as: :task %>
</tbody>
conversations/_show:
<div class="chatboxcontent">
<% if @messages.any? %>
<%= render @messages %>
<% end %>
</div>
<div class="chatboxinput">
<%= form_for([@conversation, @message], :remote => true, :html => {id: "conversation_form_#{@conversation.id}"}) do |f| %>
<%= f.text_area :body, class: "chatboxtextarea", "data-cid" => @conversation.id %>
<% end %>
<%= form_for([@conversation, @message], html: {class: "refile_form"}, remote: true) do |form| %>
<span class="btn btn-success btn-sm btn-file">Choose file
<%= form.attachment_field :message_attachment, direct: true, presigned: true, class: "choosefile" %></span>
<%= form.submit "Send File", class: "btn btn-primary btn-sm btn-submit-refile", style:"display:none"%>
<% end %>
<span id="progresspercent"></span>
</div>
您只能在控制器中保留@user 实例变量,并且在局部使用:@user.tasks 而不是@tasks,@user.tasks.new 而不是@task 等。另请注意,您可以将参数传递给 partials (3.4.4 Passing Local Variables)
示例:
<%= render partial: "your_partial", locals: {tasks: @user.tasks} %>
更新:
用你的方式(从 class 调用方法而不是对象)你可以做类似的事情:
def show
@user = User.find(params[:id])
if Task.between(current_user.id, @user.id).present?
# @user.tasks.where(another_user_field_name: current_user).present? - looks more like Rails way
@tasks = Task.uncompleted.between(current_user.id, @user.id).order("created_at DESC").includes(:assigner).paginate(page: params[:page], per_page: 12)
@conversation = Conversation.between(current_user.id, @user.id).first
if @conversation
respond_to do |format|
format.html
format.js { render :template => "tasks/update.js.erb", :template => "tasks/destroy.js.erb", layout: false }
end
end
# Do not forget that if @conversation is not exists this code render views by default way
else
redirect_to user_profile_path(@user)
end
end
<%= render 'conversations/show' %>
<tbody class="newtaskinsert2">
<%= render partial: "tasks/task_between"%>
</tbody>
<%if @conversation%>
<div class="chatboxcontent">
<%= render '_your_messages_partial', locals: {messages: @conversation.messages.includes(:user)}%>
</div>
<div class="chatboxinput">
<%= form_for([@conversation, @conversation.messages.new], :remote => true, :html => {id: "conversation_form_#{@conversation.id}"}) do |f| %>
<%= f.text_area :body, class: "chatboxtextarea", "data-cid" => @conversation.id %>
<% end %>
<%= form_for([@conversation, @conversation.messages.new], html: {class: "refile_form"}, remote: true) do |form| %>
<span class="btn btn-success btn-sm btn-file">Choose file
<%= form.attachment_field :message_attachment, direct: true, presigned: true, class: "choosefile" %></span>
<%= form.submit "Send File", class: "btn btn-primary btn-sm btn-submit-refile", style:"display:none"%>
<% end %>
<span id="progresspercent"></span>
</div>
<% end %>
如果使用关系(@user.conversations 而不是 Conversation.between...等),您可以使此代码更短
我建议对您的视图使用缓存技术:
http://edgeguides.rubyonrails.org/caching_with_rails.html#fragment-caching
http://edgeguides.rubyonrails.org/caching_with_rails.html#russian-doll-caching
在性能仍然是您的问题的极端情况下,我建议开始对部分进行非规范化,直到您对性能满意为止。
我有一个 rails 应用程序。我在 users/:id/show 页面上显示来自不同 类 的更多部分(用户、任务、对话、消息)。我在 users.controller 的 def show 动作中设置了所有实例变量(也适用于其他 类)。
好像有点重,有没有比这更好的方法呢? (我在 AJAX 调用中使用了@task 和@message。)
def show
@user = User.find(params[:id])
if Task.between(current_user.id, @user.id).present?
@tasks = Task.uncompleted.between(current_user.id, @user.id).order("created_at DESC").includes(:assigner).paginate(page: params[:page], per_page: 12)
@task = Task.new
if Conversation.between(current_user.id, @user.id).present?
@conversation = Conversation.between(current_user.id, @user.id).first
@messages = @conversation.messages.includes(:user)
@message = Message.new
respond_to do |format|
format.html
format.js { render :template => "tasks/update.js.erb", :template => "tasks/destroy.js.erb", layout: false }
end
end
else
redirect_to user_profile_path(@user)
end
end
更新:
users/show:
<%if @conversation%>
<%= render 'conversations/show' %>
<% end %>
<tbody class="newtaskinsert2">
<%= render partial: "tasks/task_between", collection: @tasks, as: :task %>
</tbody>
conversations/_show:
<div class="chatboxcontent">
<% if @messages.any? %>
<%= render @messages %>
<% end %>
</div>
<div class="chatboxinput">
<%= form_for([@conversation, @message], :remote => true, :html => {id: "conversation_form_#{@conversation.id}"}) do |f| %>
<%= f.text_area :body, class: "chatboxtextarea", "data-cid" => @conversation.id %>
<% end %>
<%= form_for([@conversation, @message], html: {class: "refile_form"}, remote: true) do |form| %>
<span class="btn btn-success btn-sm btn-file">Choose file
<%= form.attachment_field :message_attachment, direct: true, presigned: true, class: "choosefile" %></span>
<%= form.submit "Send File", class: "btn btn-primary btn-sm btn-submit-refile", style:"display:none"%>
<% end %>
<span id="progresspercent"></span>
</div>
您只能在控制器中保留@user 实例变量,并且在局部使用:@user.tasks 而不是@tasks,@user.tasks.new 而不是@task 等。另请注意,您可以将参数传递给 partials (3.4.4 Passing Local Variables)
示例:
<%= render partial: "your_partial", locals: {tasks: @user.tasks} %>
更新:
用你的方式(从 class 调用方法而不是对象)你可以做类似的事情:
def show
@user = User.find(params[:id])
if Task.between(current_user.id, @user.id).present?
# @user.tasks.where(another_user_field_name: current_user).present? - looks more like Rails way
@tasks = Task.uncompleted.between(current_user.id, @user.id).order("created_at DESC").includes(:assigner).paginate(page: params[:page], per_page: 12)
@conversation = Conversation.between(current_user.id, @user.id).first
if @conversation
respond_to do |format|
format.html
format.js { render :template => "tasks/update.js.erb", :template => "tasks/destroy.js.erb", layout: false }
end
end
# Do not forget that if @conversation is not exists this code render views by default way
else
redirect_to user_profile_path(@user)
end
end
<%= render 'conversations/show' %>
<tbody class="newtaskinsert2">
<%= render partial: "tasks/task_between"%>
</tbody>
<%if @conversation%>
<div class="chatboxcontent">
<%= render '_your_messages_partial', locals: {messages: @conversation.messages.includes(:user)}%>
</div>
<div class="chatboxinput">
<%= form_for([@conversation, @conversation.messages.new], :remote => true, :html => {id: "conversation_form_#{@conversation.id}"}) do |f| %>
<%= f.text_area :body, class: "chatboxtextarea", "data-cid" => @conversation.id %>
<% end %>
<%= form_for([@conversation, @conversation.messages.new], html: {class: "refile_form"}, remote: true) do |form| %>
<span class="btn btn-success btn-sm btn-file">Choose file
<%= form.attachment_field :message_attachment, direct: true, presigned: true, class: "choosefile" %></span>
<%= form.submit "Send File", class: "btn btn-primary btn-sm btn-submit-refile", style:"display:none"%>
<% end %>
<span id="progresspercent"></span>
</div>
<% end %>
如果使用关系(@user.conversations 而不是 Conversation.between...等),您可以使此代码更短
我建议对您的视图使用缓存技术:
http://edgeguides.rubyonrails.org/caching_with_rails.html#fragment-caching http://edgeguides.rubyonrails.org/caching_with_rails.html#russian-doll-caching
在性能仍然是您的问题的极端情况下,我建议开始对部分进行非规范化,直到您对性能满意为止。