重构到helper相关的笔记记录

在helper重构view的代码,遇到包了很多层的html可以用字串的方式处理

def render_vote_icon(work)
    if work.work_voter.include?(current_user) && work.competition.get_on?
       "<span class='vote_counts_span'><i class='fa fa-thumbs-up' aria-hidden='true'></i> #{@work.vote_counts}</span>".html_safe
    else
       "<span class='vote_counts_span'><i class='fa fa-thumbs-o-up' aria-hidden='true'></i> #{@work.vote_counts}</span>".html_safe
    end
  end

要注意的点:

  • 字串要用双引号包起来
  • 外面是双引号的话,里面要用改成单引号(双引号包单引号,或者单引号包双引号)
  • 中间的ruby语言用#{}包起来
  • 最后一定要加.html_safe

helper相关

def render_vote_button(work, user)
    if work.competition.get_on?
      if work.work_voter.include?(user)
        link_to("感谢支持", "#" ,class:"btn vote-btn-lg disabled")
      else
        link_to('#', class:"btn vote-btn-lg", id:"upvote-btn") do
          content_tag(:i, "", class: "fa fa-thumbs-o-up", :'aria-hidden' => true)+"支持他"
        end
      end
    end
  end
  • 搜索关键词 rails content tag aria
  • +左右都是字串,两个字串组合要用+
    ps:
    link_to("work_path(work)+params", "data-toggle" => "modal", 'data-target' => '#workModal', remote: true) do

  • content_tag里面有一个空字符串,是因为要严格按照api里查到的格式来写,不然会报错


helper相关,重构到helper出现了一个问题。在html的时候有两个按钮,refactor到helper之后(不加result)只剩一个按钮。

原因:html是边读取边加载到网页的,而使用helper,则是先读取判断,最后回传资料(回传的是最后的结果)。而不加result的话,最后是读取到link_to("查看全部作品", competition_path(competition), class:"vote-btn")。所以这段代码以上的资料只是作为逻辑存在,最后回传的是这段代码。所以只会显示一个按钮。

解决方法:用result的方法,result加到的地方会回传,所以两个按钮就都可以显示了。

ps:因为加了result,这是个字段。所以需要在最后加上html_safe

  • view

    <% if Competition.last.present? %>
    <% if Competition.last.end? %>
    <%= link_to("查看获奖作品", awards_competition_path(Competition.last) ,class:"work-btn") %>
    <% else %>
    <% if current_user && current_user.valid_member? %>
    <%= link_to("我要参赛", new_competition_work_path(Competition.last) ,class:"work-btn") %>
    <% else %>
    <%= link_to("我要参赛", "#", class:"work-btn", "data-toggle" =>"modal", "data-target" => "#tips") %>
    <% end %>
    <% end %>
    <%= link_to("查看全部作品", competition_path(Competition.last) ,class:"vote-btn") %>
    <% else %>
    比赛还未开始,请耐心等候
    <% end %>

  • helper

    def render_competition_button_change(competition, user)
    result = ""
    if competition.present?
    if competition.end?
    result += link_to("查看获奖作品", awards_competition_path(competition) ,class:"work-btn")
    else
    if user && user.valid_member?
    result += link_to("我要参赛", new_competition_work_path(competition), class:"work-btn")
    else
    result += link_to("我要参赛", "#", class:"work-btn", "data-toggle" =>"modal", "data-target" => "#tips")
    end
    end
    result += link_to("查看全部作品", competition_path(competition), class:"vote-btn")
    else
    result += "比赛还未开始,请耐心等候"
    end
    result.html_safe
    end


helper里面是可以套helper的,不过调取套用的helper时也是要传参

def render_competition_button_change(competition, user)
    result = ""
     if competition.present?
       if competition.end?
         result += link_to("查看获奖作品", awards_competition_path(competition) ,class:"work-btn")
       else
         result += render_participate_competition_button(user, competition)
       end
       result += link_to("查看全部作品", competition_path(competition), class:"vote-btn")
     else
        result += "比赛还未开始,请耐心等候"
     end
     result.html_safe
  end

  • 正确

