Asked  7 Months ago    Answers:  5   Viewed   35 times

The default Rails 4 project generator now creates the directory "concerns" under controllers and models. I have found some explanations about how to use routing concerns, but nothing about controllers or models.

I am pretty sure it has to do with the current "DCI trend" in the community and would like to give it a try.

The question is, how am I supposed to use this feature, is there a convention on how to define the naming / class hierarchy in order to make it work? How can I include a concern in a model or controller?

 Answers

78

So I found it out by myself. It is actually a pretty simple but powerful concept. It has to do with code reuse as in the example below. Basically, the idea is to extract common and / or context specific chunks of code in order to clean up the models and avoid them getting too fat and messy.

As an example, I'll put one well known pattern, the taggable pattern:

# app/models/product.rb
class Product
  include Taggable

  ...
end

# app/models/concerns/taggable.rb
# notice that the file name has to match the module name 
# (applying Rails conventions for autoloading)
module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :taggings, as: :taggable
    has_many :tags, through: :taggings

    class_attribute :tag_limit
  end

  def tags_string
    tags.map(&:name).join(', ')
  end

  def tags_string=(tag_string)
    tag_names = tag_string.to_s.split(', ')

    tag_names.each do |tag_name|
      tags.build(name: tag_name)
    end
  end

  # methods defined here are going to extend the class, not the instance of it
  module ClassMethods

    def tag_limit(value)
      self.tag_limit_value = value
    end

  end

end

So following the Product sample, you can add Taggable to any class you desire and share its functionality.

This is pretty well explained by DHH:

In Rails 4, we’re going to invite programmers to use concerns with the default app/models/concerns and app/controllers/concerns directories that are automatically part of the load path. Together with the ActiveSupport::Concern wrapper, it’s just enough support to make this light-weight factoring mechanism shine.

Tuesday, June 1, 2021
 
Rocket
answered 7 Months ago
90

I didn't find any specific pattern either, so I simply added:

en:
  user_status:
    active:   Active
    pending:  Pending...
    archived: Archived

to an arbitrary .yml file. Then in my views:

I18n.t :"user_status.#{user.status}"
Saturday, June 12, 2021
 
Lloydworth
answered 6 Months ago
81

This has to do with Rails 4 enabling additional security protocols by default: http://weblog.rubyonrails.org/2013/2/25/Rails-4-0-beta1/

The setting that breaks iFrames on remote sites is X-Frame-Options. By default, this is set to SAMEORIGIN, which prevents the content from being loading cross domain:

config.action_dispatch.default_headers = {
    'X-Frame-Options' => 'SAMEORIGIN'
}

You can read about the new default headers here: http://edgeguides.rubyonrails.org/security.html#default-headers

In order to allow the iFrame to work cross domain, you can change the default headers to allow X-Frame across domain.

config.action_dispatch.default_headers = {
    'X-Frame-Options' => 'ALLOWALL'
}
Monday, June 28, 2021
 
lewiguez
answered 6 Months ago
57

Your @font-face declaration is very close, you are just missing the /assets prefix within the url declaration.

@font-face {
    font-family: 'HDVPeace';
    src: url('/assets/HDV_Peace.eot');
    src: url('/assets/HDV_Peace.eot?iefix') format('eot'),
         url('/assets/HDV_Peace.woff') format('woff'),
         url('/assets/HDV_Peace.ttf') format('truetype'),
         url('/assets/HDV_Peace.svg#webfont') format('svg');
}

Anything that has been added to assets.paths is available directly under the /assets path in both development and production. You only need the asset path modification line within application.rb, doing it again in development.rb and production.rb is just redundant.

Additionally, all of the font formats are essentially binary. There is no need to pre-compile them, so you can safely remove the assets.precompile addition.

Wednesday, July 28, 2021
 
Skipper
answered 5 Months ago
89

The MongoDB solution from the linked question would be:

db.models.find({ $where: '/^124/.test(this.number)' })

Things that you hand to find map pretty much one-to-one to Mongoid:

where(:$where => "/^#{numero.to_i}/.test(this.number)")

The to_i call should make string interpolation okay for this limited case.

Keep in mind that this is a pretty horrific thing to do to your database: it can't use indexes, it will scan every single document in the collection, ...

You might be better off using a string field so that you can do normal regex matching. I'm pretty sure MongoDB will be able to use an index if you anchor your regex at the beginning too. If you really need it to be a number inside the database then you could always store it as both an Integer and a String field:

field :number,   :type => Integer
field :number_s, :type => String

and then have some hooks to keep :number_s up to date as :number changes. If you did this, your pattern matching scope would look at :number_s. Precomputing and duplicating data like this is pretty common with MongoDB so you shouldn't feel bad about it.

Saturday, August 21, 2021
 
MAC
answered 4 Months ago
MAC
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share