无法从视图中访问ActiveModel :: Serialized属性

时间:2014-08-04 15:31:02

标签: ruby-on-rails json active-model-serializers

尝试从此API获取某些产品 - 但我似乎无法从我的视图中访问我的ActiveModel :: Serialized属性product.name。我哪里出错了?

型号:

require 'rest_client'

class ThirdPartyProducts
    include ActiveModel::Serializers::JSON

    # Not setting attributes here as there's just too many in the JSON response
    # attr_accessor :lorem, :ipsum, :dolor, :sit, :amet

    def attributes=(hash)
      hash.each do |key, value|

        # Set attributes here instead
        # http://stackoverflow.com/questions/1734984/why-cant-i-use-attr-accessor-inside-initialize

        self.class.send(:attr_accessor, "#{key}")
        send("#{key}=", value)
      end
    end

    def self.fetch
      response = RestClient.get "http://api.shopstyle.com/api/v2/products?pid=uid7849-6112293-28&format=json&fts=women"
      raw_products = JSON.parse(response)["products"]

      raw_products.map do |product|
        what_to_name_this ||= self.new
        product = what_to_name_this.from_json(product.to_json)

        name = product.name
        # url = ...
        # image = ...
      end
    end
end

控制器:

class MainController < ApplicationController
  def index
    @products = ThirdPartyProducts.fetch
  end
end

查看:

<% if @products.any? %>
  <% @products.each do |product| %>
    <div class="product">
      <%= product.name %>
    </div>
  <% end %>
<% end %>

错误:

NoMethodError in Main#index
Showing /root/rails-repo/app/views/main/index.html.erb where line #5 raised:

undefined method `name' for "McQ Alexander McQueen Mesh-paneled stretch-jersey top":String
Extracted source (around line #5):
  <% if @products.any? %>
    <% @products.each do |product| %>
      <div class="product">
        <%= product.name %>
      </div>
    <% end %>
  <% end %> 

Rails.root: /root/rails-repo

app/views/main/index.html.erb:5:in `block in _app_views_main_index_html_erb__1422808888741532498_21926060'
app/views/main/index.html.erb:3:in `each'
app/views/main/index.html.erb:3:in `_app_views_main_index_html_erb__1422808888741532498_21926060'

1 个答案:

答案 0 :(得分:1)

假设第三方产品是一系列产品,您可能希望重新定义您的课程,例如:

class ThirdPartyProducts
  require 'rest_client'

  def self.fetch
    response = RestClient.get "http://api.shopstyle.com/api/v2/products?pid=uid7849-6112293-28&format=json&fts=women"
    raw_products = JSON.parse(response)["products"]
    products = []
    raw_products.map { |pro| Product.new(pro) }
  end
end

class Product
   def new(args)
     hash.each do |key, value| 
       self.class.send(:attr_accessor, "#{key}") }
       send("#{key}=", value)
     end
   end
end

这一行:

@products = ThirdPartyProducts.fetch

返回一组Product个实例,每个实例都有api的响应。

由于数组存在,您不再需要了:

<% if @products.any? %>

@products.any始终是数组,如果为空,则迭代不会呈现下一行,因此您在视图中没有任何逻辑。

更新回答:

其他选项是在视图中为每个元素使用哈希。

@products = Products.fetch

class Products
  def self.fetch
    response = RestClient.get "http://api.shopstyle.com/api/v2/products?pid=uid7849-6112293-28&format=json&fts=women"
    JSON.parse(response)["products"]
  end
end

在观点中:

<% @products.each do |product| %>
   <%= product["name"] %>
   <%= product["price"] %>
<% end %>