link_to('#', class:"btn vote-btn-lg", id:"upvote-btn")

  • 错误(多了一个空格键)

link_to ('#', class:"btn vote-btn-lg", id:"upvote-btn")

三个小知识

①answers里面有很多数据,要对数据根据user的判断条件进行过滤

解法一:连接数据表(多对多关系)——推荐
解法二:使用includes调用

  scope :find_student_answers , -> {includes(:user).where(users: { is_admin: false}).where(users: { is_staff: false}).where(users: { is_editor: false})}

参考:https://doc.bccnsoft.com/docs/rails-guides-4.1-cn/active_record_querying.html13.2)
搜索关键词:rails sql query

②where("users.expired_at" == "Sun, 31 Dec 2017 08:00:00 CST +08:00")

输出字段的时候不用 -> , 用 ==

③如何从view传参数到controller

<%= link_to "Add Product", new_product_path(:param1 => "value1", :param2 => "value2") %>

然后在相应的controller里面调用params1即可

搜索关键词:link to params

markdown接入

  • markdown to html

无论什么输入框,只要输入markdown语言即可转为特定格式输出。

gem "ultra_markdown", github: "rocodev/ultra_markdown"

https://github.com/rocodev/ultra_markdown

Usage:

"string".to_markdown

例如:

<%= @task.description.to_markdown %>

备用:red carpet

https://github.com/vmg/redcarpet

  • markdown 编辑器

gem 'simplemde'

http://www.rubydoc.info/gems/simplemde-rails/1.10.2

安装gem

Usage:

①在对应的layout里 (注:如果和已经转载的其他编辑器有样式冲突,可以把stylesheet的那段代码直接移到对应需要加载simpleMDE的view里,而不在layout里加载)

  <head><%= csrf_meta_tags %>
      <%= stylesheet_link_tag    'simplemde.min' %>
      <%= javascript_include_tag 'simplemde.min' %>
      <%= yield :stylesheets %></head>

②config/initializers/assets.rb

Rails.application.config.assets.precompile += %w(simplemde.min.scss)
Rails.application.config.assets.precompile += %w(simplemde.min.js)

③加载编辑器(在content的输入框里)

<%= simple_form_for [:admin, @faq] do |f| %><%= f.input :content, :label =>"解答"  %><script>
var simplemde = new SimpleMDE({
  element: document.getElementById("faq_content")
});
simplemde.value();
</script>
# 放在最后

2016/11/15

今天做了什么

今天主要对网页进行一些细致的优化,主要是一些能提高用户体验,让用户使用更顺畅的小细节。

今天学到了什么

