15--helpers方法

前面我们讲的link_to、form_for、form_tag都是rails的前端的helpers方法(翻译过来就是辅助方法)。helpers方法还有很多,当然这节课我们要讲的helpers方法不是前端使用的helpers方法,而是控制器或模型中能够直接调用的一些辅助方法,并且我们能够自定义方法的名称以及里面的一些功能,这样的helpers方法我们可以称之为自定义的helpers方法(下面我们都叫自定义方法好了)。

前面我们讲过我们可以将自定义的库文件写在lib文件夹中,但是这种文件一般代码量很大独立成文件,暴露接口给用户去使用,如果是一些比较简短的小方法小接口想在工程中去调用怎么办呢?这时候就需要helpers文件发挥作用了。

我们可以看到工程目录下有如下文件:

除了application_helper这个文件是默认生成的以外,只要你有一个控制器或者说一个资源,会自动生成对应的helper文件,这个helper文件里的方法就能够在对应名称的控制器文件中使用。比如我们想在user控制器中使用我们自己定义的一个接口(或者叫函数),那么我们就可以将这个接口写在对应的users_helper文件中,同时在我们控制器的基类application_controller.rb中包含一下我们的users_helper,这样你就可以在user控制器中使用这个方法了。

15--helpers方法_第1张图片

下面我们就用实例来讲一下在控制器中使用helpers文件的方式:

如下会话控制器和用户控制器都有这么一句,将已登陆用户的id保存进session变量的user_id参数里面,我们两个地方用到这个功能:1是登陆成功以后用到这个功能,2是注册成功以后也用到这个功能(因为前面我们实现了让用户注册完就直接是登陆状态了)

15--helpers方法_第2张图片

然后我们利用helpers文件(文件名中是helper没s)来实现:

15--helpers方法_第3张图片

添加一个方法后,结果如下:

15--helpers方法_第4张图片

这个函数就是将@user对象作为参数user传入log_in这个方法,将参数user(也就是@user对象)的id属性保存到全局变量session的user_id参数里,这样就完成了公共方法的定义

但是还不能使用,我们接下来还得把sessions_helper.rb文件包含进application_controller.rb这个文件里,更改后如下:

15--helpers方法_第5张图片

直接添加第5行代码如下(会自动提示SessionsHelper,这个就是sessions_helper文件,虽然大小写下划线不一致但实际指的是同一个文件):

15--helpers方法_第6张图片

然后回到注册控制器和登陆控制器文件,session[:user_id]=@user.id替换成log_in @user 

15--helpers方法_第7张图片

15--helpers方法_第8张图片

这样helpers的用法就完成了,但是我们还需要继续添加几个helpers方法,因为我们的微博应用虽然有了登陆功能,但是我们直接在浏览器输入路由比如微博show页面的路由就可以直接访问(直接跳过登陆和注册也可以访问),所以需要完善。

我们需要添加一个功能,就是进入一个页面的时候判断你有没有登陆,如果你没有登陆就强制将页面转到登陆页。

第一步我们要添加的就是返回当前用户的这么一个方法,因为我们当前返回用户是怎么做的呢?就是查找session的user_id,但这样不好我们需要利用helpers文件来完善:

如下添加第6到9行

15--helpers方法_第9张图片

还有查找用户可以使用find也可以使用find_by,参数都是id,但是区别在于查找失败find会抛出异常,而find_by返回nil,而我们这里需要的就是返回nil而不是抛出异常直接是错误页面了。

我们还可以再次修改一下,因为如果我们工程中经常调用这个current_user函数,我们调用一次就要查询一次数据库啊,很消耗资源而且速度慢。所以我们在查询之前可以先判断一下@current_user这个变量存在不存在,如果存在就不用再去查询数据库直接返回变量结果就行了,更改完如下:

15--helpers方法_第10张图片

||这里跟判断语句的作用是一样的。

完成这个工作以后我们就要添加一个共有函数判断用户有没有登陆,在里面要判断current_user这个公共函数的返回值,如果用户已经登陆返回true否则返回false,添加的代码如下第11到15行

还有就是添加了共有函数log_in,我们肯定还要添加一个登出方法,我们添加log_out方法代表登出(第17到19行),登出代码第18行我们之前就讲过了只要将session的会话保持的user_id删除就行,还有千万千万别忘了把@current_user变量置空,否则你在log_out里面登出了但是@current_user变量还有内容所以current_user方法还是会返回上一个用户,这肯定是不行的:

