Rails 3.1 Limit User Created Objects

Rails 3.1 limit user created objects

Try something like this:

class User < ActiveRecord::Base
has_many :things
end

class Things <ActiveRecord::Base
belongs_to :user
validate :thing_count_within_limit, :on => :create

def thing_count_within_limit
if self.user.things(:reload).count >= 5
errors.add(:base, "Exceeded thing limit")
end
end
end

Edit: updated for Rails 3

RoR 3 Limiting users to 2 posts per day

Try this:

class User
has_many :posts do

def today
where(:created_at => (Time.zone.now.beginning_of_day..Time.zone.now))
end

def this_week
where(:created_at => (Time.zone.now.beginning_of_week..Time.zone.now))
end
end
end


class Post
belongs_to :user

validate :user_quota, :on => :create

private
def user_quota
if user.posts.today.count >= 2
errors.add(:base, "Exceeds daily limit")
elsif user.posts.this_week.count >= 5
errors.add(:base, "Exceeds weekly limit")
end
end

end

Ruby on Rails - Limit a user to a set number of database entries

You could do something like this:

class User < ActiveRecord::Base
has_many :domains
has_many :posts, through: :domains

def post_limit
roles.first.posts.count
end
end

class Domain < ActiveRecord::Base
belongs_to :user
has_many :posts
end

class Post < ActiveRecord::Base
belongs_to :domain
delegate :user, to: :domain
validate :posts_count_within_limit, on: :create

def posts_count_within_limit
if self.user.posts(:reload).count >= self.user.post_limit # self is optional
errors.add(:base, 'Exceeded posts limit')
end
end
end

Based on this answer.

Ruby on Rails: Limit user to endorse(comment) 3 other users a month

I actually found a reason.

It should look like this in the user model:

has_many :endorsing, through: :active_endorsements, source: :endorsed do
def this_month
where(:created_at => (Time.zone.now.beginning_of_month..Time.zone.now))
end
end

I was missing the do..end at the other post and placed the method at the end of the model. It seems to work now, produces an error

ArgumentError (First argument in form cannot contain nil or be empty):
app/views/shared/_unendorse.html.erb:1:in `_app_views_shared__unendorse_html_erb__1506472371249770260_70025812987440'
app/views/endorsements/create.js.erb:1:in `_app_views_endorsements_create_js_erb__2132303159922640595_70025812908380'
app/controllers/endorsements_controller.rb:8:in `create'

In the server log. I belive thats a valid error (already got 3 endorsed users) - but how can i display it on the website? So it looks like in the method

"Exceeded endorse limit (3) this month"

instead of what the error produces?

Edit:

I've managed to solve the error displaying correctly :)

It boiled down to have this method in my endorsement model:

  def endorsement_count_within_limit?
if endorser.endorsing.where(:created_at => (Time.zone.now.beginning_of_month..Time.zone.now)).count >= 3
errors.add(:base, "Exceeded endorse limit (3) this month")
end
end

and having my endorse partial that render the correct form depending if user is endorsing other user or not:

<%= form_for(current_user.active_endorsements.build, remote: true) do |f| %>
<% if f.object.endorsement_count_within_limit? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(f.object.errors.count, "error") %>.
</div>
<ul>
<% f.object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% else %>
<div><%= hidden_field_tag :endorsed_id, @user.id %></div>
<%= f.submit "Endorse", class: "btn btn-primary" %>
<%= f.text_field :comment, class: 'form-control' %>
<% end %>
<% end %>

Set has_many or has_one dynamically according to object own attributes

My first thought would be to use single-table inheritance, since Orphan is a specific kind of child with different behaviors.

When deciding whether this is the right route, I found this post really helpful.

If you chose use STI, you'd end up with something like...

class Child < ActiveRecord::Base
end

class Orphan < Child
has_one :parent
end

class StereotypicalFamilyUnit < Child
has_many :parents
end

Rails will also assume and expect that you have a "type" string column in the Child table. When you call Orphan.new, it will create a child of type "Orphan." And if you do "Orphan.first" it's basically doing Child.where(type: "Orphan").first behind the scenes.

Another option (which I eventually opted for in an app I'm building in lieu of STI), would be to have a boolean as you suggested and use scopes, which might look like:

class Child < ActiveRecord::Base
has_many :parents

scope :orphan, -> { where(orphan: true) }
end

Which lets you instead call Child.orphan.new or Child.orphan.first, and do different things in views/controllers when orphan is true. You could then also follow the advice in this prior post to create a custom validation for orphans.

Rails: `includes` a `has_many` relation with `limit`

There is a note tucked away in the associations documentation under "Eager loading of associations":

If you eager load an association with a specified :limit option, it will be ignored, returning all the associated objects.

So, it is behaving as documented even though that might not be the intuitive behaviour.

The work around is to not eager load the limited associated and to access separately afterwards. As you point out that's not ideal but it is almost certainly preferable to loading all of the associated objects without a limit.



Related Topics



Leave a reply



Submit