控制器Rails中定义的对象的未定义方法

时间:2018-02-19 16:36:21

标签: ruby-on-rails ruby-on-rails-5

我有一个带有表单和表格的视图,可以显示数据库中的一些数据。每当我尝试在我的视图中从我的控制器访问该对象时,我得到undefined method domain for "https://www.lookagain.co.uk/":String。但如果<%@savedHTML = ScrapedPage.all%>一切正常。我知道我不应该在视图中这样做,因为它击败了MVC的目的,但我似乎没有完成修复。

查看:

<%= stylesheet_link_tag "masterstyles.css" %>




<% @url = 'default' %>
<%= form_for @url, :url => {:controller => "page_scraper", :action => "scrape"} do |f| %>
  <%= f.text_field (:url) %>
  <%= f.submit "Scrape" %>
<% end %>

<%@domain ='default'%>
<%@date ='default'%>

<%= form_for @domain, :url => {:controller => "page_scraper", :action => "compare"} do |f| %>
  <%=select_tag 'domain', options_for_select(@savedHTML.collect{ |u| [u.domain, u.domain] })%> 
  <%=select_tag 'date', options_for_select(@savedHTML.collect{ |u| [u.created_at, u.created_at] })%>
  <%= f.submit "compare" %>
<% end %>

<div class="subjects index">
  <h2>FGH Page Scraper</h2>



  <table class="listing" summary="Links list">
    <tr class="header">
      <th>ID</th>
      <th>link</th>
      <th>Created at</th>
      <th>Updated at</th>
    </tr>
    <% @savedHTML.each do |page| %>
    <tr>
      <td><%= page.id %></td>
      <td><%= page.domain %></td>
      <td class="center"><%= page.created_at %></td>
      <td class="center"><%= page.updated_at %></td>
      <td class="actions">
        <%= link_to("Delete", {:controller => 'page_scraper', :action => 'delete', :id => page.id}, :class => 'action delete') %>
      </td>
    </tr>
    <% end %>
  </table>
</div>

控制器:

class PageScraperController < ApplicationController
    require 'nokogiri'
    require 'open-uri'
    require 'diffy'
    require 'htmlentities'

    def scrape

        @url = watched_link_params[:url].to_s
        puts "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOG#{@url}"
        @page = Nokogiri::HTML(open(@url))
        coder = HTMLEntities.new
        @encodedHTML = coder.encode(@page)
        create

     end

     def index      
         @savedHTML = ScrapedPage.distinct.pluck(:domain)
      end

      def show
        @savedHTML = ScrapedPage.distinct.pluck(:domain)

      end

      def new
        @savedHTML = ScrapedPage.new


      end

      def create

        @savedHTML = ScrapedPage.create(domain: @url, html: @encodedHTML, css: '', javascript: '')

        if @savedHTML.save

          puts "ADDED TO THE DATABASE"

          redirect_to(root_path)
        else

          puts "FAILED TO ADD TO THE DATABASE"

        end
      end

      def edit

      end

      def upadate

      end

      def delete
        @savedHTML = ScrapedPage.find(params[:id])
      end

      def destroy
        @savedHTML = ScrapedPage.find(params[:id])
        @savedHTML.destroy
        redirect_to(root_path)
      end

     def compare

        @domain  = params[:domain].to_s
        puts @domain
        redirect_to(root_path)
        @timestamp

     end

    def watched_link_params

        params.require(:default).permit(:url)

    end

    def compare_params

        params.require(:domain).permit(:domain)

    end

end

1 个答案:

答案 0 :(得分:1)

问题在于,在控制器中,只将字符串值保存到@savedHTML变量(pluck只会给出给定对象的属性数组)。因此,您无法询问&#34; some_string&#34; .domain,因为String类没有domain方法。

如果domain对象上有ScrapedPage方法,那么在您的控制器操作(indexshow - 无论您处理的是什么)中,您应该替换

@savedHTML = ScrapedPage.distinct.pluck(:domain)

@savedHTML = ScrapedPage.select(:domain).distinct

后者会根据ScrapedPage值为您提供唯一的domain个对象。请查看here以获取更多信息和示例。

NB!也是重构的提示: 在private部分下使用强参数。此外,如果您在不同的操作中两次在控制器中使用相同的查询,那么最好在before_action中进行这样的查询:

class PageScraperController < ApplicationController
  before_action :set_saved_html, only: %i[index show]

  def index
  end

  def show
  end

  private

  def watched_link_params
    params.require(:default).permit(:url)
  end

  def compare_params
    params.require(:domain).permit(:domain)
  end

  def set_saved_html
    @savedHTML = ScrapedPage.select(:domain).distinct
  end
end