完整代码如下,注意我们在application_controller.rb文件中添加了SessionsHelper了(所以再添加新的公共函数就可以直接在session控制器中使用了不需要再去里面包含):

15--helpers方法_第11张图片

到此,我们就可以在工程中使用logged_in?这个方法,

那么我们回到sessions控制器中,先来修改destroy代码(这个代码是用来退出登录的用户):

15--helpers方法_第12张图片

修改的时候我们首先要判断该用户是不是登陆状态,如果是我们才进行退出操作,改完如下:

15--helpers方法_第13张图片

那么其他还要改哪里呢?我们应该去那些有对应视图的action中去判断有没有登陆,有才可以访问否则强制返回登陆页面。

其实也很简单,比如我们看一下user控制器的show这个动作(就是显示用户的个人页面):

15--helpers方法_第14张图片

我们往里面添加判断语句判断有没有登陆,有才可以访问否则强制返回根页面,更改后如下:

15--helpers方法_第15张图片

然后我们再去更改下路由的根地址:

原来的根地址如下是posts的index页面

改成登陆页面:

那么登陆页面路由是啥呢?跟会话保持的session有关,不是浏览器输入的路由哦,我们之前在routes.rb文件中就写了,如下找到

15--helpers方法_第16张图片

所以我们就知道根页面路由要改成如下:

然后我们回到浏览器,刷新一下下面的页面:

15--helpers方法_第17张图片

结果就强制回到根页面(因为我们把根页面改成登陆页了):

15--helpers方法_第18张图片

然后我们浏览器输入http://localhost:3000/users/4结果仍然回到登陆页面:

因为其他的还没添加,所以我们输入其他页面路由还是可以访问

15--helpers方法_第19张图片

如下报错不是不能访问,而是不存在该记录

15--helpers方法_第20张图片

还可以访问及其他页面:

15--helpers方法_第21张图片

15--helpers方法_第22张图片

这样我们就实现了强制你不能访问某些页面,除非你先登陆,但是如果不登陆很多页面都不能访问,那么我们到每个页面对应的action都要写判断语句就很麻烦。那么有没有这样一个方法,让我们只在一个控制器中(一个控制器里有多个对应视图的action)判断一次就可以了,指定哪些页面需要跳转回登陆页面(即哪些页面需要登陆才可以访问)这个我们先不讲,我们现在只要知道在每个需要如此处理的地方添加如下的判断就能实现:

if logged_in? 


else
redirect_to root_url #跳转到根页面
end

 

记住根页面路由是http://localhost:3000/,而我们把根页面设置为登陆页面,所以http://localhost:3000/login路由跟前面那个路由都是一样的。

现在还有个问题,我们输入后点击登陆

15--helpers方法_第23张图片

发现点击完还是跳转回该页面:

15--helpers方法_第24张图片

这个问题分析如下:

我们来到sessions控制器中找到对应动作create如下:

15--helpers方法_第25张图片

我们怀疑是log_in @user函数出问题或者redirect_to @user出问题

对于log_in @user,我们该回去为session[:user_id][email protected]刷新页面再登陆还是一样

对于redirect_to @user,我们觉得可能上面没问题还是执行了跳转语句,只不过@user这个页面出问题才一直显示登陆页面,我们就改成如下:

15--helpers方法_第26张图片

15--helpers方法_第27张图片

原因是路由写错了,所以我们再更改为:

15--helpers方法_第28张图片

15--helpers方法_第29张图片

这里我们再改成:

发现还是登陆页面,因此问题就知道了,页面会跳转说明登陆成功,需要登陆访问的页面却还是登陆页面看来没有会话保持登陆状态或者又登出了,所以才会一直强制返回登陆页面。至于上面posts的new页面能跳转是因为这个页面不需要登陆就可以访问。

分析完我们还是改回:

15--helpers方法_第30张图片

而我们登陆完跳转微博内容页users/4这个对应控制器的show动作如下,所以我们就知道很可能是这段代码的if条件不成立导致的:

15--helpers方法_第31张图片

而if条件不成立很可能就是logged_in?这个方法出错,

15--helpers方法_第32张图片

具体哪里错还不知道,但是我们可以通过这样一步一步查找问题出错的地方,比如loggged_in?没错,我们还能根据里面含有@current_user变量来追溯到会不会是current_user这个方法出错,若是还不是我们能进一步追溯到是不是哪里使用log_out方法导致:

15--helpers方法_第33张图片

 

 

你可能感兴趣的:(15--helpers方法)