helper中输出html的写法——使用content_tag(类似的还有image_tag

常用写法:

content_tag(:p, "Hello world!")

=> <p>Hello world!</p>

content_tag(:div, content_tag(:p, "Hello world!"), class: "strong")

=> <div class="strong"><p>Hello world!</p></div>

content_tag(:div, "Hello world!", class: ["strong", "highlight"])

=> <div class="strong highlight">Hello world!</div>

今天遇到的坑

view 里面判断已注册的用户用<% if current_user %>

!!!!!不能带问号!!!!!

2016/11/14

今天做了什么

最近学到了什么

①用js做fix导航栏和置顶按钮

fix导航栏:

http://www.acgxt.com/375.html

置顶按钮:

http://www.w3cplus.com/jquery/scrolling-to-the-top-with-jquery

②关于yml文件

  • 多个yml文件是为了区分和便于找到,不用引用,直接写就可以。类似于scss文件的排布法
  • yml文件切记要对齐

同一层级的命令如果没有对齐,则会报错。这也算是一个坑

③scss 不要写@import,要写require,这样效能比较好

④在iterm查看git情况

方法1:

brew install tig安装tag可以看push情况

使用方法:

在项目目录下:
tig查看git 的 log

常用指令:
上下箭头选择log的版本
enter进入具体版本查看详细
k和j是上下滚动查看详细信息的内容
m是关闭详细信息,返回到log的版本
pageup/pagedown是同k和j,只不过是一屏一屏的滚动

方法2:

git blame +文件路径 可以看特定文件每个人的push情况

⑤全球化合作的两个网站——SketchDeck、thoughtbot

2016/11/8、9

做了什么

①研究devise的定制化,发现太复杂,研究了快一天后只能放弃

②完成Assignment的页面优化

③完成进度条的优化制作

学到了什么

①多VPN错乱怎么解决

原因:开了多态,也开了Lantern,错乱了

解决方法:关闭Lantern,只留多态

②图片突出背景外的css写法和富文本的输出方法

1、要写出图片突出到背景外的效果,一开始的思路是用z-index用图层的思路做,其实不用那么麻烦。只需要把图片写个负值的margin-top就可以实现了。(原来图片顶部应该和色块平齐,写了负值的margin-top实现的就是往上移动)

2、课程的描述部分输出了html语言。原因是<%= xxx %>输出的是普通文本,而如果是在编辑器编辑输出的则是富文本格式,要用sanitize,比如<%= sanitize(@course.description) %>

③如何定制循环中某一项为特例

例:执行循环,同时最后一个定制

<% @stuff.each_with_index do |thing, i| %>
  <% if (i + 1) == @stuff.length %>
    # ...last one stuff
  <% else %>
    # ...normal stuff
  <% end %>
<% end %>

原理:i为计数(也可换为其他字母或单词),每次新读取一个stuff都会计数(0,1,2...)。因此,要对最后一个进行定制,只需让i+1=length即可。其他的定制也是按照这个思路进行。

④用style定义css的区别写法

html语言内用等号,且class和style的间隔不能加<div class="small-progress-bar" style="margin-left:0px;" >

erb语言内用冒号:<%= link_to assignment_path( assignment), class: "" ,style:"height:85px; width:450px;" do %>

⑤垂直居中的一种写法+强行换行的写法(平时是靠各单词间的空格换行的)

.bar-title {
  height: 50px;
  width: 120px;
  background-color: #545965;
  border-top-left-radius:0.5em;
  border-bottom-left-radius:0.5em;
  float: left;
  display: table;

  .bar-title-text {
    color: #DCDCDC;
    text-align: center;

    width: 120px;
    word-break: break-all;
    display: table-cell;
    vertical-align: middle;

  }
}

垂直居中思路:display为table,在单元格里用vertical-align

强行断行的写法:word-break: break-all;

领悟

①一个东西研究太久还是研究不出来的话,不要过于执着。可以问别人,或者用其他方式解决。只要能解决问题,并且把办法嵌入到自己的组块中,都是有效的。

②遇到问题,先把能想到的全部解决方案写下来(如果解决的过程中灵感来了,也把新想到的方法写下来),大概限制自己一个时间,解决不了就先处理下一个问题。在一个问题上一直耗着是没有任何效益的。用相同的无效方法死磕同一个问题是经常犯的错误。所以,不是没有解决问题的能力,而是解决问题的方法出现了问题。

计划

明天起每天晚上拨出点时间在办公室里学学设计,从扁平化icon入手。

2016/11/7

今天做了什么

优化全网文案,全网。。。。。。

2016/11/4

今天做了什么

①修改用户名出现的bug

②course及相关页面,当隐藏时用户不能进入。如果进入则自动返回学习中心

③删除注册、登录、退出的flash进度提示条

今天学到了什么

devise的flash条在不同状态有不同的提示用语,都写在了devise默认的文件里(这里可以查看:https://gitlab.com/gitlab-org/gitlab-ce/blob/4377ba1c360cf6f4d15e3b5ad2a7ed7bc41f795e/config/locales/devise.en.yml), 而通过atom搜索专案是搜索不到的。
ps:这里可以下载各种不同语言的I18N: https://www.localeapp.com/projects/377/downloads
I18N相关wiki:https://github.com/plataformatec/devise/wiki/i18n

所以要去文件查看,查看好后,找到想删除或者重新定义提示语的选项,在devise.en.yml里重新来写。比如注册、登录、退出要删除flash条,则要写如下代码:

  略
      signed_up: ''
    sessions:
    略
      signed_in: ''
      signed_out: ''

感悟

①每天的注意力有限,高效脑力也是有限的,所以做事情的时候要珍惜这些脑力,把脑力专注用在重要的事情上,临时想起的不重要的事记下来即可(或者规定自己两分钟,两分钟解决不了就记下来以后弄)。这是保护自己高效脑力的方法。(其实就是推迟对好奇心的满足感)。

②解bug其实和看病的原理差不多,通过分析代码或者google先找到bug的根源在哪里,然后在根源处修改、优化、调整,解决问题即可。

2016/11/3

今天做了什么?

①作业提交后能显示已提交。(最后也没能做出来,Rebecca做出来了)

②理清所有与恭喜页面有关的流程,新增页面,调整逻辑。

③处理完成登录系统。包括登录、注册、退出的相关流程。

④在做功能的时候,因为各种原因(包括自己操作不当、之前在处理ontrack代码绕过的一些问题重新浮现等等)出现了各种坑,在老师帮助下勉强弄清了与登录、session、csrf有关的一些东西。

今天学到了什么?

①理解一下has_many/belongs_to和栏位的一些关系

比如post belongs_to course,如果要存course的id,则还要在post 这个model 里面建一个course_id的栏位。(注:没有建立user_id是因为devise这个gem自带了current_user可以直接使用)

如果在controller里面post要调用course的话,其实是要先通过post.course调用course_id,进而在调用course的其他栏位。比如:

@course = @post.course(调用course_id)
if @course.paid_courses(调用coursepaid_courses的栏位)

②新思路:要对数据库传入资料或更改不一定要新建一个action或者通过按钮的点击实现功能。也可以放在原来的action,比如create,update里面也可以,这样就是只要实行了create或者update这个动作,就是做了某个model里面def的东西。

③一个栏位只能存储一个值!!!

多对多关系的原因是:一个栏位只能有一个值。

比如:user_id (1) post_id(1,2,3)

错误思路:在user的model 里面建立一个post_id 的栏位,里面传进去post_id(1,2,3)

正确思路:新建一个post_relationship 的model,里面包含user_id和post_id两个栏位,这样里面就可以这样存储:user_id(1) post_id(1),user_id(1) post_id(2),user_id(1) post_id(2)

所以要思考的是用何种方式把数据存进数据库里,即如何告诉数据库我们要存什么。

④clone专案必须用和之前不一样的文件名

删除专案后,重新clone或者建立一个相同文件名的专案会出现这样的错误。

建一个不同文件名的专案即可解决。

⑤一般来说,clone一个新专案后需要运行的代码整理

bundle install

bundle update

rake db:create

rake db:migrate

rake db:seed

⑥新clone下来的专案(quanzhan)出现登录不进去或者退出不了的情况(数据传不进去)

原因:
原来ontrack的设计是有很多的team,每个team对应一个domain。每次登陆时,只要是同一个team,就是同一个domain,同一个csrf,这时devise就会顺利通过。而现在我们把team拔掉了,所以不需要domain来实现这个功能。
这个时候,如果domain还在的话,csrf则会每次都判断为不同人进入(csrf是从session来判断的),所以devise会将这种情况判定为非法登入,则会阻止登陆。
解决办法:

  • 去掉config/initializers/session_store.rb里面的

domain: ENV.fetch("SESSION_STORE_DOMAIN", ENV.fetch("APPLICATION_HOST"))

原因:

Rails.application.config.session_store(
:cookie_store, :cookie_store,
key: "quanzhan_session", key: "quanzhan_session",
domain: ENV.fetch("SESSIONSTORE_DOMAIN", ENV.fetch("APPLICATIONHOST")),

tld_length: 2 tld_length: 2
) )

session_store.rb 里面没有 SESSIONSTORE_DOMAIN

所以 cookie 吃的是 .quanzhan.dev 而不是 quanzhan.dev

因此在奇怪的情形下,会同时存在两个 cookie

一个叫 .quanzhan.dev 与 quanzhan.dev

浏览器分不清楚谁是谁,所以根本登不进去。

解决的方法就是把 SESSIONSTORE_DOMAIN 干掉

并且清除浏览器的 cookie 就回复正常了

⑦网页运行的时候, rake db:drop 是会失败的,因为网页还在运行原有的数据库,所以需要先 powder down 关掉powder(或者退出rails s),再 rake db:droprake db:createrake db:migrate ,然后再powder up

⑧用count的思路可以解决作业提交后能显示已提交这个问题。作业提交后显示已提交,可以拆解为判断所有answer提交后显示某个东西。

思路:读取到answer记为0,否则记为1。然后判断sum>0即为作业未完成,else则为作业已完成。

这种思路可以解决类似于需要计数的一些典型问题。

实现代码:

<% if post.tasks_count > 0 %>
            <% sum = 0 %>
            <% post.tasks.each do |task| %>
              <% if current_user.has_submitted_answer?(task) %>
                <% unsubmit = 0 %>
              <% else  %>
                <% unsubmit = 1 %>
              <% end %>
              <% sum = sum + unsubmit  %>
            <% end %>
            
            <% if sum > 0 %>
              <%= ibutton("做作业", post_path(post), :class => "pull-left btn btn-default btn-sm", :iclass => "fa fa-coffee") %>
            <% else %>
              <%= ibutton("已提交", post_path(post), :class => "pull-left btn btn-default btn-sm", :iclass => "fa fa-check") %>
            <% end %>
        <% end %>
def has_submitted_answer?(task)
    task.answers.where(user: self).first
  end

⑨怎样用新的自己建立的controller替代devise默认的controller:

# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
class RegistrationsController < Devise::RegistrationsController
  def new
    super
  end

  def create
    # build_resource(sign_up_params)
    super
  end

  def edit
    super
  end

  private

  def sign_up_params
    params.require(:user).permit(:username, :email, :password, :password_confirmation)
  end

  def after_update_path_for(resource)
   account_users_path
   end

   def after_sign_up_path_for(resource)
     account_congratulations_path
   end
end

private下面可以设置各种转态的跳转。

git stash

如果遇到自己在某分支上做了很多工作,但是想要把这些工作抛在一个新分支去,可以这样做:

git stash把所做的修改先放在一个贮藏处,这时候git status可以看到没做修改。然后新建一个分支,运行git stash apply把内容拉过来即可。

⑪route写法区别

get "account/congratulations/after_pay", to: "account/congratulations#after_pay"
namespace :accont do
  resources :congratulations do
    member do
      post :after_pay
    end
  end
end

上面的写法导出的链接是account/congratulations/after_pay,下面则是account/congratulations/:id/after_pay

小技巧

很多gem里面有很多的wiki,里面有很多常见问题的解答,如果遇到问题可以到里面去看看。

How To: redirect to a specific page on successful sign in

How To: Redirect to a specific page on successful sign up (registration)

2016/11/2

今天做了什么

做了显示作业是否已经提交的功能,未遂!

今天学到了什么

①在view里面需要写多个循环时,一种更优的写法:

<%= render :partial => "task", :collection => post.tasks %>

这样,在_task.html.erb里面就可以直接调用task了。

②rails c 出现莫名错误(比如已经确认过几遍确实定义好的方法提示错误)的时候,记得重开!重开!重开!!!

反省

做功能切忌畏手畏脚,要敢于瞎玩、瞎折腾,动手下去各种试,也许答案就出来了。

想起了一句话,“如何入门?一脚踹开啊!”