rails是抽象深层对象文字数据的最佳方式

时间:2013-06-26 01:00:27

标签: ruby-on-rails

我的控制器中有这样的代码:

def home
  @mainImage = []
  @mainImage.push(
    {:breakpoint => 1024, 
     :src => i_path('pages/home-d.jpg'),
     :src_2x => i_path('pages/home-d_2x.jpg')}
  )
  @mainImage.push(
    {:breakpoint => 768, 
     :src => i_path('pages/home-t.jpg'), 
     :src_2x => i_path('pages/home-t_2x.jpg')}
  )
  @mainImage.push(
    {:breakpoint => 320, 
     :src => i_path('pages/home-m.jpg'), 
     :src_2x => i_path('pages/home-m_2x.jpg')}
  )
  @alt = 'An image description'
  @defaultImage = i_path('pages/home-m.jpg')
end

视图中的哪一个是在部分帮助下渲染的。

我现在需要添加类似的功能来从回形针对象渲染模型属性。

现在看起来像这样:

@respImage.push(
  {:breakpoint => 1024, 
   :src => slide.image.url(:desktop_reg),
   :src_2x => slide.image.url(:desktop_retina)}
)
@respImage.push(
  {:breakpoint => 768, 
   :src => slide.image.url(:tablet_reg),
   :src_2x => slide.image.url(:tablet_retina)}
)

#...

最终目标是使用幻灯片进行幻灯片放映。 幻灯片具有多个属性字符串和回形针属性。 paperclip属性为每个图像大小设置了6种样式。

Rails将上述数据传输到视图的标准机制是什么? 我假设这个通用数组不是最灵活的解决方案。


这是代码最终的地方。

在控制器中:

def home
  @mainImage2 = RespImage.new(:alt => 'default homepage image')

  @mainImage2.add_breakpoint(BREAKPOINTS['desktop'],i_path('pages/home-d.jpg'),i_path('pages/home-d_2x.jpg'));
  @mainImage2.add_breakpoint(BREAKPOINTS['tablet'],i_path('pages/home-t.jpg'),i_path('pages/home-t_2x.jpg'));
  #...

models / resp_image.rb:

class RespImage
  attr_accessor :alt, :breakpoints

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def add_breakpoint(px,src,src_2x)
    self.breakpoints ||= [];
    self.breakpoints.push RespBreakpoint.new(:px => px, :src => src, :src_2x =>src_2x)
  end

  def add_paperclip_breakpoints(paperclip)
    add_breakpoint(BREAKPOINTS('desktop'), paperclip.url(:desktop_reg), paperclip.url(:desktop_retina));
    add_breakpoint(BREAKPOINTS('tablet'), paperclip.url(:tablet_reg), paperclip.url(:tablet_retina));
    add_breakpoint(BREAKPOINTS('mobile'), paperclip.url(:mobile_reg), paperclip.url(:mobile_retina));
  end

  def default_src
    self.breakpoints.sort.first.src
  end
end

模型/ resp_breakpoint

class RespBreakpoint
  include Comparable

  attr_accessor :px,:src,:src_2x

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def better_than?(other)
    self.px > other.px
  end

  def <=>(other)
    self.px <=> other.px
  end

  def eql?(other)
    self.px === other.px
  end
end

非常感谢下面的 @Dave Newton

1 个答案:

答案 0 :(得分:1)

首先,use value objects。虽然哈希数组起初看起来很容易,但VO可以帮助您轻松地封装行为和数据,并提高可读性。

其次,考虑将这些VO设为“顶级”模型,以便使用适当命名的部分进行渲染,我假设它也会清理你的帮助。

你的问题的最后一部分有点不透明,没有任何上下文:你是什么意思“添加类似的功能来从Paperclip对象渲染模型属性”?对象具有相同的属性吗?数据是否已由类或类的属性表示?

如果是后者,那么你可以使用duck-typing来消除一些重复。


现在看起来这些信息存储有点时髦。我可能会稍微改变一下模型并使用一个哈希,用断点键入(有用,因为它是CSS用来触发样式更改)或更具语义的东西(例如:desktop:tablet,等)。

您的模型将包含散列键作为属性(即breakpointsrcsrc_2x)。

值可以存储在任何地方,这取决于他们需要更改的频率。使用常量,YAML文件或Ruby配置对象等可能就足够了。

数组本身将由实用程序类或服务对象创建,它采用一些参数来确定需要进入哪些信息。您可能有一种方法可以根据传入的内容返回i_path或幻灯片图像URL(想想控制反转)。

或者它可以是装饰你的幻灯片模型和i_path等的假(或真)模型的装饰者。